Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug #677 skipbroadcast #678

Merged
merged 8 commits into from
Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
06/19/2021 Version 4.4.0-beta1
- option --skipbroadcast not working (#677)
- add feature VLAN Q-in-Q (#625)

06/19/2021 Version 4.3.5-beta1
Expand Down
6 changes: 1 addition & 5 deletions src/common/flows.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
uint32_t pkt_len = pkthdr->caplen;
const u_char *packet = pktdata;
uint32_t _U_ vlan_offset;
uint32_t _U_ l2offset;
uint16_t ether_type = 0;
ipv4_hdr_t *ip_hdr = NULL;
ipv6_hdr_t *ip6_hdr = NULL;
Expand All @@ -172,7 +173,6 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
icmpv4_hdr_t *icmp_hdr;
flow_entry_data_t entry;
uint32_t l2len = 0;
uint32_t l2offset;
uint8_t protocol;
uint32_t hash;
int ip_len;
Expand Down Expand Up @@ -201,10 +201,6 @@ flow_entry_type_t flow_decode(flow_hash_table_t *fht, const struct pcap_pkthdr *
return FLOW_ENTRY_INVALID;
}

packet += l2offset;
l2len -= l2offset;
pkt_len -= l2offset;

assert(l2len > 0);

if (ether_type == ETHERTYPE_IP) {
Expand Down
46 changes: 33 additions & 13 deletions src/common/get.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ int parse_mpls(const u_char *pktdata,
if (len_remaining < 4)
return -1;

first_nibble = (*((u_char *)(mpls_label + 1)) >> 4) & 0xf;
first_nibble = *((u_char *)(mpls_label + 1)) >> 4;
switch(first_nibble) {
case 4:
*next_protocol = ETHERTYPE_IP;
Expand All @@ -151,7 +151,6 @@ int parse_mpls(const u_char *pktdata,
break;
default:
/* suspect Generic Associated Channel Header */
warnx("Unsupported MPLS label first nibble %u", first_nibble);
return -1;
}

Expand Down Expand Up @@ -322,7 +321,7 @@ int get_l2len_protocol(const u_char *pktdata,
uint32_t l2_net_off = sizeof(*eth_hdr) + *l2offset;
uint16_t ether_type = ntohs(eth_hdr->ether_type);

if (datalen < l2_net_off)
if (datalen <= l2_net_off)
return -1;

if (parse_metadata(pktdata,
Expand All @@ -337,7 +336,19 @@ int get_l2len_protocol(const u_char *pktdata,
return -1;

*l2len = l2_net_off;
*protocol = ether_type; /* yes, return it in host byte order */
if (ether_type > 1500) {
/* Ethernet II frame - return in host order */
*protocol = ether_type;
} else {
/* 803.3 frame */
if ((pktdata[l2_net_off] >> 4) == 4)
*protocol = ETHERTYPE_IP;
else if ((pktdata[l2_net_off] >> 4) == 6)
*protocol = ETHERTYPE_IP6;
else
/* unsupported 802.3 protocol */
return -1;
}
break;
}
case DLT_PPP_SERIAL:
Expand Down Expand Up @@ -580,8 +591,9 @@ void *
get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
{
struct tcpr_ipv6_ext_hdr_base *next, *exthdr;
uint8_t proto;
bool done = false;
uint32_t maxlen;
uint8_t proto;
int min_len;

assert(ip6_hdr);
Expand All @@ -594,14 +606,14 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
next = (struct tcpr_ipv6_ext_hdr_base *)((u_char *)ip6_hdr + TCPR_IPV6_H);
proto = ip6_hdr->ip_nh;

while (1) {
while (!done) {
dbgx(3, "Processing proto: 0x%hx", (uint16_t)proto);

switch (proto) {
/* recurse due to v6-in-v6, need to recast next as an IPv6 Header */
case TCPR_IPV6_NH_IPV6:
dbg(3, "recursing due to v6-in-v6");
return get_layer4_v6((ipv6_hdr_t *)next, l3len - min_len);
next = get_layer4_v6((ipv6_hdr_t *)next, l3len - min_len);
break;

/* loop again */
Expand All @@ -612,8 +624,10 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
dbgx(3, "Going deeper due to extension header 0x%02X", proto);
maxlen = l3len - (int)((u_char *)ip6_hdr - (u_char *)next);
exthdr = get_ipv6_next(next, maxlen);
if (exthdr == NULL)
return next;
if (exthdr == NULL) {
done = true;
break;
}
proto = exthdr->ip_nh;
next = exthdr;
break;
Expand All @@ -623,7 +637,8 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
*/
case TCPR_IPV6_NH_FRAGMENT:
case TCPR_IPV6_NH_ESP:
return NULL;
next = NULL;
done = true;
break;

/*
Expand All @@ -633,14 +648,19 @@ get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
if (proto != ip6_hdr->ip_nh) {
dbgx(3, "Returning byte offset of this ext header: %u",
IPV6_EXTLEN_TO_BYTES(next->ip_len));
return (void *)((u_char *)next + IPV6_EXTLEN_TO_BYTES(next->ip_len));
next = (void *)((u_char *)next + IPV6_EXTLEN_TO_BYTES(next->ip_len));
} else {
dbgx(3, "%s", "Returning end of IPv6 Header");
return next;
}
break;

done = true;
} /* switch */
} /* while */

if (!next || (u_char*)next > (u_char*)ip6_hdr + l3len)
return NULL;

return next;
}


Expand Down
6 changes: 5 additions & 1 deletion src/defines.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,11 @@ typedef enum tcpprep_mode_e {
CLIENT_MODE /* second pass through in client (router) mode */
} tcpprep_mode_t;

#define BROADCAST_MAC "\xFF\xFF\xFF\xFF\xFF\xFF"
#define BROADCAST_MAC "\xff\xff\xff\xff\xff\xff"
#define IPV4_MULTICAST_MAC "\x01\x00\x5e\x00\x00\x00"
#define IPV6_MULTICAST_MAC "\x33\x33\x00\x00\x00\x00"
#define IPV4_VRRP "\x00\x00\x50\x00\x01\x00"
#define IPV6_VRRP "\x00\x00\x50\x00\x02\x00"

/* MAC macros for printf */
#define MAC_FORMAT "%02X:%02X:%02X:%02X:%02X:%02X"
Expand Down
4 changes: 0 additions & 4 deletions src/send_packets.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ fast_edit_packet(struct pcap_pkthdr *pkthdr, u_char **pktdata,
if (res < 0)
return res;

packet += l2offset;
l2len -= l2offset;
pkt_len -= l2offset;

assert(l2len > 0);

switch (ether_type) {
Expand Down
41 changes: 18 additions & 23 deletions src/tcpedit/checksum.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static int do_checksum_math(uint16_t *, int);
* Returns -1 on error and 0 on success, 1 on warn
*/
int
do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int payload_len) {
do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int len) {
ipv4_hdr_t *ipv4;
ipv6_hdr_t *ipv6;
tcp_hdr_t *tcp;
Expand All @@ -50,25 +50,20 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int payload_len) {
ipv6 = NULL;
assert(data);

if (!data || payload_len < (int)sizeof(*ipv4) || payload_len > 0xffff) {
tcpedit_setwarn(tcpedit, "%s", "Unable to checksum packet with no L3+ data");
return TCPEDIT_WARN;
if (!data || len <= 0) {
tcpedit_seterr(tcpedit, "%s", "length of data must be > 0");
return TCPEDIT_ERROR;
}

ipv4 = (ipv4_hdr_t *)data;
if (ipv4->ip_v == 6) {
if (payload_len < (int)sizeof(*ipv6)) {
tcpedit_setwarn(tcpedit, "%s", "Unable to checksum IPv6 packet with insufficient data");
return TCPEDIT_WARN;
}

ipv6 = (ipv6_hdr_t *)data;
ipv4 = NULL;

proto = get_ipv6_l4proto(ipv6, payload_len + sizeof(ipv6_hdr_t));
proto = get_ipv6_l4proto(ipv6, len + sizeof(ipv6_hdr_t));
dbgx(3, "layer4 proto is 0x%hx", (uint16_t)proto);

layer = (u_char*)get_layer4_v6(ipv6, payload_len + sizeof(ipv6_hdr_t));
layer = (u_char*)get_layer4_v6(ipv6, len + sizeof(ipv6_hdr_t));
if (!layer) {
tcpedit_setwarn(tcpedit, "%s", "Packet to short for checksum");
return TCPEDIT_WARN;
Expand All @@ -77,14 +72,14 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int payload_len) {
ip_hl = layer - (u_char*)data;
dbgx(3, "ip_hl proto is 0x%d", ip_hl);

payload_len -= (ip_hl - TCPR_IPV6_H);
len -= (ip_hl - TCPR_IPV6_H);
} else {
ip_hl = ipv4->ip_hl << 2;
}

switch (proto) {
case IPPROTO_TCP:
if (payload_len < (int)sizeof(tcp_hdr_t)) {
if (len < (int)sizeof(tcp_hdr_t)) {
tcpedit_setwarn(tcpedit, "%s", "Unable to checksum TCP with insufficient L4 data");
return TCPEDIT_WARN;
}
Expand All @@ -104,13 +99,13 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int payload_len) {
} else {
sum = do_checksum_math((uint16_t *)&ipv4->ip_src, 8);
}
sum += ntohs(IPPROTO_TCP + payload_len);
sum += do_checksum_math((uint16_t *)tcp, payload_len);
sum += ntohs(IPPROTO_TCP + len);
sum += do_checksum_math((uint16_t *)tcp, len);
tcp->th_sum = CHECKSUM_CARRY(sum);
break;

case IPPROTO_UDP:
if (payload_len < (int)sizeof(udp_hdr_t)) {
if (len < (int)sizeof(udp_hdr_t)) {
tcpedit_setwarn(tcpedit, "%s", "Unable to checksum UDP with insufficient L4 data");
return TCPEDIT_WARN;
}
Expand All @@ -124,13 +119,13 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int payload_len) {
} else {
sum = do_checksum_math((uint16_t *)&ipv4->ip_src, 8);
}
sum += ntohs(IPPROTO_UDP + payload_len);
sum += do_checksum_math((uint16_t *)udp, payload_len);
sum += ntohs(IPPROTO_UDP + len);
sum += do_checksum_math((uint16_t *)udp, len);
udp->uh_sum = CHECKSUM_CARRY(sum);
break;

case IPPROTO_ICMP:
if (payload_len < (int)sizeof(icmpv4_hdr_t)) {
if (len < (int)sizeof(icmpv4_hdr_t)) {
tcpedit_setwarn(tcpedit, "%s", "Unable to checksum ICMP with insufficient L4 data");
return TCPEDIT_WARN;
}
Expand All @@ -140,12 +135,12 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int payload_len) {
sum = do_checksum_math((uint16_t *)&ipv6->ip_src, 32);
icmp->icmp_sum = CHECKSUM_CARRY(sum);
}
sum += do_checksum_math((uint16_t *)icmp, payload_len);
sum += do_checksum_math((uint16_t *)icmp, len);
icmp->icmp_sum = CHECKSUM_CARRY(sum);
break;

case IPPROTO_ICMP6:
if (payload_len < (int)sizeof(icmpv6_hdr_t)) {
if (len < (int)sizeof(icmpv6_hdr_t)) {
tcpedit_setwarn(tcpedit, "%s", "Unable to checksum ICMP6 with insufficient L4 data");
return TCPEDIT_WARN;
}
Expand All @@ -154,8 +149,8 @@ do_checksum(tcpedit_t *tcpedit, uint8_t *data, int proto, int payload_len) {
if (ipv6 != NULL) {
sum = do_checksum_math((u_int16_t *)&ipv6->ip_src, 32);
}
sum += ntohs(IPPROTO_ICMP6 + payload_len);
sum += do_checksum_math((u_int16_t *)icmp6, payload_len);
sum += ntohs(IPPROTO_ICMP6 + len);
sum += do_checksum_math((u_int16_t *)icmp6, len);
icmp6->icmp_sum = CHECKSUM_CARRY(sum);
break;

Expand Down
2 changes: 1 addition & 1 deletion src/tcpedit/fuzzing.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ fuzzing(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
caplen = pkthdr->caplen;
plugin = tcpedit->dlt_ctx->encoder;
l2len = plugin->plugin_l2len(ctx, packet, caplen);
l2proto = ntohs(ctx->proto);
l2proto = ntohs(plugin->plugin_proto(ctx, packet, caplen));
if (l2len == -1 || caplen < l2len)
goto done;

Expand Down
22 changes: 17 additions & 5 deletions src/tcpedit/plugins/ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
#include "ethernet.h"

/*
* takes a ptr to an ethernet address and returns
* Takes a ptr to an ethernet address and returns
* 1 if it is unicast or 0 if it is multicast or
* broadcast.
* broadcast. As per RFC7042.
*/
int
is_unicast_ethernet(tcpeditdlt_t *ctx, const u_char *ether)
Expand All @@ -35,12 +35,24 @@ is_unicast_ethernet(tcpeditdlt_t *ctx, const u_char *ether)
assert(ctx);
assert(ether);

/* is broadcast? */
/* ff:ff:ff:ff:ff:ff - broadcast */
if (memcmp(ether, BROADCAST_MAC, ETHER_ADDR_LEN) == 0)
return 0;

/* Multicast addresses' leading octet are odd */
if ((ether[0] & 0x01) == 0x01)
/* 01:00:5e:(00:00:00-7f:ff:ff) - IPv4 Multicast and MLPS Multicast */
if (memcmp(&ether[0], IPV4_MULTICAST_MAC, 3) == 0)
return 0;

/* 33:33 - IPv6 Multicast */
if (memcmp(&ether[0], IPV6_MULTICAST_MAC, 2) == 0)
return 0;

/*
* 00:00:5e:(00:01:00 – 00:01:ff) - IPv4 Virtual Router Redundancy Protocol
* 00:00:5e:(00:02:00 – 00:02:ff) - IPv6 Virtual Router Redundancy Protocol
*/
if (memcmp(&ether[0], IPV4_VRRP, 5) == 0
|| memcmp(&ether[0], IPV6_VRRP, 5) == 0)
return 0;

/* everything else is unicast */
Expand Down
Loading