mirror of
https://github.com/digarok/gsplus.git
synced 2025-02-17 11:31:11 +00:00
os x - setuid helper utility to connect to the bridge interface.
This commit is contained in:
parent
4a5d6effd5
commit
5e852773ca
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user