add a hacked up version of upslug2 which is able to flash a wrt350nv2 in recovery...
[openwrt/svn-archive/archive.git] / tools / upslug2 / patches / 100-libpcap_fix.patch
diff --git a/tools/upslug2/patches/100-libpcap_fix.patch b/tools/upslug2/patches/100-libpcap_fix.patch
new file mode 100644 (file)
index 0000000..1e14de4
--- /dev/null
@@ -0,0 +1,153 @@
+--- a/pcap_wire.cc
++++ b/pcap_wire.cc
+@@ -18,6 +18,7 @@
+ #include <sys/time.h>
+ #include <sys/select.h>
++#include <sys/poll.h>
+ /* Ways of finding the hardware MAC on this machine... */
+ /* This is the Linux only fallback. */
+@@ -130,20 +131,18 @@ namespace NSLU2Upgrade {
+                * non-static (real) Handler.
+                */
+               void Handler(const struct pcap_pkthdr *packet_header, const u_char *packet) {
+-                      /* This should only be called once... */
+-                      if (captured)
+-                              throw std::logic_error("Handler called twice");
+-
+                       /* Verify the protocol and originating address of the packet, then
+                        * return this packet.
+                        */
++                      if (captured)
++                              return;
+                       if (packet_header->caplen > 14 && (broadcast ||
+                               std::memcmp(packet+6, header, 6) == 0)) {
+-                              /* Record the address and copy the data */
+-                              std::memcpy(source, packet+6, 6);
+                               const size_t len(packet_header->caplen - 14);
+                               if (len > captureSize)
+-                                      throw std::logic_error("packet too long");
++                                      return;
++                              /* Record the address and copy the data */
++                              std::memcpy(source, packet+6, 6);
+                               std::memcpy(captureBuffer, packet+14, len);
+                               captureSize = len;
+                               captured = true;
+@@ -156,7 +155,7 @@ namespace NSLU2Upgrade {
+                        * packet and the buffer should be big enough.
+                        */
+                       if (packet_header->caplen < packet_header->len)
+-                              throw std::logic_error("truncated packet");
++                              return;
+                       /*IGNORE EVIL: known evil cast */
+                       reinterpret_cast<PCapWire*>(user)->Handler(packet_header, packet);
+@@ -173,56 +172,24 @@ namespace NSLU2Upgrade {
+               virtual void Receive(void *buffer, size_t &size, unsigned long timeout) {
+                       /* Now try to read packets until the timeout has been consumed.
+                        */
+-                      struct timeval tvStart;
+-                      if (timeout > 0 && gettimeofday(&tvStart, 0) != 0)
+-                              throw OSError(errno, "gettimeofday(base)");
++                      int time_count;
+                       captureBuffer = buffer;
+                       captureSize = size;
+                       captured = false;
++                      time_count = timeout / 2000; /* 2 ms intervals */
++                      time_count++;
+                       do {
+                               /*IGNORE EVIL: known evil cast */
+-                              int count(pcap_dispatch(pcap, 1, PCapHandler,
+-                                                      reinterpret_cast<u_char*>(this)));
++                              int count = pcap_dispatch(pcap, 1, PCapHandler,
++                                                      reinterpret_cast<u_char*>(this));
+-                              if (count > 0) {
+-                                      /* Were any packets handled? */
+-                                      if (captured) {
+-                                              size = captureSize;
+-                                              return;
+-                                      }
+-                                      /* else try again. */
+-                              } else if (count == 0) {
+-                                      /* Nothing to handle - do the timeout, do this
+-                                       * by waiting a bit then trying again, the trick
+-                                       * to this is to work out how long to wait each
+-                                       * time, for the moment a 10ms delay is used.
+-                                       */
+-                                      if (timeout == 0)
+-                                              break;
+-
+-                                      struct timeval tvNow;
+-                                      if (gettimeofday(&tvNow, 0) != 0)
+-                                              throw OSError(errno, "gettimeofday(now)");
+-
+-                                      unsigned long t(tvNow.tv_sec - tvStart.tv_sec);
+-                                      t *= 1000000;
+-                                      t += tvNow.tv_usec;
+-                                      t -= tvStart.tv_usec;
+-                                      if (t > timeout)
+-                                              break;
+-
+-                                      tvNow.tv_sec = 0;
+-                                      tvNow.tv_usec = timeout-t;
+-                                      if (tvNow.tv_usec > 10000)
+-                                              tvNow.tv_usec = 10000;
+-
+-                                      /* Delay, may be interrupted - this should
+-                                       * be portable to the BSDs (since the
+-                                       * technique originates in BSD.)
+-                                       */
+-                                      (void)select(0, 0, 0, 0, &tvNow);
+-                              } else {
++                              /* Were any packets handled? */
++                              if (captured) {
++                                      size = captureSize;
++                                      return;
++                              }
++                              if (count < 0) {
+                                       /* Error condition. */
+                                       if (count == -1) {
+                                               if (errno != EINTR)
+@@ -232,7 +199,8 @@ namespace NSLU2Upgrade {
+                                       } else
+                                               throw std::logic_error("pcap unexpected result");
+                               }
+-                      } while (timeout != 0);
++                              time_count--;
++                      } while (time_count > 0);
+                       /* Here on timeout. */
+                       size = 0;
+@@ -288,6 +256,7 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
+               const unsigned char *mac, const unsigned char *address, int uid) {
+       /* This is used to store the error passed to throw. */
+       static char PCapErrbuf[PCAP_ERRBUF_SIZE];
++      struct bpf_program fp;
+       /* Check the device name.  If not given use 'DEFAULT_ETHERNET_IF'. */
+       if (device == NULL)
+@@ -301,20 +270,12 @@ NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::
+                * for other ethernet MACs.  (Because the code above does not
+                * check that the destination matches the device in use).
+                */
+-              pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 1/*ms*/, PCapErrbuf);
++              pcap = pcap_open_live(device, 1540, false/*promiscuous*/, 2/*ms*/, PCapErrbuf);
+               if (pcap == NULL)
+                       throw WireError(errno, PCapErrbuf);
+       }
+-      /* Always do a non-blocking read, because the 'timeout' above
+-       * doesn't work on Linux (return is immediate) and on OSX (and
+-       * maybe other BSDs) the interface tends to hang waiting for
+-       * the timeout to expire even after receiving a single packet.
+-       */
+-      if (pcap_setnonblock(pcap, true, PCapErrbuf))
+-              throw WireError(errno, PCapErrbuf);
+-
+       try {
+               /* The MAC of the transmitting device is needed - without
+                * this the return packet won't go to the right place!