Skip to content

Commit

Permalink
Only add VLAN tags for Ethernet.
Browse files Browse the repository at this point in the history
The code to insert VLAN tags was assuming Ethernet packets; that's not
the case, for example, if you're capturing on the "any" device, as the
packet headers aren't Ethernet headers.  Have a flag in the pcap
structure to indicate whether to check for and add VLAN tags, and set it
only if we're using PF_PACKET sockets, we're getting Ethernet headers,
and, if we're using the memory-mapped capture mechanism, it's not
version 1.

This should fix SourceForge bug 3525828.
  • Loading branch information
guyharris committed Aug 19, 2012
1 parent a5e6d85 commit 4cc089d
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 22 deletions.
1 change: 1 addition & 0 deletions pcap-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ struct pcap_md {
char *mondevice; /* mac80211 monitor device we created */
u_char *mmapbuf; /* memory-mapped region pointer */
size_t mmapbuflen; /* size of region */
int add_vlan_tags; /* 1 if we should insert VLAN tags */
u_int tp_version; /* version of tpacket_hdr for mmaped ring */
u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */
u_char *oneshot_buffer; /* buffer for copy of packet */
Expand Down
72 changes: 50 additions & 22 deletions pcap-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -1530,32 +1530,34 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
}

#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
struct tpacket_auxdata *aux;
unsigned int len;
struct vlan_tag *tag;

if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
cmsg->cmsg_level != SOL_PACKET ||
cmsg->cmsg_type != PACKET_AUXDATA)
continue;
if (handle->md.add_vlan_tags) {
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
struct tpacket_auxdata *aux;
unsigned int len;
struct vlan_tag *tag;

aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
if (aux->tp_vlan_tci == 0)
continue;
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
cmsg->cmsg_level != SOL_PACKET ||
cmsg->cmsg_type != PACKET_AUXDATA)
continue;

len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
if (len < 2 * ETH_ALEN)
break;
aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
if (aux->tp_vlan_tci == 0)
continue;

bp -= VLAN_TAG_LEN;
memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN);
len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
if (len < 2 * ETH_ALEN)
break;

bp -= VLAN_TAG_LEN;
memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN);

tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN);
tag->vlan_tpid = htons(ETH_P_8021Q);
tag->vlan_tci = htons(aux->tp_vlan_tci);
tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN);
tag->vlan_tpid = htons(ETH_P_8021Q);
tag->vlan_tci = htons(aux->tp_vlan_tci);

packet_len += VLAN_TAG_LEN;
packet_len += VLAN_TAG_LEN;
}
}
#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
#endif /* HAVE_PF_PACKET_SOCKETS */
Expand Down Expand Up @@ -3043,6 +3045,19 @@ activate_new(pcap_t *handle)
}
handle->bufsize = handle->snapshot;

/*
* Only enable the insertion of VLAN tags if the link-layer
* header type is Ethernet. If it should be supported on
* any other link-layer type, the code that inserts them
* must be modified to insert them in the proper place, which
* differs from link-layer header type to link-layer header
* type.
*/
if (handle->linktype == DLT_EN10MB)
handle->md.add_vlan_tags = 1;
else
handle->md.add_vlan_tags = 0;

/* Save the socket FD in the pcap structure */
handle->fd = sock_fd;

Expand Down Expand Up @@ -3130,6 +3145,14 @@ activate_mmap(pcap_t *handle, int *status)
handle->getnonblock_op = pcap_getnonblock_mmap;
handle->oneshot_callback = pcap_oneshot_mmap;
handle->selectable_fd = handle->fd;

/*
* We only support inserting VLAN tags for tpacket V2;
* if we're using v1, disable it.
*/
if (handle->md.tp_version == TPACKET_V1)
handle->md.add_vlan_tags = 0;

return 1;
}
#else /* HAVE_PACKET_RING */
Expand Down Expand Up @@ -3882,7 +3905,7 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
}

#ifdef HAVE_TPACKET2
if (handle->md.tp_version == TPACKET_V2 && h.h2->tp_vlan_tci &&
if (handle->md.add_vlan_tags && h.h2->tp_vlan_tci &&
tp_snaplen >= 2 * ETH_ALEN) {
struct vlan_tag *tag;

Expand Down Expand Up @@ -5075,6 +5098,11 @@ activate_old(pcap_t *handle)
*/
handle->offset = 0;

/*
* No support for getting VLAN tags to insert.
*/
handle->md.add_vlan_tags = 0;

return 1;
}

Expand Down

0 comments on commit 4cc089d

Please sign in to comment.