> new and old function should only handle the PACKET_SOCKET vs.
> PF_PACKET case IMHO.
> Do you agree?

I.e., do something along the lines of what this patch does?

Index: pcap-linux.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-linux.c,v
retrieving revision 1.61
diff -c -r1.61 pcap-linux.c
*** pcap-linux.c        2001/07/29 18:25:47     1.61
--- pcap-linux.c        2001/08/22 21:18:42
***************
*** 178,186 ****
  pcap_t *
  pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  {
          /* Allocate a handle for this session. */
  
!       pcap_t  *handle = malloc(sizeof(*handle));
        if (handle == NULL) {
                snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
                         pcap_strerror(errno));
--- 178,190 ----
  pcap_t *
  pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  {
+       pcap_t          *handle;
+       int             mtu;
+       struct utsname  utsname;
+ 
          /* Allocate a handle for this session. */
  
!       handle = malloc(sizeof(*handle));
        if (handle == NULL) {
                snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
                         pcap_strerror(errno));
***************
*** 234,239 ****
--- 238,317 ----
                return NULL;
        }
  
+       /* Compute the buffersize */
+ 
+       mtu     = iface_get_mtu(handle->fd, device, ebuf);
+       if (mtu == -1) {
+               close(handle->fd);
+               free(handle->md.device);
+               free(handle);
+               return NULL;
+       }
+       handle->bufsize  = MAX_LINKHEADER_SIZE + mtu;
+       if (handle->bufsize < handle->snapshot)
+               handle->bufsize = handle->snapshot;
+ 
+       /* Allocate the buffer */
+ 
+       handle->buffer   = malloc(handle->bufsize + handle->offset);
+       if (!handle->buffer) {
+               snprintf(ebuf, PCAP_ERRBUF_SIZE,
+                        "malloc: %s", pcap_strerror(errno));
+               close(handle->fd);
+               free(handle->md.device);
+               free(handle);
+               return NULL;
+       }
+ 
+       /*
+        * If we're using SOCKET_PACKET, this might be a 2.0[.x] kernel,
+        * and might require special handling - check.
+        */
+       if (handle->md.sock_packet && (uname(&utsname) < 0 ||
+           strncmp(utsname.release, "2.0", 3) == 0)) {
+               /*
+                * We're using a SOCK_PACKET structure, and either
+                * we couldn't find out what kernel release this is,
+                * or it's a 2.0[.x] kernel.
+                *
+                * In the 2.0[.x] kernel, a "recvfrom()" on
+                * a SOCK_PACKET socket, with MSG_TRUNC set, will
+                * return the number of bytes read, so if we pass
+                * a length based on the snapshot length, it'll
+                * return the number of bytes from the packet
+                * copied to userland, not the actual length
+                * of the packet.
+                *
+                * This means that, for example, the IP dissector
+                * in tcpdump will get handed a packet length less
+                * than the length in the IP header, and will
+                * complain about "truncated-ip".
+                *
+                * So we don't bother trying to copy from the
+                * kernel only the bytes in which we're interested,
+                * but instead copy them all, just as the older
+                * versions of libpcap for Linux did.
+                *
+                * That's just one of many problems with packet capture
+                * on 2.0[.x] kernels; you really want a 2.2[.x]
+                * or later kernel if you want packet capture to
+                * work well.
+                */
+               handle->md.readlen = handle->bufsize;
+       } else {
+               /*
+                * This is a 2.2[.x] or later kernel (we know that
+                * either because we're not using a SOCK_PACKET
+                * socket - PF_PACKET is supported only in 2.2
+                * and later kernels - or because we checked the
+                * kernel version).
+                *
+                * We can safely pass "recvfrom()" a byte count
+                * based on the snapshot length.
+                */
+               handle->md.readlen = handle->snapshot;
+       }
+ 
        return handle;
  }
  
***************
*** 783,789 ****
              int to_ms, char *ebuf)
  {
  #ifdef HAVE_PF_PACKET_SOCKETS
!       int                     sock_fd = -1, device_id, mtu, arptype;
        struct packet_mreq      mr;
  
        /* One shot loop used for error handling - bail out with break */
--- 861,867 ----
              int to_ms, char *ebuf)
  {
  #ifdef HAVE_PF_PACKET_SOCKETS
!       int                     sock_fd = -1, device_id, arptype;
        struct packet_mreq      mr;
  
        /* One shot loop used for error handling - bail out with break */
***************
*** 929,962 ****
                        }
                }
  #endif
- 
-               /* Compute the buffersize */
  
!               mtu     = iface_get_mtu(sock_fd, device, ebuf);
!               if (mtu == -1)
!                       break;
!               handle->bufsize  = MAX_LINKHEADER_SIZE + mtu;
! 
!               /* Fill in the pcap structure */
  
                handle->fd       = sock_fd;
  
-               handle->buffer   = malloc(handle->bufsize + handle->offset);
-               if (!handle->buffer) {
-                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                                "malloc: %s", pcap_strerror(errno));
-                       break;
-               }
- 
-               /*
-                * This is a 2.2 or later kernel, as it has PF_PACKET;
-                * "recvfrom()", when passed the MSG_TRUNC flag, will
-                * return the actual length of the packet, not the
-                * number of bytes from the packet copied to userland,
-                * so we can safely pass it a byte count based on the
-                * snapshot length.
-                */
-               handle->md.readlen = handle->snapshot;
                return 1;
  
        } while(0);
--- 1007,1017 ----
                        }
                }
  #endif
  
!               /* Save the socket FD in the pcap structure */
  
                handle->fd       = sock_fd;
  
                return 1;
  
        } while(0);
***************
*** 1131,1138 ****
  live_open_old(pcap_t *handle, char *device, int promisc, 
              int to_ms, char *ebuf)
  {
!       int             sock_fd = -1, mtu, arptype;
!       struct utsname  utsname;
        struct ifreq    ifr;
  
        do {
--- 1186,1192 ----
  live_open_old(pcap_t *handle, char *device, int promisc, 
              int to_ms, char *ebuf)
  {
!       int             sock_fd = -1, arptype;
        struct ifreq    ifr;
  
        do {
***************
*** 1215,1243 ****
                        }
                }
  
-               /* Compute the buffersize */
- 
-               mtu     = iface_get_mtu(sock_fd, device, ebuf);
-               if (mtu == -1)
-                       break;
-               handle->bufsize  = MAX_LINKHEADER_SIZE + mtu;
-               if (handle->bufsize < handle->snapshot)
-                       handle->bufsize = handle->snapshot;
- 
                /* All done - fill in the pcap handle */
  
                arptype = iface_get_arptype(sock_fd, device, ebuf);
                if (arptype == -1)
                        break;
  
                /*
                 * Default value for offset to align link-layer payload
                 * on a 4-byte boundary.
                 */
                handle->offset   = 0;
  
-               handle->fd       = sock_fd;
- 
                /*
                 * XXX - handle ISDN types here?  We can't fall back on
                 * cooked sockets, so we'd have to figure out from the
--- 1269,1290 ----
                        }
                }
  
                /* All done - fill in the pcap handle */
  
                arptype = iface_get_arptype(sock_fd, device, ebuf);
                if (arptype == -1)
                        break;
  
+               /* Save the socket FD in the pcap structure */
+ 
+               handle->fd       = sock_fd;
+ 
                /*
                 * Default value for offset to align link-layer payload
                 * on a 4-byte boundary.
                 */
                handle->offset   = 0;
  
                /*
                 * XXX - handle ISDN types here?  We can't fall back on
                 * cooked sockets, so we'd have to figure out from the
***************
*** 1254,1310 ****
                                 "interface type of %s not supported", device);
                        break;
                }
-               handle->buffer   = malloc(handle->bufsize + handle->offset);
-               if (!handle->buffer) {
-                       snprintf(ebuf, PCAP_ERRBUF_SIZE,
-                                "malloc: %s", pcap_strerror(errno));
-                       break;
-               }
  
-               /*
-                * This might be a 2.0[.x] kernel - check.
-                */
-               if (uname(&utsname) < 0 ||
-                   strncmp(utsname.release, "2.0", 3) == 0) {
-                       /*
-                        * Either we couldn't find out what kernel release
-                        * this is, or it's a 2.0[.x] kernel.
-                        *
-                        * In the 2.0[.x] kernel, a "recvfrom()" on
-                        * a SOCK_PACKET socket, with MSG_TRUNC set, will
-                        * return the number of bytes read, so if we pass
-                        * a length based on the snapshot length, it'll
-                        * return the number of bytes from the packet
-                        * copied to userland, not the actual length
-                        * of the packet.
-                        *
-                        * This means that, for example, the IP dissector
-                        * in tcpdump will get handed a packet length less
-                        * than the length in the IP header, and will
-                        * complain about "truncated-ip".
-                        *
-                        * So we don't bother trying to copy from the
-                        * kernel only the bytes in which we're interested,
-                        * but instead copy them all, just as the older
-                        * versions of libpcap for Linux did.
-                        *
-                        * Just one of many problems with packet capture
-                        * on 2.0[.x] kernels; you really want a 2.2[.x]
-                        * or later kernel if you want packet capture to
-                        * work well.
-                        */
-                       handle->md.readlen = handle->bufsize;
-               } else {
-                       /*
-                        * This is a 2.2[.x] or later kernel (although
-                        * why we're using SOCK_PACKET on such a system
-                        * is unknown to me).
-                        *
-                        * We can safely pass "recvfrom()" a byte count
-                        * based on the snapshot length.
-                        */
-                       handle->md.readlen = handle->snapshot;
-               }
                return 1;
  
        } while (0);
--- 1301,1307 ----
-
This is the TCPDUMP workers list. It is archived at
http://www.tcpdump.org/lists/workers/index.html
To unsubscribe use mailto:[EMAIL PROTECTED]?body=unsubscribe

Reply via email to