From 5c105d9f3fd086aff195d3849dcf847d6b0bd927 Mon Sep 17 00:00:00 2001 From: blogic Date: Fri, 5 Oct 2012 10:12:53 +0000 Subject: branch Attitude Adjustment git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@33625 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- tools/upslug2/patches/100-libpcap_fix.patch | 153 ++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 tools/upslug2/patches/100-libpcap_fix.patch (limited to '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 index 000000000..1e14de451 --- /dev/null +++ b/tools/upslug2/patches/100-libpcap_fix.patch @@ -0,0 +1,153 @@ +--- a/pcap_wire.cc ++++ b/pcap_wire.cc +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + /* 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(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(this))); ++ int count = pcap_dispatch(pcap, 1, PCapHandler, ++ reinterpret_cast(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! -- cgit v1.2.3