diff options
Diffstat (limited to 'meta/recipes-connectivity')
-rw-r--r-- | meta/recipes-connectivity/dhcp/dhcp/dhcp-xen-checksum.patch | 307 | ||||
-rw-r--r-- | meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb | 1 |
2 files changed, 308 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/dhcp/dhcp/dhcp-xen-checksum.patch b/meta/recipes-connectivity/dhcp/dhcp/dhcp-xen-checksum.patch new file mode 100644 index 0000000000..62c279db12 --- /dev/null +++ b/meta/recipes-connectivity/dhcp/dhcp/dhcp-xen-checksum.patch | |||
@@ -0,0 +1,307 @@ | |||
1 | dhcp-client: Ignore partial checksums | ||
2 | |||
3 | dhclient will fail to get an IP address if run inside a guest when traffic is | ||
4 | flowing over a virtual network interface. The user will see the error | ||
5 | message: | ||
6 | |||
7 | 5 bad udp checksums in 5 packets | ||
8 | No DHCPOFFERS received. | ||
9 | Unable to obtain a lease on first try. Exiting. | ||
10 | Failed to bring up eth0. | ||
11 | |||
12 | This is because Linux only uses partial checksums for packets that go over | ||
13 | virtual network interfaces and dhclient does not like this. | ||
14 | |||
15 | See linux kernel commit 78ea85f17b15390e30d8b47488ec7b6cf0790663 | ||
16 | ("net: skbuff: improve comment on checksumming") | ||
17 | |||
18 | An application can detect this behaviour by checking for the | ||
19 | TP_STATUS_CSUMNOTREADY flag in the tp_status field. | ||
20 | |||
21 | See linux kernel commit 8dc4194474159660d7f37c495e3fc3f10d0db8cc | ||
22 | ("Add optional checksum computation for recvmsg") | ||
23 | |||
24 | An extra parameter is added to decode_udp_ip_header() in dhclient to indicate | ||
25 | whether or not dhclient should ignore partial checksums. This is used | ||
26 | when the TP_STATUS_CSUMNOTREADY bit is set by the guest kernel. | ||
27 | |||
28 | This fix has been included in Fedora and Ubuntu, however it has not yet been | ||
29 | accepted by ISC upstream. Likely because it is specific to behaviour in Linux | ||
30 | and other UNIX variants do not seem to be affected. | ||
31 | |||
32 | The patch was imported from the dhcp source RPM in Fedora 21 | ||
33 | (http://pkgs.fedoraproject.org/cgit/dhcp.git/tree/dhcp-xen-checksum.patch?h=f21) | ||
34 | |||
35 | Originally contributed to fedora-cvs-commit by David Cantrell on Jan 30 2007 | ||
36 | (https://www.redhat.com/archives/fedora-cvs-commits/2007-January/msg01442.html) | ||
37 | |||
38 | Submitted to dhcp-bugs@isc.org - [ISC-Bugs #22806] - by Michael S. Tsirkin | ||
39 | (http://comments.gmane.org/gmane.comp.emulators.kvm.devel/65236) | ||
40 | (https://lists.isc.org/pipermail/dhcp-hackers/2010-April/001835.html) | ||
41 | |||
42 | Upstream-Status: Submitted [dhcp-bugs@isc.org] | ||
43 | Signed-off-by: Rob Woolley <rob.woolley@windriver.com> | ||
44 | -- | ||
45 | common/bpf.c | 2 - | ||
46 | common/dlpi.c | 2 - | ||
47 | common/lpf.c | 83 +++++++++++++++++++++++++++++++++++++++++-------------- | ||
48 | common/nit.c | 2 - | ||
49 | common/packet.c | 4 +- | ||
50 | common/upf.c | 2 - | ||
51 | includes/dhcpd.h | 2 - | ||
52 | 7 files changed, 70 insertions(+), 27 deletions(-) | ||
53 | |||
54 | diff --git a/common/bpf.c b/common/bpf.c | ||
55 | --- a/common/bpf.c | ||
56 | +++ b/common/bpf.c | ||
57 | @@ -481,7 +481,7 @@ ssize_t receive_packet (interface, buf, | ||
58 | /* Decode the IP and UDP headers... */ | ||
59 | offset = decode_udp_ip_header(interface, interface->rbuf, | ||
60 | interface->rbuf_offset, | ||
61 | - from, hdr.bh_caplen, &paylen); | ||
62 | + from, hdr.bh_caplen, &paylen, 0); | ||
63 | |||
64 | /* If the IP or UDP checksum was bad, skip the packet... */ | ||
65 | if (offset < 0) { | ||
66 | diff --git a/common/dlpi.c b/common/dlpi.c | ||
67 | --- a/common/dlpi.c | ||
68 | +++ b/common/dlpi.c | ||
69 | @@ -691,7 +691,7 @@ ssize_t receive_packet (interface, buf, | ||
70 | length -= offset; | ||
71 | #endif | ||
72 | offset = decode_udp_ip_header (interface, dbuf, bufix, | ||
73 | - from, length, &paylen); | ||
74 | + from, length, &paylen, 0); | ||
75 | |||
76 | /* | ||
77 | * If the IP or UDP checksum was bad, skip the packet... | ||
78 | diff --git a/common/lpf.c b/common/lpf.c | ||
79 | --- a/common/lpf.c | ||
80 | +++ b/common/lpf.c | ||
81 | @@ -29,14 +29,15 @@ | ||
82 | |||
83 | #include "dhcpd.h" | ||
84 | #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE) | ||
85 | +#include <sys/socket.h> | ||
86 | #include <sys/uio.h> | ||
87 | #include <errno.h> | ||
88 | |||
89 | #include <asm/types.h> | ||
90 | #include <linux/filter.h> | ||
91 | #include <linux/if_ether.h> | ||
92 | +#include <linux/if_packet.h> | ||
93 | #include <netinet/in_systm.h> | ||
94 | -#include <net/if_packet.h> | ||
95 | #include "includes/netinet/ip.h" | ||
96 | #include "includes/netinet/udp.h" | ||
97 | #include "includes/netinet/if_ether.h" | ||
98 | @@ -51,6 +52,19 @@ | ||
99 | /* Reinitializes the specified interface after an address change. This | ||
100 | is not required for packet-filter APIs. */ | ||
101 | |||
102 | +#ifndef PACKET_AUXDATA | ||
103 | +#define PACKET_AUXDATA 8 | ||
104 | + | ||
105 | +struct tpacket_auxdata | ||
106 | +{ | ||
107 | + __u32 tp_status; | ||
108 | + __u32 tp_len; | ||
109 | + __u32 tp_snaplen; | ||
110 | + __u16 tp_mac; | ||
111 | + __u16 tp_net; | ||
112 | +}; | ||
113 | +#endif | ||
114 | + | ||
115 | #ifdef USE_LPF_SEND | ||
116 | void if_reinitialize_send (info) | ||
117 | struct interface_info *info; | ||
118 | @@ -73,10 +87,14 @@ int if_register_lpf (info) | ||
119 | struct interface_info *info; | ||
120 | { | ||
121 | int sock; | ||
122 | - struct sockaddr sa; | ||
123 | + union { | ||
124 | + struct sockaddr_ll ll; | ||
125 | + struct sockaddr common; | ||
126 | + } sa; | ||
127 | + struct ifreq ifr; | ||
128 | |||
129 | /* Make an LPF socket. */ | ||
130 | - if ((sock = socket(PF_PACKET, SOCK_PACKET, | ||
131 | + if ((sock = socket(PF_PACKET, SOCK_RAW, | ||
132 | htons((short)ETH_P_ALL))) < 0) { | ||
133 | if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || | ||
134 | errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || | ||
135 | @@ -91,11 +109,17 @@ int if_register_lpf (info) | ||
136 | log_fatal ("Open a socket for LPF: %m"); | ||
137 | } | ||
138 | |||
139 | + memset (&ifr, 0, sizeof ifr); | ||
140 | + strncpy (ifr.ifr_name, (const char *)info -> ifp, sizeof ifr.ifr_name); | ||
141 | + ifr.ifr_name[IFNAMSIZ-1] = '\0'; | ||
142 | + if (ioctl (sock, SIOCGIFINDEX, &ifr)) | ||
143 | + log_fatal ("Failed to get interface index: %m"); | ||
144 | + | ||
145 | /* Bind to the interface name */ | ||
146 | memset (&sa, 0, sizeof sa); | ||
147 | - sa.sa_family = AF_PACKET; | ||
148 | - strncpy (sa.sa_data, (const char *)info -> ifp, sizeof sa.sa_data); | ||
149 | - if (bind (sock, &sa, sizeof sa)) { | ||
150 | + sa.ll.sll_family = AF_PACKET; | ||
151 | + sa.ll.sll_ifindex = ifr.ifr_ifindex; | ||
152 | + if (bind (sock, &sa.common, sizeof sa)) { | ||
153 | if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || | ||
154 | errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || | ||
155 | errno == EAFNOSUPPORT || errno == EINVAL) { | ||
156 | @@ -177,9 +201,18 @@ static void lpf_gen_filter_setup (struct | ||
157 | void if_register_receive (info) | ||
158 | struct interface_info *info; | ||
159 | { | ||
160 | + int val; | ||
161 | + | ||
162 | /* Open a LPF device and hang it on this interface... */ | ||
163 | info -> rfdesc = if_register_lpf (info); | ||
164 | |||
165 | + val = 1; | ||
166 | + if (setsockopt (info -> rfdesc, SOL_PACKET, PACKET_AUXDATA, &val, | ||
167 | + sizeof val) < 0) { | ||
168 | + if (errno != ENOPROTOOPT) | ||
169 | + log_fatal ("Failed to set auxiliary packet data: %m"); | ||
170 | + } | ||
171 | + | ||
172 | #if defined (HAVE_TR_SUPPORT) | ||
173 | if (info -> hw_address.hbuf [0] == HTYPE_IEEE802) | ||
174 | lpf_tr_filter_setup (info); | ||
175 | @@ -301,7 +334,6 @@ ssize_t send_packet (interface, packet, | ||
176 | double hh [16]; | ||
177 | double ih [1536 / sizeof (double)]; | ||
178 | unsigned char *buf = (unsigned char *)ih; | ||
179 | - struct sockaddr_pkt sa; | ||
180 | int result; | ||
181 | int fudge; | ||
182 | |||
183 | @@ -322,17 +354,7 @@ ssize_t send_packet (interface, packet, | ||
184 | (unsigned char *)raw, len); | ||
185 | memcpy (buf + ibufp, raw, len); | ||
186 | |||
187 | - /* For some reason, SOCK_PACKET sockets can't be connected, | ||
188 | - so we have to do a sentdo every time. */ | ||
189 | - memset (&sa, 0, sizeof sa); | ||
190 | - sa.spkt_family = AF_PACKET; | ||
191 | - strncpy ((char *)sa.spkt_device, | ||
192 | - (const char *)interface -> ifp, sizeof sa.spkt_device); | ||
193 | - sa.spkt_protocol = htons(ETH_P_IP); | ||
194 | - | ||
195 | - result = sendto (interface -> wfdesc, | ||
196 | - buf + fudge, ibufp + len - fudge, 0, | ||
197 | - (const struct sockaddr *)&sa, sizeof sa); | ||
198 | + result = write (interface -> wfdesc, buf + fudge, ibufp + len - fudge); | ||
199 | if (result < 0) | ||
200 | log_error ("send_packet: %m"); | ||
201 | return result; | ||
202 | @@ -349,14 +371,35 @@ ssize_t receive_packet (interface, buf, | ||
203 | { | ||
204 | int length = 0; | ||
205 | int offset = 0; | ||
206 | + int nocsum = 0; | ||
207 | unsigned char ibuf [1536]; | ||
208 | unsigned bufix = 0; | ||
209 | unsigned paylen; | ||
210 | + unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; | ||
211 | + struct iovec iov = { | ||
212 | + .iov_base = ibuf, | ||
213 | + .iov_len = sizeof ibuf, | ||
214 | + }; | ||
215 | + struct msghdr msg = { | ||
216 | + .msg_iov = &iov, | ||
217 | + .msg_iovlen = 1, | ||
218 | + .msg_control = cmsgbuf, | ||
219 | + .msg_controllen = sizeof(cmsgbuf), | ||
220 | + }; | ||
221 | + struct cmsghdr *cmsg; | ||
222 | |||
223 | - length = read (interface -> rfdesc, ibuf, sizeof ibuf); | ||
224 | + length = recvmsg (interface -> rfdesc, &msg, 0); | ||
225 | if (length <= 0) | ||
226 | return length; | ||
227 | |||
228 | + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { | ||
229 | + if (cmsg->cmsg_level == SOL_PACKET && | ||
230 | + cmsg->cmsg_type == PACKET_AUXDATA) { | ||
231 | + struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg); | ||
232 | + nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY; | ||
233 | + } | ||
234 | + } | ||
235 | + | ||
236 | bufix = 0; | ||
237 | /* Decode the physical header... */ | ||
238 | offset = decode_hw_header (interface, ibuf, bufix, hfrom); | ||
239 | @@ -373,7 +416,7 @@ ssize_t receive_packet (interface, buf, | ||
240 | |||
241 | /* Decode the IP and UDP headers... */ | ||
242 | offset = decode_udp_ip_header (interface, ibuf, bufix, from, | ||
243 | - (unsigned)length, &paylen); | ||
244 | + (unsigned)length, &paylen, nocsum); | ||
245 | |||
246 | /* If the IP or UDP checksum was bad, skip the packet... */ | ||
247 | if (offset < 0) | ||
248 | diff --git a/common/nit.c b/common/nit.c | ||
249 | --- a/common/nit.c | ||
250 | +++ b/common/nit.c | ||
251 | @@ -363,7 +363,7 @@ ssize_t receive_packet (interface, buf, | ||
252 | |||
253 | /* Decode the IP and UDP headers... */ | ||
254 | offset = decode_udp_ip_header (interface, ibuf, bufix, | ||
255 | - from, length, &paylen); | ||
256 | + from, length, &paylen, 0); | ||
257 | |||
258 | /* If the IP or UDP checksum was bad, skip the packet... */ | ||
259 | if (offset < 0) | ||
260 | diff --git a/common/packet.c b/common/packet.c | ||
261 | --- a/common/packet.c | ||
262 | +++ b/common/packet.c | ||
263 | @@ -226,7 +226,7 @@ ssize_t | ||
264 | decode_udp_ip_header(struct interface_info *interface, | ||
265 | unsigned char *buf, unsigned bufix, | ||
266 | struct sockaddr_in *from, unsigned buflen, | ||
267 | - unsigned *rbuflen) | ||
268 | + unsigned *rbuflen, int nocsum) | ||
269 | { | ||
270 | unsigned char *data; | ||
271 | struct ip ip; | ||
272 | @@ -337,7 +337,7 @@ decode_udp_ip_header(struct interface_in | ||
273 | 8, IPPROTO_UDP + ulen)))); | ||
274 | |||
275 | udp_packets_seen++; | ||
276 | - if (usum && usum != sum) { | ||
277 | + if (!nocsum && usum && usum != sum) { | ||
278 | udp_packets_bad_checksum++; | ||
279 | if (udp_packets_seen > 4 && | ||
280 | (udp_packets_seen / udp_packets_bad_checksum) < 2) { | ||
281 | diff --git a/common/upf.c b/common/upf.c | ||
282 | --- a/common/upf.c | ||
283 | +++ b/common/upf.c | ||
284 | @@ -314,7 +314,7 @@ ssize_t receive_packet (interface, buf, | ||
285 | |||
286 | /* Decode the IP and UDP headers... */ | ||
287 | offset = decode_udp_ip_header (interface, ibuf, bufix, | ||
288 | - from, length, &paylen); | ||
289 | + from, length, &paylen, 0); | ||
290 | |||
291 | /* If the IP or UDP checksum was bad, skip the packet... */ | ||
292 | if (offset < 0) | ||
293 | diff --git a/includes/dhcpd.h b/includes/dhcpd.h | ||
294 | --- a/includes/dhcpd.h | ||
295 | +++ b/includes/dhcpd.h | ||
296 | @@ -2857,7 +2857,7 @@ ssize_t decode_hw_header (struct interfa | ||
297 | unsigned, struct hardware *); | ||
298 | ssize_t decode_udp_ip_header (struct interface_info *, unsigned char *, | ||
299 | unsigned, struct sockaddr_in *, | ||
300 | - unsigned, unsigned *); | ||
301 | + unsigned, unsigned *, int); | ||
302 | |||
303 | /* ethernet.c */ | ||
304 | void assemble_ethernet_header (struct interface_info *, unsigned char *, | ||
305 | -- | ||
306 | 1.8.1.2 | ||
307 | |||
diff --git a/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb b/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb index 3f82a25fd2..d4414cc347 100644 --- a/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb +++ b/meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb | |||
@@ -6,6 +6,7 @@ SRC_URI += "file://dhcp-3.0.3-dhclient-dbus.patch;striplevel=0 \ | |||
6 | file://fixsepbuild.patch \ | 6 | file://fixsepbuild.patch \ |
7 | file://dhclient-script-drop-resolv.conf.dhclient.patch \ | 7 | file://dhclient-script-drop-resolv.conf.dhclient.patch \ |
8 | file://replace-ifconfig-route.patch \ | 8 | file://replace-ifconfig-route.patch \ |
9 | file://dhcp-xen-checksum.patch \ | ||
9 | " | 10 | " |
10 | 11 | ||
11 | SRC_URI[md5sum] = "b3a42ece3c7f2cd2e74a3e12ca881d20" | 12 | SRC_URI[md5sum] = "b3a42ece3c7f2cd2e74a3e12ca881d20" |