{
struct sockaddr_ll socket_address;
int socket;
- uint8_t *pstart;
- size_t plen;
- union thdr h;
- uint16_t vlan_tci = 0;
if (p->afp_v.copy_mode == AFP_COPY_MODE_IPS) {
if (PacketTestAction(p, ACTION_DROP)) {
SCMutexLock(&p->afp_v.peer->sock_protect);
socket = SC_ATOMIC_GET(p->afp_v.peer->socket);
- h.raw = p->afp_v.relptr;
-
- if (version == TPACKET_V2) {
- /* Copy VLAN header from ring memory. For post june 2011 kernel we test
- * the flag. It is not defined for older kernel so we go best effort
- * and test for non zero value of the TCI header. */
- if (h.h2->tp_status & TP_STATUS_VLAN_VALID || h.h2->tp_vlan_tci) {
- vlan_tci = h.h2->tp_vlan_tci;
- }
- } else {
-#ifdef HAVE_TPACKET_V3
- if (h.h3->tp_status & TP_STATUS_VLAN_VALID || h.h3->hv1.tp_vlan_tci) {
- vlan_tci = h.h3->hv1.tp_vlan_tci;
- }
-#else
- /* Should not get here */
- BUG_ON(1);
-#endif
- }
-
- if (vlan_tci != 0) {
- pstart = GET_PKT_DATA(p) - VLAN_HEADER_LEN;
- plen = GET_PKT_LEN(p) + VLAN_HEADER_LEN;
- /* move ethernet addresses */
- memmove(pstart, GET_PKT_DATA(p), 2 * ETH_ALEN);
- /* write vlan info */
- *(uint16_t *)(pstart + 2 * ETH_ALEN) = htons(0x8100);
- *(uint16_t *)(pstart + 2 * ETH_ALEN + 2) = htons(vlan_tci);
- } else {
- pstart = GET_PKT_DATA(p);
- plen = GET_PKT_LEN(p);
- }
-
- if (sendto(socket, pstart, plen, 0,
- (struct sockaddr*) &socket_address,
- sizeof(struct sockaddr_ll)) < 0) {
+ if (sendto(socket, GET_PKT_DATA(p), GET_PKT_LEN(p), 0, (struct sockaddr *)&socket_address,
+ sizeof(struct sockaddr_ll)) < 0) {
SCLogWarning(SC_ERR_SOCKET, "Sending packet failed on socket %d: %s",
socket,
strerror(errno));
(tp_status & TP_STATUS_VLAN_VALID || h.h2->tp_vlan_tci)) {
p->vlan_id[0] = h.h2->tp_vlan_tci & 0x0fff;
p->vlan_idx = 1;
+ p->afp_v.vlan_tci = h.h2->tp_vlan_tci;
}
(void)PacketSetData(p, (unsigned char *)h.raw + h.h2->tp_mac, h.h2->tp_snaplen);
(ppd->tp_status & TP_STATUS_VLAN_VALID || ppd->hv1.tp_vlan_tci)) {
p->vlan_id[0] = ppd->hv1.tp_vlan_tci & 0x0fff;
p->vlan_idx = 1;
+ p->afp_v.vlan_tci = ppd->hv1.tp_vlan_tci;
}
(void)PacketSetData(p, (unsigned char *)ppd + ppd->tp_mac, ppd->tp_snaplen);
}
#endif
- /* Let's reserve head room so we can add the VLAN header in IPS
- * or TAP mode before write the packet */
- if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
- /* Only one vlan is extracted from AFP header so
- * one VLAN header length is enough. */
- int reserve = VLAN_HEADER_LEN;
- if (setsockopt(ptv->socket, SOL_PACKET, PACKET_RESERVE, (void *) &reserve,
- sizeof(reserve)) < 0) {
- SCLogError(SC_ERR_AFP_CREATE,
- "Can't activate reserve on packet socket: %s",
- strerror(errno));
- return AFP_FATAL_ERROR;
- }
+ /* Reserve head room for a VLAN header. One vlan is extracted from AFP header
+ * so one VLAN header length is enough. */
+ int reserve = VLAN_HEADER_LEN;
+ if (setsockopt(ptv->socket, SOL_PACKET, PACKET_RESERVE, (void *)&reserve, sizeof(reserve)) <
+ 0) {
+ SCLogError(
+ SC_ERR_AFP_CREATE, "Can't activate reserve on packet socket: %s", strerror(errno));
+ return AFP_FATAL_ERROR;
}
/* Allocate RX ring */
SCReturnInt(TM_ECODE_OK);
}
+/** \internal
+ * \brief add a VLAN header into the raw data for inspection, logging
+ * and sending out in IPS mode
+ *
+ * The kernel doesn't provide the first VLAN header the raw packet data,
+ * but instead feeds it to us through meta data. For logging and IPS
+ * we need to put it back into the raw data. Luckily there is some head
+ * room in the original data so its enough to move the ethernet header
+ * a bit to make space for the VLAN header.
+ */
+static void UpdateRawDataForVLANHdr(Packet *p)
+{
+ if (p->afp_v.vlan_tci != 0) {
+ uint8_t *pstart = GET_PKT_DATA(p) - VLAN_HEADER_LEN;
+ size_t plen = GET_PKT_LEN(p) + VLAN_HEADER_LEN;
+ /* move ethernet addresses */
+ memmove(pstart, GET_PKT_DATA(p), 2 * ETH_ALEN);
+ /* write vlan info */
+ *(uint16_t *)(pstart + 2 * ETH_ALEN) = htons(0x8100);
+ *(uint16_t *)(pstart + 2 * ETH_ALEN + 2) = htons(p->afp_v.vlan_tci);
+
+ /* update the packet raw data pointer to start at the new offset */
+ (void)PacketSetData(p, pstart, plen);
+ /* update ethernet header pointer to point to the new start of the data */
+ p->ethh = (void *)pstart;
+ }
+}
+
/**
* \brief This function passes off to link type decoders.
*
TmEcode DecodeAFP(ThreadVars *tv, Packet *p, void *data)
{
SCEnter();
+
+ const bool afp_vlan_hdr = p->vlan_idx != 0;
DecodeThreadVars *dtv = (DecodeThreadVars *)data;
DEBUG_VALIDATE_BUG_ON(PKT_IS_PSEUDOPKT(p));
/* update counters */
DecodeUpdatePacketCounters(tv, dtv, p);
- /* If suri has set vlan during reading, we increase vlan counter */
- if (p->vlan_idx) {
- StatsIncr(tv, dtv->counter_vlan);
- }
-
/* call the decoder */
DecodeLinkLayer(tv, dtv, p->datalink, p, GET_PKT_DATA(p), GET_PKT_LEN(p));
+ /* post-decoding put vlan hdr back into the raw data) */
+ if (afp_vlan_hdr) {
+ StatsIncr(tv, dtv->counter_vlan);
+ UpdateRawDataForVLANHdr(p);
+ }
PacketDecodeFinalize(tv, dtv, p);