1 /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
22 #include <sys/param.h>
23 #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
24 #include <sys/sysctl.h>
27 #include <net/route.h>
28 #include <net/if_dl.h>
29 #include <netinet/if_ether.h>
30 #if defined(__FreeBSD__)
31 # include <net/if_var.h>
33 #include <netinet/in_var.h>
35 # include <netinet6/in6_var.h>
40 ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
42 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
45 #ifdef HAVE_BSD_NETWORK
46 static int del_family
= 0;
47 static struct all_addr del_addr
;
50 #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
52 int arp_enumerate(void *parm
, int (*callback
)())
57 struct rt_msghdr
*rtm
;
58 struct sockaddr_inarp
*sin2
;
59 struct sockaddr_dl
*sdl
;
70 mib
[4] = NET_RT_FLAGS
;
76 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) == -1 || needed
== 0)
81 if (!expand_buf(&buff
, needed
))
83 if ((rc
= sysctl(mib
, 6, buff
.iov_base
, &needed
, NULL
, 0)) == 0 ||
91 for (next
= buff
.iov_base
; next
< (char *)buff
.iov_base
+ needed
; next
+= rtm
->rtm_msglen
)
93 rtm
= (struct rt_msghdr
*)next
;
94 sin2
= (struct sockaddr_inarp
*)(rtm
+ 1);
95 sdl
= (struct sockaddr_dl
*)((char *)sin2
+ SA_SIZE(sin2
));
96 if (!(*callback
)(AF_INET
, &sin2
->sin_addr
, LLADDR(sdl
), sdl
->sdl_alen
, parm
))
102 #endif /* defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) */
105 int iface_enumerate(int family
, void *parm
, int (*callback
)())
107 struct ifaddrs
*head
, *addrs
;
108 int errsav
, fd
= -1, ret
= 0;
110 if (family
== AF_UNSPEC
)
111 #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
112 return arp_enumerate(parm
, callback
);
114 return 0; /* need code for Solaris and MacOS*/
117 /* AF_LINK doesn't exist in Linux, so we can't use it in our API */
118 if (family
== AF_LOCAL
)
121 if (getifaddrs(&head
) == -1)
124 #if defined(HAVE_BSD_NETWORK) && defined(HAVE_IPV6)
125 if (family
== AF_INET6
)
126 fd
= socket(PF_INET6
, SOCK_DGRAM
, 0);
129 for (addrs
= head
; addrs
; addrs
= addrs
->ifa_next
)
131 if (addrs
->ifa_addr
->sa_family
== family
)
133 int iface_index
= if_nametoindex(addrs
->ifa_name
);
135 if (iface_index
== 0 || !addrs
->ifa_addr
||
136 (!addrs
->ifa_netmask
&& family
!= AF_LINK
))
139 if (family
== AF_INET
)
141 struct in_addr addr
, netmask
, broadcast
;
142 addr
= ((struct sockaddr_in
*) addrs
->ifa_addr
)->sin_addr
;
143 #ifdef HAVE_BSD_NETWORK
144 if (del_family
== AF_INET
&& del_addr
.addr
.addr4
.s_addr
== addr
.s_addr
)
147 netmask
= ((struct sockaddr_in
*) addrs
->ifa_netmask
)->sin_addr
;
148 if (addrs
->ifa_broadaddr
)
149 broadcast
= ((struct sockaddr_in
*) addrs
->ifa_broadaddr
)->sin_addr
;
151 broadcast
.s_addr
= 0;
152 if (!((*callback
)(addr
, iface_index
, NULL
, netmask
, broadcast
, parm
)))
156 else if (family
== AF_INET6
)
158 struct in6_addr
*addr
= &((struct sockaddr_in6
*) addrs
->ifa_addr
)->sin6_addr
;
159 unsigned char *netmask
= (unsigned char *) &((struct sockaddr_in6
*) addrs
->ifa_netmask
)->sin6_addr
;
160 int scope_id
= ((struct sockaddr_in6
*) addrs
->ifa_addr
)->sin6_scope_id
;
161 int i
, j
, prefix
= 0;
162 u32 valid
= 0xffffffff, preferred
= 0xffffffff;
164 #ifdef HAVE_BSD_NETWORK
165 if (del_family
== AF_INET6
&& IN6_ARE_ADDR_EQUAL(&del_addr
.addr
.addr6
, addr
))
168 #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
169 struct in6_ifreq ifr6
;
171 memset(&ifr6
, 0, sizeof(ifr6
));
172 strncpy(ifr6
.ifr_name
, addrs
->ifa_name
, sizeof(ifr6
.ifr_name
));
174 ifr6
.ifr_addr
= *((struct sockaddr_in6
*) addrs
->ifa_addr
);
175 if (fd
!= -1 && ioctl(fd
, SIOCGIFAFLAG_IN6
, &ifr6
) != -1)
177 if (ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_TENTATIVE
)
178 flags
|= IFACE_TENTATIVE
;
180 if (ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_DEPRECATED
)
181 flags
|= IFACE_DEPRECATED
;
183 #ifdef IN6_IFF_TEMPORARY
184 if (!(ifr6
.ifr_ifru
.ifru_flags6
& (IN6_IFF_AUTOCONF
| IN6_IFF_TEMPORARY
)))
185 flags
|= IFACE_PERMANENT
;
188 #ifdef IN6_IFF_PRIVACY
189 if (!(ifr6
.ifr_ifru
.ifru_flags6
& (IN6_IFF_AUTOCONF
| IN6_IFF_PRIVACY
)))
190 flags
|= IFACE_PERMANENT
;
194 ifr6
.ifr_addr
= *((struct sockaddr_in6
*) addrs
->ifa_addr
);
195 if (fd
!= -1 && ioctl(fd
, SIOCGIFALIFETIME_IN6
, &ifr6
) != -1)
197 valid
= ifr6
.ifr_ifru
.ifru_lifetime
.ia6t_vltime
;
198 preferred
= ifr6
.ifr_ifru
.ifru_lifetime
.ia6t_pltime
;
202 for (i
= 0; i
< IN6ADDRSZ
; i
++, prefix
+= 8)
203 if (netmask
[i
] != 0xff)
206 if (i
!= IN6ADDRSZ
&& netmask
[i
])
207 for (j
= 7; j
> 0; j
--, prefix
++)
208 if ((netmask
[i
] & (1 << j
)) == 0)
211 /* voodoo to clear interface field in address */
212 if (!option_bool(OPT_NOWILD
) && IN6_IS_ADDR_LINKLOCAL(addr
))
214 addr
->s6_addr
[2] = 0;
215 addr
->s6_addr
[3] = 0;
218 if (!((*callback
)(addr
, prefix
, scope_id
, iface_index
, flags
,
219 (int) preferred
, (int)valid
, parm
)))
222 #endif /* HAVE_IPV6 */
225 else if (family
== AF_LINK
)
227 /* Assume ethernet again here */
228 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*) addrs
->ifa_addr
;
229 if (sdl
->sdl_alen
!= 0 &&
230 !((*callback
)(iface_index
, ARPHRD_ETHER
, LLADDR(sdl
), sdl
->sdl_alen
, parm
)))
248 #endif /* defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK) */
251 #if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)
260 sprintf(daemon
->dhcp_buff
, "/dev/bpf%d", i
++);
261 if ((daemon
->dhcp_raw_fd
= open(daemon
->dhcp_buff
, O_RDWR
, 0)) != -1)
265 die(_("cannot create DHCP BPF socket: %s"), NULL
, EC_BADNET
);
269 void send_via_bpf(struct dhcp_packet
*mess
, size_t len
,
270 struct in_addr iface_addr
, struct ifreq
*ifr
)
272 /* Hairy stuff, packet either has to go to the
273 net broadcast or the destination can't reply to ARP yet,
274 but we do know the physical address.
275 Build the packet by steam, and send directly, bypassing
276 the kernel IP stack */
278 struct ether_header ether
;
281 u16 uh_sport
; /* source port */
282 u16 uh_dport
; /* destination port */
283 u16 uh_ulen
; /* udp length */
284 u16 uh_sum
; /* udp checksum */
290 /* Only know how to do ethernet on *BSD */
291 if (mess
->htype
!= ARPHRD_ETHER
|| mess
->hlen
!= ETHER_ADDR_LEN
)
293 my_syslog(MS_DHCP
| LOG_WARNING
, _("DHCP request for unsupported hardware type (%d) received on %s"),
294 mess
->htype
, ifr
->ifr_name
);
298 ifr
->ifr_addr
.sa_family
= AF_LINK
;
299 if (ioctl(daemon
->dhcpfd
, SIOCGIFADDR
, ifr
) < 0)
302 memcpy(ether
.ether_shost
, LLADDR((struct sockaddr_dl
*)&ifr
->ifr_addr
), ETHER_ADDR_LEN
);
303 ether
.ether_type
= htons(ETHERTYPE_IP
);
305 if (ntohs(mess
->flags
) & 0x8000)
307 memset(ether
.ether_dhost
, 255, ETHER_ADDR_LEN
);
308 ip
.ip_dst
.s_addr
= INADDR_BROADCAST
;
312 memcpy(ether
.ether_dhost
, mess
->chaddr
, ETHER_ADDR_LEN
);
313 ip
.ip_dst
.s_addr
= mess
->yiaddr
.s_addr
;
316 ip
.ip_p
= IPPROTO_UDP
;
317 ip
.ip_src
.s_addr
= iface_addr
.s_addr
;
318 ip
.ip_len
= htons(sizeof(struct ip
) +
319 sizeof(struct udphdr
) +
321 ip
.ip_hl
= sizeof(struct ip
) / 4;
325 ip
.ip_off
= htons(0x4000); /* don't fragment */
326 ip
.ip_ttl
= IPDEFTTL
;
328 for (sum
= 0, i
= 0; i
< sizeof(struct ip
) / 2; i
++)
329 sum
+= ((u16
*)&ip
)[i
];
331 sum
= (sum
& 0xffff) + (sum
>> 16);
332 ip
.ip_sum
= (sum
== 0xffff) ? sum
: ~sum
;
334 udp
.uh_sport
= htons(daemon
->dhcp_server_port
);
335 udp
.uh_dport
= htons(daemon
->dhcp_client_port
);
337 ((char *)mess
)[len
] = 0; /* for checksum, in case length is odd. */
339 udp
.uh_ulen
= sum
= htons(sizeof(struct udphdr
) + len
);
340 sum
+= htons(IPPROTO_UDP
);
341 sum
+= ip
.ip_src
.s_addr
& 0xffff;
342 sum
+= (ip
.ip_src
.s_addr
>> 16) & 0xffff;
343 sum
+= ip
.ip_dst
.s_addr
& 0xffff;
344 sum
+= (ip
.ip_dst
.s_addr
>> 16) & 0xffff;
345 for (i
= 0; i
< sizeof(struct udphdr
)/2; i
++)
346 sum
+= ((u16
*)&udp
)[i
];
347 for (i
= 0; i
< (len
+ 1) / 2; i
++)
348 sum
+= ((u16
*)mess
)[i
];
350 sum
= (sum
& 0xffff) + (sum
>> 16);
351 udp
.uh_sum
= (sum
== 0xffff) ? sum
: ~sum
;
353 ioctl(daemon
->dhcp_raw_fd
, BIOCSETIF
, ifr
);
355 iov
[0].iov_base
= ðer
;
356 iov
[0].iov_len
= sizeof(ether
);
357 iov
[1].iov_base
= &ip
;
358 iov
[1].iov_len
= sizeof(ip
);
359 iov
[2].iov_base
= &udp
;
360 iov
[2].iov_len
= sizeof(udp
);
361 iov
[3].iov_base
= mess
;
362 iov
[3].iov_len
= len
;
364 while (retry_send(writev(daemon
->dhcp_raw_fd
, iov
, 4)));
367 #endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
370 #ifdef HAVE_BSD_NETWORK
372 void route_init(void)
374 /* AF_UNSPEC: all addr families */
375 daemon
->routefd
= socket(PF_ROUTE
, SOCK_RAW
, AF_UNSPEC
);
377 if (daemon
->routefd
== -1 || !fix_fd(daemon
->routefd
))
378 die(_("cannot create PF_ROUTE socket: %s"), NULL
, EC_BADNET
);
381 void route_sock(void)
383 struct if_msghdr
*msg
;
384 int rc
= recv(daemon
->routefd
, daemon
->packet
, daemon
->packet_buff_sz
, 0);
389 msg
= (struct if_msghdr
*)daemon
->packet
;
391 if (rc
< msg
->ifm_msglen
)
394 if (msg
->ifm_version
!= RTM_VERSION
)
396 static int warned
= 0;
399 my_syslog(LOG_WARNING
, _("Unknown protocol version from route socket"));
403 else if (msg
->ifm_type
== RTM_NEWADDR
)
406 queue_event(EVENT_NEWADDR
);
408 else if (msg
->ifm_type
== RTM_DELADDR
)
410 /* There's a race in the kernel, such that if we run iface_enumerate() immediately
411 we get a DELADDR event, the deleted address still appears. Here we store the deleted address
412 in a static variable, and omit it from the set returned by iface_enumerate() */
413 int mask
= ((struct ifa_msghdr
*)msg
)->ifam_addrs
;
414 int maskvec
[] = { RTA_DST
, RTA_GATEWAY
, RTA_NETMASK
, RTA_GENMASK
,
415 RTA_IFP
, RTA_IFA
, RTA_AUTHOR
, RTA_BRD
};
419 for (i
= 0, of
= sizeof(struct ifa_msghdr
); of
< rc
&& i
< sizeof(maskvec
)/sizeof(maskvec
[0]); i
++)
420 if (mask
& maskvec
[i
])
422 struct sockaddr
*sa
= (struct sockaddr
*)((char *)msg
+ of
);
423 size_t diff
= (sa
->sa_len
!= 0) ? sa
->sa_len
: sizeof(long);
425 if (maskvec
[i
] == RTA_IFA
)
427 del_family
= sa
->sa_family
;
428 if (del_family
== AF_INET
)
429 del_addr
.addr
.addr4
= ((struct sockaddr_in
*)sa
)->sin_addr
;
431 else if (del_family
== AF_INET6
)
432 del_addr
.addr
.addr6
= ((struct sockaddr_in6
*)sa
)->sin6_addr
;
439 /* round up as needed */
440 if (diff
& (sizeof(long) - 1))
441 of
+= sizeof(long) - (diff
& (sizeof(long) - 1));
444 queue_event(EVENT_NEWADDR
);
448 #endif /* HAVE_BSD_NETWORK */