On Thu, Mar 08, 2001 at 12:26:23AM -0800, Guy Harris wrote:
> On Wed, Mar 07, 2001 at 02:56:04PM -0800, Guy Harris wrote:
> > To reproduce this problem, you will have to run on a
> > processor+compiler+OS that doesn't allow unaligned accesses
>
> You might also be able to do it by editing "config.h" to define
> "LBL_ALIGN" (i.e., lie to it and tell it that the machine can't do
> unaligned 2-byte or 4-byte memory references) and rebuilding tcpdump.
Yes, that does it - I could reproduce it on my Debian 2.2 partition.
The patch attached to this message fixes it; it:
changes "map_arphrd_to_dlt()" to, instead of returning the
DLT_xxx value, take a "pcap_t *" as an argument, and set both
"handle->linktype" and, in some cases, "handle->offset"
("handle->offset" is set to 0 before it's called, so if
"map_arphrd_to_dlt()" doesn't set it, it defaults to 0);
sets "handle->buffer" to a buffer that's "handle->bufsize +
handle->offset" bytes long.
If nobody reports a problem with it, I'll check it in tomorrow or so.
Index: pcap-linux.c
===================================================================
RCS file: /tcpdump/master/libpcap/pcap-linux.c,v
retrieving revision 1.55
diff -c -r1.55 pcap-linux.c
*** pcap-linux.c 2001/01/20 07:47:54 1.55
--- pcap-linux.c 2001/03/12 01:12:41
***************
*** 142,148 ****
/*
* Prototypes for internal functions
*/
! static int map_arphrd_to_dlt(int arptype );
static int live_open_old(pcap_t *, char *, int, int, char *);
static int live_open_new(pcap_t *, char *, int, int, char *);
static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
--- 142,148 ----
/*
* Prototypes for internal functions
*/
! static int map_arphrd_to_dlt(pcap_t *, int);
static int live_open_old(pcap_t *, char *, int, int, char *);
static int live_open_new(pcap_t *, char *, int, int, char *);
static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
***************
*** 591,625 ****
/*
* Linux uses the ARP hardware type to identify the type of an
* interface. pcap uses the DLT_xxx constants for this. This
! * function maps the ARPHRD_xxx constant to an appropriate
! * DLT_xxx constant.
*
* Returns -1 if unable to map the type; we print a message and,
* if we're using PF_PACKET/SOCK_RAW rather than PF_INET/SOCK_PACKET,
* we fall back on using PF_PACKET/SOCK_DGRAM.
*/
! static int map_arphrd_to_dlt(int arptype)
{
switch (arptype) {
case ARPHRD_ETHER:
case ARPHRD_METRICOM:
! case ARPHRD_LOOPBACK: return DLT_EN10MB;
! case ARPHRD_EETHER: return DLT_EN3MB;
! case ARPHRD_AX25: return DLT_AX25;
! case ARPHRD_PRONET: return DLT_PRONET;
! case ARPHRD_CHAOS: return DLT_CHAOS;
#ifndef ARPHRD_IEEE802_TR
#define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */
#endif
case ARPHRD_IEEE802_TR:
! case ARPHRD_IEEE802: return DLT_IEEE802;
! case ARPHRD_ARCNET: return DLT_ARCNET;
! case ARPHRD_FDDI: return DLT_FDDI;
#ifndef ARPHRD_ATM /* FIXME: How to #include this? */
#define ARPHRD_ATM 19
#endif
! case ARPHRD_ATM: return DLT_ATM_CLIP;
case ARPHRD_PPP:
/* Not sure if this is correct for all tunnels, but it
--- 591,660 ----
/*
* Linux uses the ARP hardware type to identify the type of an
* interface. pcap uses the DLT_xxx constants for this. This
! * function takes a pointer to a "pcap_t", and an ARPHRD_xxx
! * constant, as arguments, and sets "handle->linktype" to the
! * appropriate DLT_XXX constant and sets "handle->offset" to
! * the appropriate value (to make "handle->offset" plus link-layer
! * header length be a multiple of 4, so that the link-layer payload
! * will be aligned on a 4-byte boundary when capturing packets).
! * (If the offset isn't set here, it'll be 0; add code as appropriate
! * for cases where it shouldn't be 0.)
*
* Returns -1 if unable to map the type; we print a message and,
* if we're using PF_PACKET/SOCK_RAW rather than PF_INET/SOCK_PACKET,
* we fall back on using PF_PACKET/SOCK_DGRAM.
*/
! static int map_arphrd_to_dlt(pcap_t *handle, int arptype)
{
switch (arptype) {
+
case ARPHRD_ETHER:
case ARPHRD_METRICOM:
! case ARPHRD_LOOPBACK:
! handle->linktype = DLT_EN10MB;
! handle->offset = 2;
! break;
!
! case ARPHRD_EETHER:
! handle->linktype = DLT_EN3MB;
! break;
!
! case ARPHRD_AX25:
! handle->linktype = DLT_AX25;
! break;
!
! case ARPHRD_PRONET:
! handle->linktype = DLT_PRONET;
! break;
!
! case ARPHRD_CHAOS:
! handle->linktype = DLT_CHAOS;
! break;
!
#ifndef ARPHRD_IEEE802_TR
#define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */
#endif
case ARPHRD_IEEE802_TR:
! case ARPHRD_IEEE802:
! handle->linktype = DLT_IEEE802;
! handle->offset = 2;
! break;
!
! case ARPHRD_ARCNET:
! handle->linktype = DLT_ARCNET;
! break;
!
! case ARPHRD_FDDI:
! handle->linktype = DLT_FDDI;
! handle->offset = 3;
! break;
#ifndef ARPHRD_ATM /* FIXME: How to #include this? */
#define ARPHRD_ATM 19
#endif
! case ARPHRD_ATM:
! handle->linktype = DLT_ATM_CLIP;
! break;
case ARPHRD_PPP:
/* Not sure if this is correct for all tunnels, but it
***************
*** 633,642 ****
case ARPHRD_SLIP6:
case ARPHRD_CSLIP6:
case ARPHRD_ADAPT:
! case ARPHRD_SLIP: return DLT_RAW;
! }
! return -1;
}
/* ===== Functions to interface to the newer kernels ================== */
--- 668,681 ----
case ARPHRD_SLIP6:
case ARPHRD_CSLIP6:
case ARPHRD_ADAPT:
! case ARPHRD_SLIP:
! handle->linktype = DLT_RAW;
! break;
! default:
! return -1;
! }
! return 0;
}
/* ===== Functions to interface to the newer kernels ================== */
***************
*** 689,694 ****
--- 728,739 ----
handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", ebuf);
/*
+ * Default value for offset to align link-layer payload
+ * on a 4-byte boundary.
+ */
+ handle->offset = 0;
+
+ /*
* What kind of frames do we have to deal with? Fall back
* to cooked mode if we have an unknown interface type.
*/
***************
*** 700,707 ****
arptype = iface_get_arptype(sock_fd, device, ebuf);
if (arptype == -1)
break;
! handle->linktype = map_arphrd_to_dlt(arptype);
! if (handle->linktype == -1 ||
(handle->linktype == DLT_EN10MB &&
(strncmp("isdn", device, 4) == 0 ||
strncmp("isdY", device, 4) == 0)) ||
--- 745,751 ----
arptype = iface_get_arptype(sock_fd, device, ebuf);
if (arptype == -1)
break;
! if (map_arphrd_to_dlt(handle, arptype) == -1 ||
(handle->linktype == DLT_EN10MB &&
(strncmp("isdn", device, 4) == 0 ||
strncmp("isdY", device, 4) == 0)) ||
***************
*** 804,812 ****
/* Fill in the pcap structure */
handle->fd = sock_fd;
- handle->offset = 0;
! handle->buffer = malloc(handle->bufsize);
if (!handle->buffer) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
--- 848,855 ----
/* 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));
***************
*** 1095,1103 ****
if (arptype == -1)
break;
! handle->fd = sock_fd;
handle->offset = 0;
! handle->linktype = map_arphrd_to_dlt(arptype);
/*
* XXX - handle ISDN types here? We can't fall back on
* cooked sockets, so we'd have to figure out from the
--- 1138,1151 ----
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
***************
*** 1109,1120 ****
* type that has only an Ethernet packet type as
* a link-layer header.
*/
! if (handle->linktype == -1) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"interface type of %s not supported", device);
break;
}
! handle->buffer = malloc(handle->bufsize);
if (!handle->buffer) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
--- 1157,1168 ----
* type that has only an Ethernet packet type as
* a link-layer header.
*/
! if (map_arphrd_to_dlt(handle, arptype) == -1) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"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));