]>
Commit | Line | Data |
---|---|---|
c6ce1e7e MT |
1 | From 65c721200023ef0023114459a8d12f8b0a24cfd8 Mon Sep 17 00:00:00 2001 |
2 | From: Lung-Pin Chang <changlp@cs.nctu.edu.tw> | |
3 | Date: Thu, 19 Mar 2015 23:22:21 +0000 | |
697b4f04 MT |
4 | Subject: [PATCH 060/113] dhcp: set outbound interface via cmsg in unicast |
5 | reply | |
c6ce1e7e MT |
6 | |
7 | If multiple routes to the same network exist, Linux blindly picks | |
8 | the first interface (route) based on destination address, which might not be | |
9 | the one we're actually offering leases. Rather than relying on this, | |
10 | always set the interface for outgoing unicast DHCP packets. | |
11 | --- | |
12 | src/dhcp.c | 45 +++++++++++++++++++++++++-------------------- | |
13 | 1 file changed, 25 insertions(+), 20 deletions(-) | |
14 | ||
15 | diff --git a/src/dhcp.c b/src/dhcp.c | |
16 | index 5c3089ab94ff..f1f43f8d8f90 100644 | |
17 | --- a/src/dhcp.c | |
18 | +++ b/src/dhcp.c | |
19 | @@ -376,10 +376,9 @@ void dhcp_packet(time_t now, int pxe_fd) | |
20 | } | |
21 | } | |
22 | #if defined(HAVE_LINUX_NETWORK) | |
23 | - else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 || | |
24 | - mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0) | |
25 | + else | |
26 | { | |
27 | - /* broadcast to 255.255.255.255 (or mac address invalid) */ | |
28 | + /* fill cmsg for outbound interface (both broadcast & unicast) */ | |
29 | struct in_pktinfo *pkt; | |
30 | msg.msg_control = control_u.control; | |
31 | msg.msg_controllen = sizeof(control_u); | |
32 | @@ -389,23 +388,29 @@ void dhcp_packet(time_t now, int pxe_fd) | |
33 | pkt->ipi_spec_dst.s_addr = 0; | |
34 | msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); | |
35 | cmptr->cmsg_level = IPPROTO_IP; | |
36 | - cmptr->cmsg_type = IP_PKTINFO; | |
37 | - dest.sin_addr.s_addr = INADDR_BROADCAST; | |
38 | - dest.sin_port = htons(daemon->dhcp_client_port); | |
39 | - } | |
40 | - else | |
41 | - { | |
42 | - /* unicast to unconfigured client. Inject mac address direct into ARP cache. | |
43 | - struct sockaddr limits size to 14 bytes. */ | |
44 | - dest.sin_addr = mess->yiaddr; | |
45 | - dest.sin_port = htons(daemon->dhcp_client_port); | |
46 | - memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in)); | |
47 | - arp_req.arp_ha.sa_family = mess->htype; | |
48 | - memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen); | |
49 | - /* interface name already copied in */ | |
50 | - arp_req.arp_flags = ATF_COM; | |
51 | - if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1) | |
52 | - my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno)); | |
53 | + cmptr->cmsg_type = IP_PKTINFO; | |
54 | + | |
55 | + if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 || | |
56 | + mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0) | |
57 | + { | |
58 | + /* broadcast to 255.255.255.255 (or mac address invalid) */ | |
59 | + dest.sin_addr.s_addr = INADDR_BROADCAST; | |
60 | + dest.sin_port = htons(daemon->dhcp_client_port); | |
61 | + } | |
62 | + else | |
63 | + { | |
64 | + /* unicast to unconfigured client. Inject mac address direct into ARP cache. | |
65 | + struct sockaddr limits size to 14 bytes. */ | |
66 | + dest.sin_addr = mess->yiaddr; | |
67 | + dest.sin_port = htons(daemon->dhcp_client_port); | |
68 | + memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in)); | |
69 | + arp_req.arp_ha.sa_family = mess->htype; | |
70 | + memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen); | |
71 | + /* interface name already copied in */ | |
72 | + arp_req.arp_flags = ATF_COM; | |
73 | + if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1) | |
74 | + my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno)); | |
75 | + } | |
76 | } | |
77 | #elif defined(HAVE_SOLARIS_NETWORK) | |
78 | else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER) | |
79 | -- | |
80 | 2.1.0 | |
81 |