summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-connectivity')
-rw-r--r--meta/recipes-connectivity/dhcp/dhcp/dhcp-xen-checksum.patch307
-rw-r--r--meta/recipes-connectivity/dhcp/dhcp_4.3.1.bb1
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 @@
1dhcp-client: Ignore partial checksums
2
3dhclient will fail to get an IP address if run inside a guest when traffic is
4flowing over a virtual network interface. The user will see the error
5message:
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
12This is because Linux only uses partial checksums for packets that go over
13virtual network interfaces and dhclient does not like this.
14
15 See linux kernel commit 78ea85f17b15390e30d8b47488ec7b6cf0790663
16 ("net: skbuff: improve comment on checksumming")
17
18An application can detect this behaviour by checking for the
19TP_STATUS_CSUMNOTREADY flag in the tp_status field.
20
21 See linux kernel commit 8dc4194474159660d7f37c495e3fc3f10d0db8cc
22 ("Add optional checksum computation for recvmsg")
23
24An extra parameter is added to decode_udp_ip_header() in dhclient to indicate
25whether or not dhclient should ignore partial checksums. This is used
26when the TP_STATUS_CSUMNOTREADY bit is set by the guest kernel.
27
28This fix has been included in Fedora and Ubuntu, however it has not yet been
29accepted by ISC upstream. Likely because it is specific to behaviour in Linux
30and other UNIX variants do not seem to be affected.
31
32The 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
35Originally 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
38Submitted 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
42Upstream-Status: Submitted [dhcp-bugs@isc.org]
43Signed-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
54diff --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) {
66diff --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...
78diff --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)
248diff --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)
260diff --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) {
281diff --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)
293diff --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--
3061.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
11SRC_URI[md5sum] = "b3a42ece3c7f2cd2e74a3e12ca881d20" 12SRC_URI[md5sum] = "b3a42ece3c7f2cd2e74a3e12ca881d20"