updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / upslug2-openwrt / 100-libpcap_fix.patch
blob1e14de45197c909b032290598bd667f68c555b7d
1 --- a/pcap_wire.cc
2 +++ b/pcap_wire.cc
3 @@ -18,6 +18,7 @@
5 #include <sys/time.h>
6 #include <sys/select.h>
7 +#include <sys/poll.h>
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.
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");
19 /* Verify the protocol and originating address of the packet, then
20 * return this packet.
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.
40 if (packet_header->caplen < packet_header->len)
41 - throw std::logic_error("truncated packet");
42 + return;
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.
50 - struct timeval tvStart;
51 - if (timeout > 0 && gettimeofday(&tvStart, 0) != 0)
52 - throw OSError(errno, "gettimeofday(base)");
53 + int time_count;
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));
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;
83 - struct timeval tvNow;
84 - if (gettimeofday(&tvNow, 0) != 0)
85 - throw OSError(errno, "gettimeofday(now)");
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;
94 - tvNow.tv_sec = 0;
95 - tvNow.tv_usec = timeout-t;
96 - if (tvNow.tv_usec > 10000)
97 - tvNow.tv_usec = 10000;
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;
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");
118 - } while (timeout != 0);
119 + time_count--;
120 + } while (time_count > 0);
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;
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).
136 - pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 1/*ms*/, PCapErrbuf);
137 + pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 2/*ms*/, PCapErrbuf);
139 if (pcap == NULL)
140 throw WireError(errno, PCapErrbuf);
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);
151 try {
152 /* The MAC of the transmitting device is needed - without
153 * this the return packet won't go to the right place!