Merging upstream version 2.3.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-04-21 09:31:29 +02:00
parent 678fe22a2c
commit 248a2fcec1
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
101 changed files with 2349 additions and 847 deletions

View file

@ -1,6 +1,6 @@
/*
* Author Jerry Lundström <jerry@dns-oarc.net>
* Copyright (c) 2016-2017, OARC, Inc.
* Copyright (c) 2016-2025 OARC, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -52,6 +52,7 @@
static void pcap_thread_callback(u_char* user, const struct pcap_pkthdr* pkthdr, const u_char* pkt, const char* name, int dlt);
static void pcap_thread_callback_linux_sll(u_char* user, pcap_thread_packet_t* packet, const u_char* payload, size_t length);
static void pcap_thread_callback_linux_sll2(u_char* user, pcap_thread_packet_t* packet, const u_char* payload, size_t length);
static void pcap_thread_callback_ether(u_char* user, pcap_thread_packet_t* packet, const u_char* payload, size_t length);
static void pcap_thread_callback_null(u_char* user, pcap_thread_packet_t* packet, const u_char* payload, size_t length);
static void pcap_thread_callback_loop(u_char* user, pcap_thread_packet_t* packet, const u_char* payload, size_t length);
@ -719,7 +720,8 @@ int pcap_thread_set_callback_linux_sll(pcap_thread_t* pcap_thread, pcap_thread_l
if (!pcap_thread) {
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_ether
if (pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
|| pcap_thread->callback_ieee802
@ -742,12 +744,42 @@ int pcap_thread_set_callback_linux_sll(pcap_thread_t* pcap_thread, pcap_thread_l
return PCAP_THREAD_OK;
}
int pcap_thread_set_callback_linux_sll2(pcap_thread_t* pcap_thread, pcap_thread_layer_callback_t callback_linux_sll2)
{
if (!pcap_thread) {
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
|| pcap_thread->callback_ieee802
|| pcap_thread->callback_gre
|| pcap_thread->callback_ip
|| pcap_thread->callback_ipv4
|| pcap_thread->callback_ipv6
|| pcap_thread->callback_icmp
|| pcap_thread->callback_icmpv6
|| pcap_thread->callback_udp
|| pcap_thread->callback_tcp) {
return PCAP_THREAD_ELAYERCB;
}
if (pcap_thread->running) {
return PCAP_THREAD_ERUNNING;
}
pcap_thread->callback_linux_sll2 = callback_linux_sll2;
return PCAP_THREAD_OK;
}
int pcap_thread_set_callback_ether(pcap_thread_t* pcap_thread, pcap_thread_layer_callback_t callback_ether)
{
if (!pcap_thread) {
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
|| pcap_thread->callback_ieee802
@ -776,6 +808,7 @@ int pcap_thread_set_callback_null(pcap_thread_t* pcap_thread, pcap_thread_layer_
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_loop
|| pcap_thread->callback_ieee802
@ -804,6 +837,7 @@ int pcap_thread_set_callback_loop(pcap_thread_t* pcap_thread, pcap_thread_layer_
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_ieee802
@ -832,6 +866,7 @@ int pcap_thread_set_callback_ieee802(pcap_thread_t* pcap_thread, pcap_thread_lay
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -860,6 +895,7 @@ int pcap_thread_set_callback_gre(pcap_thread_t* pcap_thread, pcap_thread_layer_c
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -888,6 +924,7 @@ int pcap_thread_set_callback_ip(pcap_thread_t* pcap_thread, pcap_thread_layer_ca
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -916,6 +953,7 @@ int pcap_thread_set_callback_ipv4(pcap_thread_t* pcap_thread, pcap_thread_layer_
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -968,6 +1006,7 @@ int pcap_thread_set_callback_ipv6(pcap_thread_t* pcap_thread, pcap_thread_layer_
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -1020,6 +1059,7 @@ int pcap_thread_set_callback_icmp(pcap_thread_t* pcap_thread, pcap_thread_layer_
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -1045,6 +1085,7 @@ int pcap_thread_set_callback_icmpv6(pcap_thread_t* pcap_thread, pcap_thread_laye
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -1070,6 +1111,7 @@ int pcap_thread_set_callback_udp(pcap_thread_t* pcap_thread, pcap_thread_layer_c
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -1095,6 +1137,7 @@ int pcap_thread_set_callback_tcp(pcap_thread_t* pcap_thread, pcap_thread_layer_c
return PCAP_THREAD_EINVAL;
}
if (pcap_thread->callback_linux_sll
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
@ -1232,9 +1275,9 @@ static void pcap_thread_callback(u_char* user, const struct pcap_pkthdr* pkthdr,
packet.state = PCAP_THREAD_PACKET_OK;
/*
* The header for null is in host byte order but may not be
* in the same endian as host if coming from a savefile
*/
* The header for null is in host byte order but may not be
* in the same endian as host if coming from a savefile
*/
if (pcaplist->is_offline && pcap_is_swapped(pcaplist->pcap)) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
@ -1322,7 +1365,26 @@ static void pcap_thread_callback(u_char* user, const struct pcap_pkthdr* pkthdr,
pcap_thread_callback_linux_sll((void*)pcaplist, &packet, pkt, length);
return;
/* TODO: These might be interesting to implement
case DLT_LINUX_SLL2:
layer_trace("dlt_linux_sll2");
packet.state = PCAP_THREAD_PACKET_INVALID_LINUX_SLL2;
need16(packet.linux_sll2.protocol_type, pkt, length);
need16(packet.linux_sll2.reserved, pkt, length);
need32(packet.linux_sll2.interface_index, pkt, length);
need16(packet.linux_sll2.arphrd_type, pkt, length);
need8(packet.linux_sll2.packet_type, pkt, length);
need8(packet.linux_sll2.link_layer_address_length, pkt, length);
needxb(packet.linux_sll2.link_layer_address, 8, pkt, length);
packet.state = PCAP_THREAD_PACKET_OK;
packet.have_linux_sll2 = 1;
if (pcaplist->pcap_thread->callback_linux_sll2)
pcaplist->pcap_thread->callback_linux_sll2(pcaplist->user, &packet, pkt, length);
else
pcap_thread_callback_linux_sll2((void*)pcaplist, &packet, pkt, length);
return;
/* TODO: These might be interesting to implement
case DLT_IPNET:
case DLT_PKTAP:
*/
@ -1410,6 +1472,77 @@ static void pcap_thread_callback_linux_sll(u_char* user, pcap_thread_packet_t* p
}
}
static void pcap_thread_callback_linux_sll2(u_char* user, pcap_thread_packet_t* packet, const u_char* payload, size_t length)
{
pcap_thread_pcaplist_t* pcaplist = (pcap_thread_pcaplist_t*)user;
const u_char* orig = payload;
size_t origlength = length;
if (!pcaplist) {
return;
}
if (!pcaplist->pcap_thread) {
return;
}
if (!packet) {
return;
}
if (!payload) {
return;
}
if (!length) {
return;
}
if (packet->have_linux_sll2) {
layer_trace("have_linux_sll2");
switch (packet->linux_sll2.protocol_type) {
case 0x8100: /* 802.1q */
case 0x88a8: /* 802.1ad */
case 0x9100: /* 802.1 QinQ non-standard */
if (packet->have_ieee802hdr)
break;
{
uint16_t tci;
packet->state = PCAP_THREAD_PACKET_INVALID_IEEE802;
need16(tci, payload, length);
packet->ieee802hdr.pcp = (tci & 0xe000) >> 13;
packet->ieee802hdr.dei = (tci & 0x1000) >> 12;
packet->ieee802hdr.vid = tci & 0x0fff;
need16(packet->ieee802hdr.ether_type, payload, length);
packet->state = PCAP_THREAD_PACKET_OK;
packet->have_ieee802hdr = 1;
}
if (pcaplist->pcap_thread->callback_ieee802)
pcaplist->pcap_thread->callback_ieee802(pcaplist->user, packet, payload, length);
else
pcap_thread_callback_ieee802((void*)pcaplist, packet, payload, length);
return;
case ETHERTYPE_IP:
case ETHERTYPE_IPV6:
if (pcaplist->pcap_thread->callback_ip)
pcaplist->pcap_thread->callback_ip(pcaplist->user, packet, payload, length);
else
pcap_thread_callback_ip((void*)pcaplist, packet, payload, length);
return;
default:
packet->state = PCAP_THREAD_PACKET_UNSUPPORTED;
break;
}
}
if (pcaplist->pcap_thread->callback_invalid) {
if (packet->state == PCAP_THREAD_PACKET_OK)
packet->state = PCAP_THREAD_PACKET_INVALID;
pcaplist->pcap_thread->callback_invalid(pcaplist->user, packet, orig, origlength);
}
}
static void pcap_thread_callback_ether(u_char* user, pcap_thread_packet_t* packet, const u_char* payload, size_t length)
{
pcap_thread_pcaplist_t* pcaplist = (pcap_thread_pcaplist_t*)user;
@ -3206,7 +3339,7 @@ static void* _thread(void* vp)
while (pcaplist->running) {
pthread_testcancel();
ret = pcap_loop(pcaplist->pcap, -1, _callback, (u_char*)pcaplist);
if (ret == -1) {
if (ret == PCAP_ERROR) {
/* TODO: Store pcap_loop() error */
break;
}
@ -3244,6 +3377,12 @@ static void _callback2(u_char* user, const struct pcap_pkthdr* pkthdr, const u_c
} else {
pcaplist->running = 0;
}
if (pcaplist->timedrun
&& (pkthdr->ts.tv_sec > pcaplist->end.tv_sec
|| (pkthdr->ts.tv_sec == pcaplist->end.tv_sec && (pkthdr->ts.tv_usec * 1000) >= pcaplist->end.tv_nsec))) {
pcap_breakloop(pcaplist->pcap);
}
}
int pcap_thread_run(pcap_thread_t* pcap_thread)
@ -3264,18 +3403,19 @@ int pcap_thread_run(pcap_thread_t* pcap_thread)
}
if (pcap_thread->use_layers
&& !(pcap_thread->callback_linux_sll
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
|| pcap_thread->callback_ieee802
|| pcap_thread->callback_gre
|| pcap_thread->callback_ip
|| pcap_thread->callback_ipv4
|| pcap_thread->callback_ipv6
|| pcap_thread->callback_icmp
|| pcap_thread->callback_icmpv6
|| pcap_thread->callback_udp
|| pcap_thread->callback_tcp)) {
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
|| pcap_thread->callback_ieee802
|| pcap_thread->callback_gre
|| pcap_thread->callback_ip
|| pcap_thread->callback_ipv4
|| pcap_thread->callback_ipv6
|| pcap_thread->callback_icmp
|| pcap_thread->callback_icmpv6
|| pcap_thread->callback_udp
|| pcap_thread->callback_tcp)) {
return PCAP_THREAD_NOCALLBACK;
}
if (pcap_thread->running) {
@ -3529,7 +3669,9 @@ int pcap_thread_run(pcap_thread_t* pcap_thread)
pcaplist->ipv6_frag_ctx = pcap_thread->callback_ipv6_frag.new(pcap_thread->callback_ipv6_frag.conf, pcaplist->user);
pcaplist->have_ipv6_frag_ctx = 1;
}
pcaplist->running = 1;
pcaplist->running = 1;
pcaplist->timedrun = timedrun;
pcaplist->end = end;
}
t1.tv_sec = pcap_thread->timeout / 1000;
@ -3590,12 +3732,13 @@ int pcap_thread_run(pcap_thread_t* pcap_thread)
}
packets = pcap_dispatch(pcaplist->pcap, -1, _callback2, (u_char*)pcaplist);
if (packets == -1) {
if (packets == PCAP_ERROR) {
pcap_thread->status = -1;
PCAP_THREAD_SET_ERRBUF(pcap_thread, "pcap_dispatch()");
pcap_thread->running = 0;
return PCAP_THREAD_EPCAP;
} else if (packets == -2 || (pcaplist->is_offline && !packets)) {
}
if (pcaplist->is_offline && !packets) {
pcaplist->running = 0;
}
}
@ -3620,18 +3763,19 @@ int pcap_thread_next(pcap_thread_t* pcap_thread)
}
if (pcap_thread->use_layers
&& !(pcap_thread->callback_linux_sll
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
|| pcap_thread->callback_ieee802
|| pcap_thread->callback_gre
|| pcap_thread->callback_ip
|| pcap_thread->callback_ipv4
|| pcap_thread->callback_ipv6
|| pcap_thread->callback_icmp
|| pcap_thread->callback_icmpv6
|| pcap_thread->callback_udp
|| pcap_thread->callback_tcp)) {
|| pcap_thread->callback_linux_sll2
|| pcap_thread->callback_ether
|| pcap_thread->callback_null
|| pcap_thread->callback_loop
|| pcap_thread->callback_ieee802
|| pcap_thread->callback_gre
|| pcap_thread->callback_ip
|| pcap_thread->callback_ipv4
|| pcap_thread->callback_ipv6
|| pcap_thread->callback_icmp
|| pcap_thread->callback_icmpv6
|| pcap_thread->callback_udp
|| pcap_thread->callback_tcp)) {
return PCAP_THREAD_NOCALLBACK;
}
if (pcap_thread->running) {