version 1.1.1.2, 2014/06/15 16:31:38
|
version 1.1.1.3, 2016/11/02 09:57:01
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley |
|
|
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
Line 146 void dhcp_packet(time_t now, int pxe_fd)
|
Line 146 void dhcp_packet(time_t now, int pxe_fd)
|
struct iovec iov; |
struct iovec iov; |
ssize_t sz; |
ssize_t sz; |
int iface_index = 0, unicast_dest = 0, is_inform = 0; |
int iface_index = 0, unicast_dest = 0, is_inform = 0; |
|
int rcvd_iface_index; |
struct in_addr iface_addr; |
struct in_addr iface_addr; |
struct iface_param parm; |
struct iface_param parm; |
#ifdef HAVE_LINUX_NETWORK |
#ifdef HAVE_LINUX_NETWORK |
Line 225 void dhcp_packet(time_t now, int pxe_fd)
|
Line 226 void dhcp_packet(time_t now, int pxe_fd)
|
strncpy(arp_req.arp_dev, ifr.ifr_name, 16); |
strncpy(arp_req.arp_dev, ifr.ifr_name, 16); |
#endif |
#endif |
|
|
/* One form of bridging on BSD has the property that packets | /* If the interface on which the DHCP request was received is an |
can be recieved on bridge interfaces which do not have an IP address. | alias of some other interface (as specified by the |
We allow these to be treated as aliases of another interface which does have | --bridge-interface option), change ifr.ifr_name so that we look |
an IP address with --dhcp-bridge=interface,alias,alias */ | for DHCP contexts associated with the aliased interface instead |
| of with the aliasing one. */ |
| rcvd_iface_index = iface_index; |
for (bridge = daemon->bridges; bridge; bridge = bridge->next) |
for (bridge = daemon->bridges; bridge; bridge = bridge->next) |
{ |
{ |
for (alias = bridge->alias; alias; alias = alias->next) |
for (alias = bridge->alias; alias; alias = alias->next) |
if (strncmp(ifr.ifr_name, alias->iface, IF_NAMESIZE) == 0) | if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE)) |
{ |
{ |
if (!(iface_index = if_nametoindex(bridge->iface))) |
if (!(iface_index = if_nametoindex(bridge->iface))) |
{ |
{ |
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr.ifr_name); | my_syslog(MS_DHCP | LOG_WARNING, |
| _("unknown interface %s in bridge-interface"), |
| bridge->iface); |
return; |
return; |
} |
} |
else |
else |
Line 376 void dhcp_packet(time_t now, int pxe_fd)
|
Line 381 void dhcp_packet(time_t now, int pxe_fd)
|
} |
} |
} |
} |
#if defined(HAVE_LINUX_NETWORK) |
#if defined(HAVE_LINUX_NETWORK) |
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 || | else |
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0) | |
{ |
{ |
/* broadcast to 255.255.255.255 (or mac address invalid) */ | /* fill cmsg for outbound interface (both broadcast & unicast) */ |
struct in_pktinfo *pkt; |
struct in_pktinfo *pkt; |
msg.msg_control = control_u.control; |
msg.msg_control = control_u.control; |
msg.msg_controllen = sizeof(control_u); |
msg.msg_controllen = sizeof(control_u); |
cmptr = CMSG_FIRSTHDR(&msg); |
cmptr = CMSG_FIRSTHDR(&msg); |
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr); |
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr); |
pkt->ipi_ifindex = iface_index; | pkt->ipi_ifindex = rcvd_iface_index; |
pkt->ipi_spec_dst.s_addr = 0; |
pkt->ipi_spec_dst.s_addr = 0; |
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); |
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); |
cmptr->cmsg_level = IPPROTO_IP; |
cmptr->cmsg_level = IPPROTO_IP; |
cmptr->cmsg_type = IP_PKTINFO; | cmptr->cmsg_type = IP_PKTINFO; |
dest.sin_addr.s_addr = INADDR_BROADCAST; | |
dest.sin_port = htons(daemon->dhcp_client_port); | if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 || |
| mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0) |
| { |
| /* broadcast to 255.255.255.255 (or mac address invalid) */ |
| dest.sin_addr.s_addr = INADDR_BROADCAST; |
| dest.sin_port = htons(daemon->dhcp_client_port); |
| } |
| else |
| { |
| /* unicast to unconfigured client. Inject mac address direct into ARP cache. |
| struct sockaddr limits size to 14 bytes. */ |
| dest.sin_addr = mess->yiaddr; |
| dest.sin_port = htons(daemon->dhcp_client_port); |
| memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in)); |
| arp_req.arp_ha.sa_family = mess->htype; |
| memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen); |
| /* interface name already copied in */ |
| arp_req.arp_flags = ATF_COM; |
| if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1) |
| my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno)); |
| } |
} |
} |
else |
|
{ |
|
/* unicast to unconfigured client. Inject mac address direct into ARP cache. |
|
struct sockaddr limits size to 14 bytes. */ |
|
dest.sin_addr = mess->yiaddr; |
|
dest.sin_port = htons(daemon->dhcp_client_port); |
|
memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in)); |
|
arp_req.arp_ha.sa_family = mess->htype; |
|
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen); |
|
/* interface name already copied in */ |
|
arp_req.arp_flags = ATF_COM; |
|
ioctl(daemon->dhcpfd, SIOCSARP, &arp_req); |
|
} |
|
#elif defined(HAVE_SOLARIS_NETWORK) |
#elif defined(HAVE_SOLARIS_NETWORK) |
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER) |
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER) |
{ |
{ |
Line 442 void dhcp_packet(time_t now, int pxe_fd)
|
Line 453 void dhcp_packet(time_t now, int pxe_fd)
|
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index)); |
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index)); |
#endif |
#endif |
|
|
while(sendmsg(fd, &msg, 0) == -1 && retry_send()); | while(retry_send(sendmsg(fd, &msg, 0))); |
| |
| /* This can fail when, eg, iptables DROPS destination 255.255.255.255 */ |
| if (errno != 0) |
| my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"), |
| inet_ntoa(dest.sin_addr), strerror(errno)); |
} |
} |
| |
/* check against secondary interface addresses */ |
/* check against secondary interface addresses */ |
static int check_listen_addrs(struct in_addr local, int if_index, char *label, |
static int check_listen_addrs(struct in_addr local, int if_index, char *label, |
struct in_addr netmask, struct in_addr broadcast, void *vparam) |
struct in_addr netmask, struct in_addr broadcast, void *vparam) |
Line 637 int address_allocate(struct dhcp_context *context,
|
Line 653 int address_allocate(struct dhcp_context *context,
|
/* hash hwaddr: use the SDBM hashing algorithm. Seems to give good |
/* hash hwaddr: use the SDBM hashing algorithm. Seems to give good |
dispersal even with similarly-valued "strings". */ |
dispersal even with similarly-valued "strings". */ |
for (j = 0, i = 0; i < hw_len; i++) |
for (j = 0, i = 0; i < hw_len; i++) |
j += hwaddr[i] + (j << 6) + (j << 16) - j; | j = hwaddr[i] + (j << 6) + (j << 16) - j; |
|
|
for (pass = 0; pass <= 1; pass++) |
for (pass = 0; pass <= 1; pass++) |
for (c = context; c; c = c->current) |
for (c = context; c; c = c->current) |