1 |
diff -up dhcp-4.2.2b1/common/bpf.c.xen dhcp-4.2.2b1/common/bpf.c |
2 |
--- dhcp-4.2.2b1/common/bpf.c.xen 2009-11-20 02:48:59.000000000 +0100 |
3 |
+++ dhcp-4.2.2b1/common/bpf.c 2011-07-01 14:00:16.936959001 +0200 |
4 |
@@ -485,7 +485,7 @@ ssize_t receive_packet (interface, buf, |
5 |
offset = decode_udp_ip_header (interface, |
6 |
interface -> rbuf, |
7 |
interface -> rbuf_offset, |
8 |
- from, hdr.bh_caplen, &paylen); |
9 |
+ from, hdr.bh_caplen, &paylen, 0); |
10 |
|
11 |
/* If the IP or UDP checksum was bad, skip the packet... */ |
12 |
if (offset < 0) { |
13 |
diff -up dhcp-4.2.2b1/common/dlpi.c.xen dhcp-4.2.2b1/common/dlpi.c |
14 |
--- dhcp-4.2.2b1/common/dlpi.c.xen 2011-05-11 16:20:59.000000000 +0200 |
15 |
+++ dhcp-4.2.2b1/common/dlpi.c 2011-07-01 14:00:16.937958997 +0200 |
16 |
@@ -693,7 +693,7 @@ ssize_t receive_packet (interface, buf, |
17 |
length -= offset; |
18 |
#endif |
19 |
offset = decode_udp_ip_header (interface, dbuf, bufix, |
20 |
- from, length, &paylen); |
21 |
+ from, length, &paylen, 0); |
22 |
|
23 |
/* |
24 |
* If the IP or UDP checksum was bad, skip the packet... |
25 |
diff -up dhcp-4.2.2b1/common/lpf.c.xen dhcp-4.2.2b1/common/lpf.c |
26 |
--- dhcp-4.2.2b1/common/lpf.c.xen 2011-05-10 16:38:58.000000000 +0200 |
27 |
+++ dhcp-4.2.2b1/common/lpf.c 2011-07-01 14:11:24.725748028 +0200 |
28 |
@@ -29,19 +29,33 @@ |
29 |
#include "dhcpd.h" |
30 |
#if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE) |
31 |
#include <sys/ioctl.h> |
32 |
+#include <sys/socket.h> |
33 |
#include <sys/uio.h> |
34 |
#include <errno.h> |
35 |
|
36 |
#include <asm/types.h> |
37 |
#include <linux/filter.h> |
38 |
#include <linux/if_ether.h> |
39 |
+#include <linux/if_packet.h> |
40 |
#include <netinet/in_systm.h> |
41 |
-#include <net/if_packet.h> |
42 |
#include "includes/netinet/ip.h" |
43 |
#include "includes/netinet/udp.h" |
44 |
#include "includes/netinet/if_ether.h" |
45 |
#include <net/if.h> |
46 |
|
47 |
+#ifndef PACKET_AUXDATA |
48 |
+#define PACKET_AUXDATA 8 |
49 |
+ |
50 |
+struct tpacket_auxdata |
51 |
+{ |
52 |
+ __u32 tp_status; |
53 |
+ __u32 tp_len; |
54 |
+ __u32 tp_snaplen; |
55 |
+ __u16 tp_mac; |
56 |
+ __u16 tp_net; |
57 |
+}; |
58 |
+#endif |
59 |
+ |
60 |
/* Reinitializes the specified interface after an address change. This |
61 |
is not required for packet-filter APIs. */ |
62 |
|
63 |
@@ -67,10 +81,14 @@ int if_register_lpf (info) |
64 |
struct interface_info *info; |
65 |
{ |
66 |
int sock; |
67 |
- struct sockaddr sa; |
68 |
+ union { |
69 |
+ struct sockaddr_ll ll; |
70 |
+ struct sockaddr common; |
71 |
+ } sa; |
72 |
+ struct ifreq ifr; |
73 |
|
74 |
/* Make an LPF socket. */ |
75 |
- if ((sock = socket(PF_PACKET, SOCK_PACKET, |
76 |
+ if ((sock = socket(PF_PACKET, SOCK_RAW, |
77 |
htons((short)ETH_P_ALL))) < 0) { |
78 |
if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || |
79 |
errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || |
80 |
@@ -85,11 +103,17 @@ int if_register_lpf (info) |
81 |
log_fatal ("Open a socket for LPF: %m"); |
82 |
} |
83 |
|
84 |
+ memset (&ifr, 0, sizeof ifr); |
85 |
+ strncpy (ifr.ifr_name, (const char *)info -> ifp, sizeof ifr.ifr_name); |
86 |
+ ifr.ifr_name[IFNAMSIZ-1] = '\0'; |
87 |
+ if (ioctl (sock, SIOCGIFINDEX, &ifr)) |
88 |
+ log_fatal ("Failed to get interface index: %m"); |
89 |
+ |
90 |
/* Bind to the interface name */ |
91 |
memset (&sa, 0, sizeof sa); |
92 |
- sa.sa_family = AF_PACKET; |
93 |
- strncpy (sa.sa_data, (const char *)info -> ifp, sizeof sa.sa_data); |
94 |
- if (bind (sock, &sa, sizeof sa)) { |
95 |
+ sa.ll.sll_family = AF_PACKET; |
96 |
+ sa.ll.sll_ifindex = ifr.ifr_ifindex; |
97 |
+ if (bind (sock, &sa.common, sizeof sa)) { |
98 |
if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || |
99 |
errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || |
100 |
errno == EAFNOSUPPORT || errno == EINVAL) { |
101 |
@@ -171,9 +195,18 @@ static void lpf_gen_filter_setup (struct |
102 |
void if_register_receive (info) |
103 |
struct interface_info *info; |
104 |
{ |
105 |
+ int val; |
106 |
+ |
107 |
/* Open a LPF device and hang it on this interface... */ |
108 |
info -> rfdesc = if_register_lpf (info); |
109 |
|
110 |
+ val = 1; |
111 |
+ if (setsockopt (info -> rfdesc, SOL_PACKET, PACKET_AUXDATA, &val, |
112 |
+ sizeof val) < 0) { |
113 |
+ if (errno != ENOPROTOOPT) |
114 |
+ log_fatal ("Failed to set auxiliary packet data: %m"); |
115 |
+ } |
116 |
+ |
117 |
#if defined (HAVE_TR_SUPPORT) |
118 |
if (info -> hw_address.hbuf [0] == HTYPE_IEEE802) |
119 |
lpf_tr_filter_setup (info); |
120 |
@@ -295,7 +328,6 @@ ssize_t send_packet (interface, packet, |
121 |
double hh [16]; |
122 |
double ih [1536 / sizeof (double)]; |
123 |
unsigned char *buf = (unsigned char *)ih; |
124 |
- struct sockaddr_pkt sa; |
125 |
int result; |
126 |
int fudge; |
127 |
|
128 |
@@ -316,17 +348,7 @@ ssize_t send_packet (interface, packet, |
129 |
(unsigned char *)raw, len); |
130 |
memcpy (buf + ibufp, raw, len); |
131 |
|
132 |
- /* For some reason, SOCK_PACKET sockets can't be connected, |
133 |
- so we have to do a sentdo every time. */ |
134 |
- memset (&sa, 0, sizeof sa); |
135 |
- sa.spkt_family = AF_PACKET; |
136 |
- strncpy ((char *)sa.spkt_device, |
137 |
- (const char *)interface -> ifp, sizeof sa.spkt_device); |
138 |
- sa.spkt_protocol = htons(ETH_P_IP); |
139 |
- |
140 |
- result = sendto (interface -> wfdesc, |
141 |
- buf + fudge, ibufp + len - fudge, 0, |
142 |
- (const struct sockaddr *)&sa, sizeof sa); |
143 |
+ result = write (interface -> wfdesc, buf + fudge, ibufp + len - fudge); |
144 |
if (result < 0) |
145 |
log_error ("send_packet: %m"); |
146 |
return result; |
147 |
@@ -343,14 +365,35 @@ ssize_t receive_packet (interface, buf, |
148 |
{ |
149 |
int length = 0; |
150 |
int offset = 0; |
151 |
+ int nocsum = 0; |
152 |
unsigned char ibuf [1536]; |
153 |
unsigned bufix = 0; |
154 |
unsigned paylen; |
155 |
+ unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; |
156 |
+ struct iovec iov = { |
157 |
+ .iov_base = ibuf, |
158 |
+ .iov_len = sizeof ibuf, |
159 |
+ }; |
160 |
+ struct msghdr msg = { |
161 |
+ .msg_iov = &iov, |
162 |
+ .msg_iovlen = 1, |
163 |
+ .msg_control = cmsgbuf, |
164 |
+ .msg_controllen = sizeof(cmsgbuf), |
165 |
+ }; |
166 |
+ struct cmsghdr *cmsg; |
167 |
|
168 |
- length = read (interface -> rfdesc, ibuf, sizeof ibuf); |
169 |
+ length = recvmsg (interface -> rfdesc, &msg, 0); |
170 |
if (length <= 0) |
171 |
return length; |
172 |
|
173 |
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { |
174 |
+ if (cmsg->cmsg_level == SOL_PACKET && |
175 |
+ cmsg->cmsg_type == PACKET_AUXDATA) { |
176 |
+ struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg); |
177 |
+ nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY; |
178 |
+ } |
179 |
+ } |
180 |
+ |
181 |
bufix = 0; |
182 |
/* Decode the physical header... */ |
183 |
offset = decode_hw_header (interface, ibuf, bufix, hfrom); |
184 |
@@ -367,7 +410,7 @@ ssize_t receive_packet (interface, buf, |
185 |
|
186 |
/* Decode the IP and UDP headers... */ |
187 |
offset = decode_udp_ip_header (interface, ibuf, bufix, from, |
188 |
- (unsigned)length, &paylen); |
189 |
+ (unsigned)length, &paylen, nocsum); |
190 |
|
191 |
/* If the IP or UDP checksum was bad, skip the packet... */ |
192 |
if (offset < 0) |
193 |
diff -up dhcp-4.2.2b1/common/nit.c.xen dhcp-4.2.2b1/common/nit.c |
194 |
--- dhcp-4.2.2b1/common/nit.c.xen 2009-11-20 02:49:01.000000000 +0100 |
195 |
+++ dhcp-4.2.2b1/common/nit.c 2011-07-01 14:00:16.939958989 +0200 |
196 |
@@ -369,7 +369,7 @@ ssize_t receive_packet (interface, buf, |
197 |
|
198 |
/* Decode the IP and UDP headers... */ |
199 |
offset = decode_udp_ip_header (interface, ibuf, bufix, |
200 |
- from, length, &paylen); |
201 |
+ from, length, &paylen, 0); |
202 |
|
203 |
/* If the IP or UDP checksum was bad, skip the packet... */ |
204 |
if (offset < 0) |
205 |
diff -up dhcp-4.2.2b1/common/packet.c.xen dhcp-4.2.2b1/common/packet.c |
206 |
--- dhcp-4.2.2b1/common/packet.c.xen 2009-07-23 20:52:20.000000000 +0200 |
207 |
+++ dhcp-4.2.2b1/common/packet.c 2011-07-01 14:00:16.939958989 +0200 |
208 |
@@ -211,7 +211,7 @@ ssize_t |
209 |
decode_udp_ip_header(struct interface_info *interface, |
210 |
unsigned char *buf, unsigned bufix, |
211 |
struct sockaddr_in *from, unsigned buflen, |
212 |
- unsigned *rbuflen) |
213 |
+ unsigned *rbuflen, int nocsum) |
214 |
{ |
215 |
unsigned char *data; |
216 |
struct ip ip; |
217 |
@@ -322,7 +322,7 @@ decode_udp_ip_header(struct interface_in |
218 |
8, IPPROTO_UDP + ulen)))); |
219 |
|
220 |
udp_packets_seen++; |
221 |
- if (usum && usum != sum) { |
222 |
+ if (!nocsum && usum && usum != sum) { |
223 |
udp_packets_bad_checksum++; |
224 |
if (udp_packets_seen > 4 && |
225 |
(udp_packets_seen / udp_packets_bad_checksum) < 2) { |
226 |
diff -up dhcp-4.2.2b1/common/upf.c.xen dhcp-4.2.2b1/common/upf.c |
227 |
--- dhcp-4.2.2b1/common/upf.c.xen 2009-11-20 02:49:01.000000000 +0100 |
228 |
+++ dhcp-4.2.2b1/common/upf.c 2011-07-01 14:00:16.940958986 +0200 |
229 |
@@ -320,7 +320,7 @@ ssize_t receive_packet (interface, buf, |
230 |
|
231 |
/* Decode the IP and UDP headers... */ |
232 |
offset = decode_udp_ip_header (interface, ibuf, bufix, |
233 |
- from, length, &paylen); |
234 |
+ from, length, &paylen, 0); |
235 |
|
236 |
/* If the IP or UDP checksum was bad, skip the packet... */ |
237 |
if (offset < 0) |
238 |
diff -up dhcp-4.2.2b1/includes/dhcpd.h.xen dhcp-4.2.2b1/includes/dhcpd.h |
239 |
--- dhcp-4.2.2b1/includes/dhcpd.h.xen 2011-07-01 14:00:16.000000000 +0200 |
240 |
+++ dhcp-4.2.2b1/includes/dhcpd.h 2011-07-01 14:12:18.069642470 +0200 |
241 |
@@ -2796,7 +2796,7 @@ ssize_t decode_hw_header (struct interfa |
242 |
unsigned, struct hardware *); |
243 |
ssize_t decode_udp_ip_header (struct interface_info *, unsigned char *, |
244 |
unsigned, struct sockaddr_in *, |
245 |
- unsigned, unsigned *); |
246 |
+ unsigned, unsigned *, int); |
247 |
|
248 |
/* ethernet.c */ |
249 |
void assemble_ethernet_header (struct interface_info *, unsigned char *, |