100-libpcap_fix.patch 4.9 KB

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