From 5e852773cac9d065d497ebb6b3aad3687e035f0f Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Tue, 8 Jan 2019 18:41:55 -0500 Subject: [PATCH] os x - setuid helper utility to connect to the bridge interface. --- src/rawnet/rawnetarch_tap.c | 74 ++++++- ...rawnetarch_darwin.c => rawnetarch_vmnet.c} | 202 +----------------- src/rawnet/rawnetarch_vmnet_helper.c | 201 +---------------- src/rawnet/rawnetsupp.c | 191 +++++++++++++++++ src/rawnet/rawnetsupp.h | 3 + 5 files changed, 279 insertions(+), 392 deletions(-) rename src/rawnet/{rawnetarch_darwin.c => rawnetarch_vmnet.c} (52%) diff --git a/src/rawnet/rawnetarch_tap.c b/src/rawnet/rawnetarch_tap.c index 940a74f..a7c7e88 100644 --- a/src/rawnet/rawnetarch_tap.c +++ b/src/rawnet/rawnetarch_tap.c @@ -82,6 +82,12 @@ static int interface_fd = -1; static char *interface_dev = NULL; +static uint8_t interface_mac[6]; +static uint8_t interface_fake_mac[6]; + +static uint8_t *interface_buffer = NULL; +static int interface_buffer_size = 0; + int rawnet_arch_init(void) { interface_fd = -1; return 1; @@ -94,6 +100,18 @@ void rawnet_arch_post_reset(void) { /* NOP */ } +/* memoized buffer for ethernet packets, etc */ +static int make_buffer(int size) { + if (size <= interface_buffer_size) return 0; + if (interface_buffer) free(interface_buffer); + if (size < 1500) size = 1500; /* good mtu size */ + interface_buffer_size = 0; + size *= 2; + interface_buffer = malloc(size); + if (!interface_buffer) return -1; + interface_buffer_size = size; + return 0; +} #if defined(__linux__) /* interface name. default is tap65816. */ @@ -132,6 +150,15 @@ int rawnet_arch_activate(const char *interface_name) { return 0; } + if (rawnet_arch_get_mac(interface_mac) < 0) { + perror("rawnet_arch_get_mac"); + close(fd); + return 0; + } + /* copy mac to fake mac */ + memcpy(interface_fake_mac, interface_mac, 6); + + interface_dev = strdup(interface_name); interface_fd = fd; return 1; @@ -170,6 +197,16 @@ int rawnet_arch_activate(const char *interface_name) { return 0; } + if (rawnet_arch_get_mac(interface_mac) < 0) { + perror("rawnet_arch_get_mac"); + close(fd); + return 0; + } + /* copy mac to fake mac */ + memcpy(interface_fake_mac, interface_mac, 6); + + + interface_dev = strdup(interface_name); interface_fd = fd; return 1; @@ -184,6 +221,10 @@ void rawnet_arch_deactivate(void) { close(interface_fd); free(interface_dev); + free(interface_buffer); + interface_buffer = 0; + interface_buffer_size = 0; + interface_dev = NULL; interface_fd = -1; } @@ -194,6 +235,14 @@ void rawnet_arch_set_mac(const uint8_t mac[6]) { #ifdef RAWNET_DEBUG_ARCH log_message( rawnet_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); #endif + + memcpy(interface_fake_mac, mac, 6); + + /* in theory, SIOCSIFHWADDR (linux) or SIOCSIFADDR (bsd) will set the mac address. */ + /* in testing, (linux) I get EBUSY or EOPNOTSUPP */ + + +#if 0 if (interface_fd < 0) return; @@ -209,8 +258,7 @@ void rawnet_arch_set_mac(const uint8_t mac[6]) { if (ioctl(interface_fd, SIOCSIFADDR, mac) < 0) perror("ioctl(SIOCSIFADDR)"); #endif - - +#endif } void rawnet_arch_set_hashfilter(const uint32_t hash_mask[2]) { /* NOP */ @@ -225,11 +273,29 @@ void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver) { } int rawnet_arch_read(void *buffer, int nbyte) { - return read(interface_fd, buffer, nbyte); + int ok; + + if (make_buffer(nbyte) < 0) return -1; + + ok = read(interface_fd, interface_buffer, nbyte); + if (ok <= 0) return -1; + + rawnet_fix_incoming_packet(interface_buffer, ok, interface_mac, interface_fake_mac); + memcpy(buffer, interface_buffer, ok); + return ok; } int rawnet_arch_write(const void *buffer, int nbyte) { - return write(interface_fd, buffer, nbyte); + int ok; + + if (make_buffer(nbyte) < 0) return -1; + + + memcpy(interface_buffer, buffer, nbyte); + rawnet_fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac); + + ok = write(interface_fd, interface_buffer, nbyte); + return ok; } diff --git a/src/rawnet/rawnetarch_darwin.c b/src/rawnet/rawnetarch_vmnet.c similarity index 52% rename from src/rawnet/rawnetarch_darwin.c rename to src/rawnet/rawnetarch_vmnet.c index 5a0c0a1..8a1cbb1 100644 --- a/src/rawnet/rawnetarch_darwin.c +++ b/src/rawnet/rawnetarch_vmnet.c @@ -16,8 +16,6 @@ #include "rawnetsupp.h" -static const uint8_t broadcast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - static interface_ref interface; static uint8_t interface_mac[6]; static uint8_t interface_fake_mac[6]; @@ -90,6 +88,10 @@ int rawnet_arch_activate(const char *interface_name) { if (interface_status == VMNET_SUCCESS) { interface_buffer = (uint8_t *)malloc(interface_packet_size); + + /* copy mac to fake mac */ + memcpy(interface_fake_mac, interface_mac, 6); + } else { log_message(rawnet_arch_log, "vmnet_start_interface failed"); if (interface) { @@ -151,195 +153,6 @@ void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver) { } - - -enum { - eth_dest = 0, // destination address - eth_src = 6, // source address - eth_type = 12, // packet type - eth_data = 14, // packet data -}; - -enum { - ip_ver_ihl = 0, - ip_tos = 1, - ip_len = 2, - ip_id = 4, - ip_frag = 6, - ip_ttl = 8, - ip_proto = 9, - ip_header_cksum = 10, - ip_src = 12, - ip_dest = 16, - ip_data = 20, -}; - -enum { - udp_source = 0, // source port - udp_dest = 2, // destination port - udp_len = 4, // length - udp_cksum = 6, // checksum - udp_data = 8, // total length udp header -}; - -enum { - bootp_op = 0, // operation - bootp_hw = 1, // hardware type - bootp_hlen = 2, // hardware len - bootp_hp = 3, // hops - bootp_transid = 4, // transaction id - bootp_secs = 8, // seconds since start - bootp_flags = 10, // flags - bootp_ipaddr = 12, // ip address knwon by client - bootp_ipclient = 16, // client ip from server - bootp_ipserver = 20, // server ip - bootp_ipgateway = 24, // gateway ip - bootp_client_hrd = 28, // client mac address - bootp_spare = 34, - bootp_host = 44, - bootp_fname = 108, - bootp_data = 236, // total length bootp packet -}; - -enum { - arp_hw = 14, // hw type (eth = 0001) - arp_proto = 16, // protocol (ip = 0800) - arp_hwlen = 18, // hw addr len (eth = 06) - arp_protolen = 19, // proto addr len (ip = 04) - arp_op = 20, // request = 0001, reply = 0002 - arp_shw = 22, // sender hw addr - arp_sp = 28, // sender proto addr - arp_thw = 32, // target hw addr - arp_tp = 38, // target protoaddr - arp_data = 42, // total length of packet -}; - -enum { - dhcp_discover = 1, - dhcp_offer = 2, - dhcp_request = 3, - dhcp_decline = 4, - dhcp_pack = 5, - dhcp_nack = 6, - dhcp_release = 7, - dhcp_inform = 8, -}; - -static uint8_t oo[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static uint8_t ff[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - -static int is_arp(const uint8_t *packet, unsigned size) { - return size == arp_data - && packet[12] == 0x08 && packet[13] == 0x06 /* ARP */ - && packet[14] == 0x00 && packet[15] == 0x01 /* ethernet */ - && packet[16] == 0x08 && packet[17] == 0x00 /* ipv4 */ - && packet[18] == 0x06 /* hardware size */ - && packet[19] == 0x04 /* protocol size */ - ; -} - -static int is_broadcast(const uint8_t *packet, unsigned size) { - return !memcmp(packet + 0, ff, 6); -} - -static int is_unicast(const uint8_t *packet, unsigned size) { - return (*packet & 0x01) == 0; -} - -static int is_multicast(const uint8_t *packet, unsigned size) { - return (*packet & 0x01) == 0x01 && !is_broadcast(packet, size); -} - -static int is_dhcp_out(const uint8_t *packet, unsigned size) { - static uint8_t cookie[] = { 0x63, 0x82, 0x53, 0x63 }; - return size >= 282 - //&& !memcmp(&packet[0], ff, 6) /* broadcast */ - && packet[12] == 0x08 && packet[13] == 0x00 - && packet[14] == 0x45 /* version 4 */ - && packet[23] == 0x11 /* UDP */ - //&& !memcmp(&packet[26], oo, 4) /* source ip */ - //&& !memcmp(&packet[30], ff, 4) /* dest ip */ - && packet[34] == 0x00 && packet[35] == 0x44 /* source port */ - && packet[36] == 0x00 && packet[37] == 0x43 /* dest port */ - //&& packet[44] == 0x01 /* dhcp boot req */ - && packet[43] == 0x01 /* ethernet */ - && packet[44] == 0x06 /* 6 byte mac */ - && !memcmp(&packet[278], cookie, 4) - ; -} - - -static int is_dhcp_in(const uint8_t *packet, unsigned size) { - static uint8_t cookie[] = { 0x63, 0x82, 0x53, 0x63 }; - return size >= 282 - //&& !memcmp(&packet[0], ff, 6) /* broadcast */ - && packet[12] == 0x08 && packet[13] == 0x00 - && packet[14] == 0x45 /* version 4 */ - && packet[23] == 0x11 /* UDP */ - //&& !memcmp(&packet[26], oo, 4) /* source ip */ - //&& !memcmp(&packet[30], ff, 4) /* dest ip */ - && packet[34] == 0x00 && packet[35] == 0x43 /* source port */ - && packet[36] == 0x00 && packet[37] == 0x44 /* dest port */ - //&& packet[44] == 0x01 /* dhcp boot req */ - && packet[43] == 0x01 /* ethernet */ - && packet[44] == 0x06 /* 6 byte mac */ - && !memcmp(&packet[278], cookie, 4) - ; -} - -static unsigned ip_checksum(const uint8_t *packet) { - unsigned x = 0; - unsigned i; - for (i = 0; i < ip_data; i += 2) { - if (i == ip_header_cksum) continue; - x += packet[eth_data + i + 0 ] << 8; - x += packet[eth_data + i + 1]; - } - - /* add the carry */ - x += x >> 16; - x &= 0xffff; - return ~x & 0xffff; -} - -static void fix_incoming_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]) { - - if (memcmp(packet + 0, real_mac, 6) == 0) - memcpy(packet + 0, fake_mac, 6); - - /* dhcp request - fix the hardware address */ - if (is_unicast(packet, size) && is_dhcp_in(packet, size)) { - if (!memcmp(packet + 70, real_mac, 6)) - memcpy(packet + 70, fake_mac, 6); - return; - } - -} - -static void fix_outgoing_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]) { - - - - if (memcmp(packet + 6, fake_mac, 6) == 0) - memcpy(packet + 6, real_mac, 6); - - if (is_arp(packet, size)) { - /* sender mac address */ - if (!memcmp(packet + 22, fake_mac, 6)) - memcpy(packet + 22, real_mac, 6); - return; - } - - /* dhcp request - fix the hardware address */ - if (is_broadcast(packet, size) && is_dhcp_out(packet, size)) { - - if (!memcmp(packet + 70, fake_mac, 6)) - memcpy(packet + 70, real_mac, 6); - return; - } - -} - int rawnet_arch_read(void *buffer, int nbyte) { int count = 1; @@ -366,10 +179,11 @@ int rawnet_arch_read(void *buffer, int nbyte) { return 0; } - fix_incoming_packet(interface_buffer, v.vm_pkt_size, interface_mac, interface_fake_mac); + rawnet_fix_incoming_packet(interface_buffer, v.vm_pkt_size, interface_mac, interface_fake_mac); // iov.iov_len is not updated with the read count, apparently. - if (!is_multicast(interface_buffer, v.vm_pkt_size)) { /* multicast crap */ + /* don't sebug multicast packets */ + if (interface_buffer[0] == 0xff || (interface_buffer[0] & 0x01) == 0 ) { fprintf(stderr, "\nrawnet_arch_receive: %u\n", (unsigned)v.vm_pkt_size); rawnet_hexdump(interface_buffer, v.vm_pkt_size); } @@ -396,7 +210,7 @@ int rawnet_arch_write(const void *buffer, int nbyte) { /* copy the buffer and fix the source mac address. */ memcpy(interface_buffer, buffer, nbyte); - fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac); + rawnet_fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac); iov.iov_base = interface_buffer; iov.iov_len = nbyte; diff --git a/src/rawnet/rawnetarch_vmnet_helper.c b/src/rawnet/rawnetarch_vmnet_helper.c index 2e8a9cc..7b1ec93 100644 --- a/src/rawnet/rawnetarch_vmnet_helper.c +++ b/src/rawnet/rawnetarch_vmnet_helper.c @@ -28,8 +28,6 @@ enum { }; #define MAKE_MSG(msg, extra) (msg | ((extra) << 8)) -static const uint8_t broadcast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - static uint8_t interface_mac[6]; static uint8_t interface_fake_mac[6]; static uint32_t interface_mtu; @@ -260,6 +258,9 @@ int rawnet_arch_activate(const char *interface_name) { ok = safe_readv(iov, 3); if (ok != 6 + 4 + 4) goto fail; + /* copy mac to fake mac */ + memcpy(interface_fake_mac, interface_mac, 6); + /* sanity check */ /* expect MTU = 1500, packet_size = 1518 */ if (interface_packet_size < 256) { @@ -318,195 +319,6 @@ void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver) { - -enum { - eth_dest = 0, // destination address - eth_src = 6, // source address - eth_type = 12, // packet type - eth_data = 14, // packet data -}; - -enum { - ip_ver_ihl = 0, - ip_tos = 1, - ip_len = 2, - ip_id = 4, - ip_frag = 6, - ip_ttl = 8, - ip_proto = 9, - ip_header_cksum = 10, - ip_src = 12, - ip_dest = 16, - ip_data = 20, -}; - -enum { - udp_source = 0, // source port - udp_dest = 2, // destination port - udp_len = 4, // length - udp_cksum = 6, // checksum - udp_data = 8, // total length udp header -}; - -enum { - bootp_op = 0, // operation - bootp_hw = 1, // hardware type - bootp_hlen = 2, // hardware len - bootp_hp = 3, // hops - bootp_transid = 4, // transaction id - bootp_secs = 8, // seconds since start - bootp_flags = 10, // flags - bootp_ipaddr = 12, // ip address knwon by client - bootp_ipclient = 16, // client ip from server - bootp_ipserver = 20, // server ip - bootp_ipgateway = 24, // gateway ip - bootp_client_hrd = 28, // client mac address - bootp_spare = 34, - bootp_host = 44, - bootp_fname = 108, - bootp_data = 236, // total length bootp packet -}; - -enum { - arp_hw = 14, // hw type (eth = 0001) - arp_proto = 16, // protocol (ip = 0800) - arp_hwlen = 18, // hw addr len (eth = 06) - arp_protolen = 19, // proto addr len (ip = 04) - arp_op = 20, // request = 0001, reply = 0002 - arp_shw = 22, // sender hw addr - arp_sp = 28, // sender proto addr - arp_thw = 32, // target hw addr - arp_tp = 38, // target protoaddr - arp_data = 42, // total length of packet -}; - -enum { - dhcp_discover = 1, - dhcp_offer = 2, - dhcp_request = 3, - dhcp_decline = 4, - dhcp_pack = 5, - dhcp_nack = 6, - dhcp_release = 7, - dhcp_inform = 8, -}; - -static uint8_t oo[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static uint8_t ff[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - -static int is_arp(const uint8_t *packet, unsigned size) { - return size == arp_data - && packet[12] == 0x08 && packet[13] == 0x06 /* ARP */ - && packet[14] == 0x00 && packet[15] == 0x01 /* ethernet */ - && packet[16] == 0x08 && packet[17] == 0x00 /* ipv4 */ - && packet[18] == 0x06 /* hardware size */ - && packet[19] == 0x04 /* protocol size */ - ; -} - -static int is_broadcast(const uint8_t *packet, unsigned size) { - return !memcmp(packet + 0, ff, 6); -} - -static int is_unicast(const uint8_t *packet, unsigned size) { - return (*packet & 0x01) == 0; -} - -static int is_multicast(const uint8_t *packet, unsigned size) { - return (*packet & 0x01) == 0x01 && !is_broadcast(packet, size); -} - -static int is_dhcp_out(const uint8_t *packet, unsigned size) { - static uint8_t cookie[] = { 0x63, 0x82, 0x53, 0x63 }; - return size >= 282 - //&& !memcmp(&packet[0], ff, 6) /* broadcast */ - && packet[12] == 0x08 && packet[13] == 0x00 - && packet[14] == 0x45 /* version 4 */ - && packet[23] == 0x11 /* UDP */ - //&& !memcmp(&packet[26], oo, 4) /* source ip */ - //&& !memcmp(&packet[30], ff, 4) /* dest ip */ - && packet[34] == 0x00 && packet[35] == 0x44 /* source port */ - && packet[36] == 0x00 && packet[37] == 0x43 /* dest port */ - //&& packet[44] == 0x01 /* dhcp boot req */ - && packet[43] == 0x01 /* ethernet */ - && packet[44] == 0x06 /* 6 byte mac */ - && !memcmp(&packet[278], cookie, 4) - ; -} - - -static int is_dhcp_in(const uint8_t *packet, unsigned size) { - static uint8_t cookie[] = { 0x63, 0x82, 0x53, 0x63 }; - return size >= 282 - //&& !memcmp(&packet[0], ff, 6) /* broadcast */ - && packet[12] == 0x08 && packet[13] == 0x00 - && packet[14] == 0x45 /* version 4 */ - && packet[23] == 0x11 /* UDP */ - //&& !memcmp(&packet[26], oo, 4) /* source ip */ - //&& !memcmp(&packet[30], ff, 4) /* dest ip */ - && packet[34] == 0x00 && packet[35] == 0x43 /* source port */ - && packet[36] == 0x00 && packet[37] == 0x44 /* dest port */ - //&& packet[44] == 0x01 /* dhcp boot req */ - && packet[43] == 0x01 /* ethernet */ - && packet[44] == 0x06 /* 6 byte mac */ - && !memcmp(&packet[278], cookie, 4) - ; -} - -static unsigned ip_checksum(const uint8_t *packet) { - unsigned x = 0; - unsigned i; - for (i = 0; i < ip_data; i += 2) { - if (i == ip_header_cksum) continue; - x += packet[eth_data + i + 0 ] << 8; - x += packet[eth_data + i + 1]; - } - - /* add the carry */ - x += x >> 16; - x &= 0xffff; - return ~x & 0xffff; -} - -static void fix_incoming_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]) { - - if (memcmp(packet + 0, real_mac, 6) == 0) - memcpy(packet + 0, fake_mac, 6); - - /* dhcp request - fix the hardware address */ - if (is_unicast(packet, size) && is_dhcp_in(packet, size)) { - if (!memcmp(packet + 70, real_mac, 6)) - memcpy(packet + 70, fake_mac, 6); - return; - } - -} - -static void fix_outgoing_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]) { - - - - if (memcmp(packet + 6, fake_mac, 6) == 0) - memcpy(packet + 6, real_mac, 6); - - if (is_arp(packet, size)) { - /* sender mac address */ - if (!memcmp(packet + 22, fake_mac, 6)) - memcpy(packet + 22, real_mac, 6); - return; - } - - /* dhcp request - fix the hardware address */ - if (is_broadcast(packet, size) && is_dhcp_out(packet, size)) { - - if (!memcmp(packet + 70, fake_mac, 6)) - memcpy(packet + 70, real_mac, 6); - return; - } - -} - - int rawnet_arch_read(void *buffer, int nbyte) { @@ -551,9 +363,10 @@ int rawnet_arch_read(void *buffer, int nbyte) { if (ok != xfer) goto fail; - fix_incoming_packet(interface_buffer, xfer, interface_mac, interface_fake_mac); + rawnet_fix_incoming_packet(interface_buffer, xfer, interface_mac, interface_fake_mac); - if (!is_multicast(interface_buffer, xfer)) { /* multicast crap */ + /* don't sebug multicast packets */ + if (interface_buffer[0] == 0xff || (interface_buffer[0] & 0x01) == 0 ) { fprintf(stderr, "\nrawnet_arch_receive: %u\n", (unsigned)xfer); rawnet_hexdump(interface_buffer, xfer); } @@ -592,7 +405,7 @@ int rawnet_arch_write(const void *buffer, int nbyte) { /* copy the buffer and fix the source mac address. */ memcpy(interface_buffer, buffer, nbyte); - fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac); + rawnet_fix_outgoing_packet(interface_buffer, nbyte, interface_mac, interface_fake_mac); fprintf(stderr, "\nrawnet_arch_transmit: %u\n", (unsigned)nbyte); diff --git a/src/rawnet/rawnetsupp.c b/src/rawnet/rawnetsupp.c index 49d18b2..5fb6db8 100644 --- a/src/rawnet/rawnetsupp.c +++ b/src/rawnet/rawnetsupp.c @@ -179,3 +179,194 @@ void rawnet_hexdump(const void *what, int count) { } } } + + + + + +enum { + eth_dest = 0, // destination address + eth_src = 6, // source address + eth_type = 12, // packet type + eth_data = 14, // packet data +}; + +enum { + ip_ver_ihl = 0, + ip_tos = 1, + ip_len = 2, + ip_id = 4, + ip_frag = 6, + ip_ttl = 8, + ip_proto = 9, + ip_header_cksum = 10, + ip_src = 12, + ip_dest = 16, + ip_data = 20, +}; + +enum { + udp_source = 0, // source port + udp_dest = 2, // destination port + udp_len = 4, // length + udp_cksum = 6, // checksum + udp_data = 8, // total length udp header +}; + +enum { + bootp_op = 0, // operation + bootp_hw = 1, // hardware type + bootp_hlen = 2, // hardware len + bootp_hp = 3, // hops + bootp_transid = 4, // transaction id + bootp_secs = 8, // seconds since start + bootp_flags = 10, // flags + bootp_ipaddr = 12, // ip address knwon by client + bootp_ipclient = 16, // client ip from server + bootp_ipserver = 20, // server ip + bootp_ipgateway = 24, // gateway ip + bootp_client_hrd = 28, // client mac address + bootp_spare = 34, + bootp_host = 44, + bootp_fname = 108, + bootp_data = 236, // total length bootp packet +}; + +enum { + arp_hw = 14, // hw type (eth = 0001) + arp_proto = 16, // protocol (ip = 0800) + arp_hwlen = 18, // hw addr len (eth = 06) + arp_protolen = 19, // proto addr len (ip = 04) + arp_op = 20, // request = 0001, reply = 0002 + arp_shw = 22, // sender hw addr + arp_sp = 28, // sender proto addr + arp_thw = 32, // target hw addr + arp_tp = 38, // target protoaddr + arp_data = 42, // total length of packet +}; + +enum { + dhcp_discover = 1, + dhcp_offer = 2, + dhcp_request = 3, + dhcp_decline = 4, + dhcp_pack = 5, + dhcp_nack = 6, + dhcp_release = 7, + dhcp_inform = 8, +}; + +static uint8_t oo[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static uint8_t ff[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +static int is_arp(const uint8_t *packet, unsigned size) { + return size == arp_data + && packet[12] == 0x08 && packet[13] == 0x06 /* ARP */ + && packet[14] == 0x00 && packet[15] == 0x01 /* ethernet */ + && packet[16] == 0x08 && packet[17] == 0x00 /* ipv4 */ + && packet[18] == 0x06 /* hardware size */ + && packet[19] == 0x04 /* protocol size */ + ; +} + +static int is_broadcast(const uint8_t *packet, unsigned size) { + return !memcmp(packet + 0, ff, 6); +} + +static int is_unicast(const uint8_t *packet, unsigned size) { + return (*packet & 0x01) == 0; +} + +static int is_multicast(const uint8_t *packet, unsigned size) { + return (*packet & 0x01) == 0x01 && !is_broadcast(packet, size); +} + +static int is_dhcp_out(const uint8_t *packet, unsigned size) { + static uint8_t cookie[] = { 0x63, 0x82, 0x53, 0x63 }; + return size >= 282 + //&& !memcmp(&packet[0], ff, 6) /* broadcast */ + && packet[12] == 0x08 && packet[13] == 0x00 + && packet[14] == 0x45 /* version 4 */ + && packet[23] == 0x11 /* UDP */ + //&& !memcmp(&packet[26], oo, 4) /* source ip */ + //&& !memcmp(&packet[30], ff, 4) /* dest ip */ + && packet[34] == 0x00 && packet[35] == 0x44 /* source port */ + && packet[36] == 0x00 && packet[37] == 0x43 /* dest port */ + //&& packet[44] == 0x01 /* dhcp boot req */ + && packet[43] == 0x01 /* ethernet */ + && packet[44] == 0x06 /* 6 byte mac */ + && !memcmp(&packet[278], cookie, 4) + ; +} + + +static int is_dhcp_in(const uint8_t *packet, unsigned size) { + static uint8_t cookie[] = { 0x63, 0x82, 0x53, 0x63 }; + return size >= 282 + //&& !memcmp(&packet[0], ff, 6) /* broadcast */ + && packet[12] == 0x08 && packet[13] == 0x00 + && packet[14] == 0x45 /* version 4 */ + && packet[23] == 0x11 /* UDP */ + //&& !memcmp(&packet[26], oo, 4) /* source ip */ + //&& !memcmp(&packet[30], ff, 4) /* dest ip */ + && packet[34] == 0x00 && packet[35] == 0x43 /* source port */ + && packet[36] == 0x00 && packet[37] == 0x44 /* dest port */ + //&& packet[44] == 0x01 /* dhcp boot req */ + && packet[43] == 0x01 /* ethernet */ + && packet[44] == 0x06 /* 6 byte mac */ + && !memcmp(&packet[278], cookie, 4) + ; +} + +static unsigned ip_checksum(const uint8_t *packet) { + unsigned x = 0; + unsigned i; + for (i = 0; i < ip_data; i += 2) { + if (i == ip_header_cksum) continue; + x += packet[eth_data + i + 0 ] << 8; + x += packet[eth_data + i + 1]; + } + + /* add the carry */ + x += x >> 16; + x &= 0xffff; + return ~x & 0xffff; +} + +void rawnet_fix_incoming_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]) { + + if (memcmp(packet + 0, real_mac, 6) == 0) + memcpy(packet + 0, fake_mac, 6); + + /* dhcp request - fix the hardware address */ + if (is_unicast(packet, size) && is_dhcp_in(packet, size)) { + if (!memcmp(packet + 70, real_mac, 6)) + memcpy(packet + 70, fake_mac, 6); + return; + } + +} + +void rawnet_fix_outgoing_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]) { + + + + if (memcmp(packet + 6, fake_mac, 6) == 0) + memcpy(packet + 6, real_mac, 6); + + if (is_arp(packet, size)) { + /* sender mac address */ + if (!memcmp(packet + 22, fake_mac, 6)) + memcpy(packet + 22, real_mac, 6); + return; + } + + /* dhcp request - fix the hardware address */ + if (is_broadcast(packet, size) && is_dhcp_out(packet, size)) { + + if (!memcmp(packet + 70, fake_mac, 6)) + memcpy(packet + 70, real_mac, 6); + return; + } + +} diff --git a/src/rawnet/rawnetsupp.h b/src/rawnet/rawnetsupp.h index a3d4f34..412e14f 100644 --- a/src/rawnet/rawnetsupp.h +++ b/src/rawnet/rawnetsupp.h @@ -53,6 +53,9 @@ extern int util_string_set(char **str, const char *new_value); extern unsigned long crc32_buf(const char *buffer, unsigned int len); extern void rawnet_hexdump(const void *what, int count); +extern void rawnet_fix_incoming_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]); +extern void rawnet_fix_outgoing_packet(uint8_t *packet, unsigned size, const uint8_t real_mac[6], const uint8_t fake_mac[6]); + #define log_message(level,...) do { fprintf(stderr,__VA_ARGS__); fputs("\n", stderr); } while (0) #endif