rpcd: iwinfo plugin fixes
[openwrt.git] / 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!