]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq/0060-dhcp-set-outbound-interface-via-cmsg-in-unicast-repl.patch
dnsmasq: Import patches from upstream
[ipfire-2.x.git] / src / patches / dnsmasq / 0060-dhcp-set-outbound-interface-via-cmsg-in-unicast-repl.patch
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
4 Subject: [PATCH 060/113] dhcp: set outbound interface via cmsg in unicast
5 reply
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