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