int promisc;
+ /* bitmask of ignored ssl_pkttypes */
+ uint32_t pkttype_filter_mask;
+
int down_count;
uint16_t cluster_id;
return AFP_READ_OK;
}
+/**
+ * \brief AF packet frame ignore logic
+ *
+ * Given a sockaddr_ll of a frame, use the pkttype_filter_mask to decide if the
+ * frame should be ignored. Protect from undefined behavior if there's ever
+ * a sll_pkttype that would shift by too much. At this point, only outgoing
+ * packets (4) are ignored. The highest value in if_linux.h is PACKET_KERNEL (7),
+ * this extra check is being overly cautious.
+ *
+ * \retval true if the frame should be ignored
+ */
+static inline bool AFPShouldIgnoreFrame(AFPThreadVars *ptv, const struct sockaddr_ll *sll)
+{
+ if (unlikely(sll->sll_pkttype > 31))
+ return false;
+
+ return (ptv->pkttype_filter_mask & BIT_U32(sll->sll_pkttype)) != 0;
+}
+
/**
* \brief AF packet read function for ring
*
goto next_frame;
}
+ const struct sockaddr_ll *sll =
+ (const struct sockaddr_ll *)((uint8_t *)h.h2 +
+ TPACKET_ALIGN(sizeof(struct tpacket2_hdr)));
+ if (unlikely(AFPShouldIgnoreFrame(ptv, sll)))
+ goto next_frame;
+
Packet *p = PacketGetFromQueueOrAlloc();
if (p == NULL) {
return AFPSuriFailure(ptv, h);
uint8_t *ppd = (uint8_t *)pbd + pbd->hdr.bh1.offset_to_first_pkt;
for (int i = 0; i < num_pkts; ++i) {
+ const struct sockaddr_ll *sll =
+ (const struct sockaddr_ll *)(ppd + TPACKET_ALIGN(sizeof(struct tpacket3_hdr)));
+ if (unlikely(AFPShouldIgnoreFrame(ptv, sll))) {
+ ppd = ppd + ((struct tpacket3_hdr *)ppd)->tp_next_offset;
+ continue;
+ }
int ret = AFPParsePacketV3(ptv, pbd, (struct tpacket3_hdr *)ppd);
switch (ret) {
case AFP_READ_OK:
goto socket_err;
}
+ /* ignore outgoing packets on loopback interfaces */
+ if (if_flags & IFF_LOOPBACK)
+ ptv->pkttype_filter_mask |= BIT_U32(PACKET_OUTGOING);
+
if (ptv->promisc != 0) {
/* Force promiscuous mode */
memset(&sock_params, 0, sizeof(sock_params));