Root/tools/upslug2/patches/100-libpcap_fix.patch

1--- a/pcap_wire.cc
2+++ b/pcap_wire.cc
3@@ -18,6 +18,7 @@
4 
5 #include <sys/time.h>
6 #include <sys/select.h>
7+#include <sys/poll.h>
8 
9 /* Ways of finding the hardware MAC on this machine... */
10 /* This is the Linux only fallback. */
11@@ -130,20 +131,18 @@ namespace NSLU2Upgrade {
12          * non-static (real) Handler.
13          */
14         void Handler(const struct pcap_pkthdr *packet_header, const u_char *packet) {
15- /* This should only be called once... */
16- if (captured)
17- throw std::logic_error("Handler called twice");
18-
19             /* Verify the protocol and originating address of the packet, then
20              * return this packet.
21              */
22+ if (captured)
23+ return;
24             if (packet_header->caplen > 14 && (broadcast ||
25                 std::memcmp(packet+6, header, 6) == 0)) {
26- /* Record the address and copy the data */
27- std::memcpy(source, packet+6, 6);
28                 const size_t len(packet_header->caplen - 14);
29                 if (len > captureSize)
30- throw std::logic_error("packet too long");
31+ return;
32+ /* Record the address and copy the data */
33+ std::memcpy(source, packet+6, 6);
34                 std::memcpy(captureBuffer, packet+14, len);
35                 captureSize = len;
36                 captured = true;
37@@ -156,7 +155,7 @@ namespace NSLU2Upgrade {
38              * packet and the buffer should be big enough.
39              */
40             if (packet_header->caplen < packet_header->len)
41- throw std::logic_error("truncated packet");
42+ return;
43 
44             /*IGNORE EVIL: known evil cast */
45             reinterpret_cast<PCapWire*>(user)->Handler(packet_header, packet);
46@@ -173,56 +172,24 @@ namespace NSLU2Upgrade {
47         virtual void Receive(void *buffer, size_t &size, unsigned long timeout) {
48             /* Now try to read packets until the timeout has been consumed.
49              */
50- struct timeval tvStart;
51- if (timeout > 0 && gettimeofday(&tvStart, 0) != 0)
52- throw OSError(errno, "gettimeofday(base)");
53+ int time_count;
54 
55             captureBuffer = buffer;
56             captureSize = size;
57             captured = false;
58+ time_count = timeout / 2000; /* 2 ms intervals */
59+ time_count++;
60             do {
61                 /*IGNORE EVIL: known evil cast */
62- int count(pcap_dispatch(pcap, 1, PCapHandler,
63- reinterpret_cast<u_char*>(this)));
64+ int count = pcap_dispatch(pcap, 1, PCapHandler,
65+ reinterpret_cast<u_char*>(this));
66 
67- if (count > 0) {
68- /* Were any packets handled? */
69- if (captured) {
70- size = captureSize;
71- return;
72- }
73- /* else try again. */
74- } else if (count == 0) {
75- /* Nothing to handle - do the timeout, do this
76- * by waiting a bit then trying again, the trick
77- * to this is to work out how long to wait each
78- * time, for the moment a 10ms delay is used.
79- */
80- if (timeout == 0)
81- break;
82-
83- struct timeval tvNow;
84- if (gettimeofday(&tvNow, 0) != 0)
85- throw OSError(errno, "gettimeofday(now)");
86-
87- unsigned long t(tvNow.tv_sec - tvStart.tv_sec);
88- t *= 1000000;
89- t += tvNow.tv_usec;
90- t -= tvStart.tv_usec;
91- if (t > timeout)
92- break;
93-
94- tvNow.tv_sec = 0;
95- tvNow.tv_usec = timeout-t;
96- if (tvNow.tv_usec > 10000)
97- tvNow.tv_usec = 10000;
98-
99- /* Delay, may be interrupted - this should
100- * be portable to the BSDs (since the
101- * technique originates in BSD.)
102- */
103- (void)select(0, 0, 0, 0, &tvNow);
104- } else {
105+ /* Were any packets handled? */
106+ if (captured) {
107+ size = captureSize;
108+ return;
109+ }
110+ if (count < 0) {
111                     /* Error condition. */
112                     if (count == -1) {
113                         if (errno != EINTR)
114@@ -232,7 +199,8 @@ namespace NSLU2Upgrade {
115                     } else
116                         throw std::logic_error("pcap unexpected result");
117                 }
118- } while (timeout != 0);
119+ time_count--;
120+ } while (time_count > 0);
121 
122             /* Here on timeout. */
123             size = 0;
124@@ -288,6 +256,7 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
125         const unsigned char *mac, const unsigned char *address, int uid) {
126     /* This is used to store the error passed to throw. */
127     static char PCapErrbuf[PCAP_ERRBUF_SIZE];
128+ struct bpf_program fp;
129 
130     /* Check the device name. If not given use 'DEFAULT_ETHERNET_IF'. */
131     if (device == NULL)
132@@ -301,20 +270,12 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
133          * for other ethernet MACs. (Because the code above does not
134          * check that the destination matches the device in use).
135          */
136- pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 1/*ms*/, PCapErrbuf);
137+ pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 2/*ms*/, PCapErrbuf);
138 
139         if (pcap == NULL)
140             throw WireError(errno, PCapErrbuf);
141     }
142 
143- /* Always do a non-blocking read, because the 'timeout' above
144- * doesn't work on Linux (return is immediate) and on OSX (and
145- * maybe other BSDs) the interface tends to hang waiting for
146- * the timeout to expire even after receiving a single packet.
147- */
148- if (pcap_setnonblock(pcap, true, PCapErrbuf))
149- throw WireError(errno, PCapErrbuf);
150-
151     try {
152         /* The MAC of the transmitting device is needed - without
153          * this the return packet won't go to the right place!
154

Archive Download this file



interactive