1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is free software; you can redistribute it and/or modify 4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat it under the terms of the GNU General Public License as published by 5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the Free Software Foundation; version 2 dated June, 1991, or 6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (at your option) version 3 dated 29 June, 2007. 7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is distributed in the hope that it will be useful, 9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat but WITHOUT ANY WARRANTY; without even the implied warranty of 10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GNU General Public License for more details. 12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat You should have received a copy of the GNU General Public License 14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat along with this program. If not, see <http://www.gnu.org/licenses/>. 15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/ 16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include "dnsmasq.h" 18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 19ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK) 20ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 21ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic struct iovec ifconf = { 22ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat .iov_base = NULL, 23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat .iov_len = 0 24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}; 25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic struct iovec ifreq = { 27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat .iov_base = NULL, 28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat .iov_len = 0 29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}; 30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)()) 32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *ptr; 34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ifreq *ifr; 35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ifconf ifc; 36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int fd, errsav, ret = 0; 37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int lastlen = 0; 38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat size_t len = 0; 39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) 41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while(1) 44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat len += 10*sizeof(struct ifreq); 46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!expand_buf(&ifconf, len)) 48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto err; 49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ifc.ifc_len = len; 51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ifc.ifc_buf = ifconf.iov_base; 52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) 54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno != EINVAL || lastlen != 0) 56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto err; 57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ifc.ifc_len == lastlen) 61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; /* got a big enough buffer now */ 62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lastlen = ifc.ifc_len; 63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (ptr = ifc.ifc_buf; ptr < (char *)(ifc.ifc_buf + ifc.ifc_len); ptr += len) 67ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 68ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* subsequent entries may not be aligned, so copy into 69ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat an aligned buffer to avoid nasty complaints about 70ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unaligned accesses. */ 71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat len = sizeof(struct ifreq); 73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ifr = (struct ifreq *)ptr; 76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru)) 77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat len = ifr->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru); 78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!expand_buf(&ifreq, len)) 81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto err; 82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ifr = (struct ifreq *)ifreq.iov_base; 84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(ifr, ptr, len); 85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ifr->ifr_addr.sa_family == AF_INET && ipv4_callback) 87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct in_addr addr, netmask, broadcast; 89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat broadcast.s_addr = 0; 90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr; 91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ioctl(fd, SIOCGIFNETMASK, ifr) == -1) 92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr; 94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ioctl(fd, SIOCGIFBRDADDR, ifr) != -1) 95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat broadcast = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr; 96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!((*ipv4_callback)(addr, 97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (int)if_nametoindex(ifr->ifr_name), 98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat netmask, broadcast, 99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat parm))) 100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto err; 101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (ifr->ifr_addr.sa_family == AF_INET6 && ipv6_callback) 104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct in6_addr *addr = &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr; 106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* voodoo to clear interface field in address */ 107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(daemon->options & OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr)) 108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr->s6_addr[2] = 0; 110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr->s6_addr[3] = 0; 111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!((*ipv6_callback)(addr, 113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (int)((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_scope_id, 114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (int)if_nametoindex(ifr->ifr_name), 115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat parm))) 116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat goto err; 117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = 1; 122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat err: 124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errsav = errno; 125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(fd); 126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = errsav; 127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ret; 129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) 134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include <net/bpf.h> 135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid init_bpf(void) 137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int i = 0; 139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (1) 141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* useful size which happens to be sufficient */ 143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (expand_buf(&ifreq, sizeof(struct ifreq))) 144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sprintf(ifreq.iov_base, "/dev/bpf%d", i++); 146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((daemon->dhcp_raw_fd = open(ifreq.iov_base, O_RDWR, 0)) != -1) 147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno != EBUSY) 150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("cannot create DHCP BPF socket: %s"), NULL, EC_BADNET); 151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid send_via_bpf(struct dhcp_packet *mess, size_t len, 155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct in_addr iface_addr, struct ifreq *ifr) 156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Hairy stuff, packet either has to go to the 158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat net broadcast or the destination can't reply to ARP yet, 159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat but we do know the physical address. 160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Build the packet by steam, and send directly, bypassing 161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the kernel IP stack */ 162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ether_header ether; 164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ip ip; 165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct udphdr { 166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat u16 uh_sport; /* source port */ 167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat u16 uh_dport; /* destination port */ 168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat u16 uh_ulen; /* udp length */ 169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat u16 uh_sum; /* udp checksum */ 170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } udp; 171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat u32 i, sum; 173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct iovec iov[4]; 174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Only know how to do ethernet on *BSD */ 176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (mess->htype != ARPHRD_ETHER || mess->hlen != ETHER_ADDR_LEN) 177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(MS_DHCP | LOG_WARNING, _("DHCP request for unsupported hardware type (%d) received on %s"), 179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat mess->htype, ifr->ifr_name); 180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ifr->ifr_addr.sa_family = AF_LINK; 184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ioctl(daemon->dhcpfd, SIOCGIFADDR, ifr) < 0) 185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return; 186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(ether.ether_shost, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN); 188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ether.ether_type = htons(ETHERTYPE_IP); 189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ntohs(mess->flags) & 0x8000) 191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(ether.ether_dhost, 255, ETHER_ADDR_LEN); 193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_dst.s_addr = INADDR_BROADCAST; 194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcpy(ether.ether_dhost, mess->chaddr, ETHER_ADDR_LEN); 198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_dst.s_addr = mess->yiaddr.s_addr; 199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_p = IPPROTO_UDP; 202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_src.s_addr = iface_addr.s_addr; 203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_len = htons(sizeof(struct ip) + 204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sizeof(struct udphdr) + 205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat len) ; 206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_hl = sizeof(struct ip) / 4; 207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_v = IPVERSION; 208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_tos = 0; 209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_id = htons(0); 210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_off = htons(0x4000); /* don't fragment */ 211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_ttl = IPDEFTTL; 212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_sum = 0; 213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++) 214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum += ((u16 *)&ip)[i]; 215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (sum>>16) 216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum = (sum & 0xffff) + (sum >> 16); 217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ip.ip_sum = (sum == 0xffff) ? sum : ~sum; 218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat udp.uh_sport = htons(daemon->dhcp_server_port); 220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat udp.uh_dport = htons(daemon->dhcp_client_port); 221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (len & 1) 222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((char *)mess)[len] = 0; /* for checksum, in case length is odd. */ 223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat udp.uh_sum = 0; 224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len); 225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum += htons(IPPROTO_UDP); 226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum += ip.ip_src.s_addr & 0xffff; 227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum += (ip.ip_src.s_addr >> 16) & 0xffff; 228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum += ip.ip_dst.s_addr & 0xffff; 229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum += (ip.ip_dst.s_addr >> 16) & 0xffff; 230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = 0; i < sizeof(struct udphdr)/2; i++) 231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum += ((u16 *)&udp)[i]; 232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (i = 0; i < (len + 1) / 2; i++) 233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum += ((u16 *)mess)[i]; 234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (sum>>16) 235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sum = (sum & 0xffff) + (sum >> 16); 236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat udp.uh_sum = (sum == 0xffff) ? sum : ~sum; 237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ioctl(daemon->dhcp_raw_fd, BIOCSETIF, ifr); 239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iov[0].iov_base = ðer; 241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iov[0].iov_len = sizeof(ether); 242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iov[1].iov_base = &ip; 243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iov[1].iov_len = sizeof(ip); 244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iov[2].iov_base = &udp; 245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iov[2].iov_len = sizeof(udp); 246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iov[3].iov_base = mess; 247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iov[3].iov_len = len; 248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send()); 250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 255