From: Ralph Ronnquist Date: Mon, 17 Feb 2025 06:23:14 +0000 (+1100) Subject: handle both ipv4 and ipv6 X-Git-Tag: 0.1~8 X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=18c8fba9dc49aa471bb07d73dd66773b7c934564;p=rrq%2Fnfblocker.git handle both ipv4 and ipv6 --- diff --git a/src/nfblocker.c b/src/nfblocker.c index b8b979c..b889d36 100644 --- a/src/nfblocker.c +++ b/src/nfblocker.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -29,38 +31,66 @@ static u_int32_t get_packet_id(struct nfq_data *tb) { return ( ph )? ntohl( ph->packet_id ) : 0; } -// Payload headers -struct headers { - struct ip first; +struct ipv4_pkt { + struct ip first; // .ip_dst[4 bytes] struct tcphdr second; - //unsigned char pad[12]; // ?? }; -///////// Debugging +struct ipv6_pkt { + struct ip6_hdr first; // .ip6_dst[16 bytes] + struct tcphdr second; +}; -static unsigned char *tell_ip(u_int32_t ip) { - static unsigned char THEIP[20]; - unsigned char *b = (unsigned char *)&ip; - sprintf( (char*) THEIP, "%d.%d.%d.%d%c", b[0], b[1], b[2], b[3], 0 ); - return THEIP; +// Payload packet +struct packet { + union { + unsigned int packet_type:4; // 4 or 6 + struct ipv4_pkt packet4; + struct ipv6_pkt packet6; + } p; + //unsigned char pad[12]; // ?? +}; + +static struct packet *get_headerP(unsigned char *data) { + return (struct packet *) data; } -static u_int32_t get_dest_ip4(unsigned char *data) { - struct headers *p = (struct headers *) data; - return p->first.ip_dst.s_addr; +///////// Debugging +//const char *inet_ntop(int af, const void *restrict src, +// char dst[restrict .size], socklen_t size); + +static const char *tell_ip(struct packet *ip) { + static char THEIP[200]; + switch ( ip->p.packet_type ) { + case 4: + return inet_ntop( AF_INET, &ip->p.packet4.first.ip_dst, THEIP, 200 ); + case 6: + return inet_ntop( AF_INET6, &ip->p.packet6.first.ip6_dst, THEIP, 200 ); + } + return strcpy( THEIP, "???" ); } /** * Review payload packet payload */ static void view_payload(unsigned char *data,int length) { - u_int32_t ip4 = get_dest_ip4( data ); - u_int16_t port = ntohs( ((struct headers *) data )->second.th_dport ); - u_int8_t syn = sizeof( struct headers ); - unsigned char *body = data ;//+ sizeof( struct headers ); + struct packet *header = get_headerP( data ); + u_int16_t port = 0; + u_int8_t syn = 0; + unsigned char *body = data ;//+ sizeof( struct packet ); + switch ( header->p.packet_type ) { + case 4: + port = ntohs( ((struct ipv4_pkt *) data )->second.th_dport ); + syn = sizeof( struct ipv4_pkt ); + break; + case 6: + port = ntohs( ((struct ipv6_pkt *) data )->second.th_dport ); + syn = sizeof( struct ipv6_pkt ); + break; + } #define END 400 unsigned char * end = body + ( ( length > END )? END : length ); - fprintf( stderr, "%s %d %d %d ", tell_ip( ip4 ), syn, port, length ); + fprintf( stderr, "%s %d %d %d ", tell_ip( header ), syn, port, length ); while ( body < end ) { unsigned char c = *body++; if ( c < ' ' || c >= 127 || 1 ) { @@ -81,7 +111,17 @@ static unsigned char buffer[1000]; */ static unsigned char *ssl_host(unsigned char *data,int length) { // Check that it's a "Client Hello" message - unsigned char *p = data + sizeof( struct headers ) + 12; + unsigned char *p; + switch ( ((struct packet *) data)->p.packet_type ) { + case 4: + p = data + sizeof( struct ipv4_pkt ) + 12; //?? + break; + case 6: + p = data + sizeof( struct ipv6_pkt ) + 0; //?? + break; + default: + return 0; + } if ( p[0] != 0x16 || p[1] != 0x03 || p[5] != 0x01 || p[6] != 0x00 ) { return 0; } @@ -127,7 +167,17 @@ static unsigned char *ssl_host(unsigned char *data,int length) { * "Host:" attribute. */ static unsigned char *http_host(unsigned char *data,int length) { - unsigned char *body = data + sizeof( struct headers ); + unsigned char *body = data + sizeof( struct packet ); + switch ( ((struct packet *) data)->p.packet_type ) { + case 4: + body = data + sizeof( struct ipv4_pkt ); + break; + case 6: + body = data + sizeof( struct ipv6_pkt ); + break; + default: + return 0; + } if ( ( strncmp( (char*) body, "GET ", 4 ) != 0 ) && ( strncmp( (char*) body, "POST ", 5 ) != 0 ) ) { return 0; @@ -174,19 +224,19 @@ static int cb( unsigned char *data; int length = nfq_get_payload( nfa, &data); int verdict = NF_ACCEPT; - u_int32_t ip4 = get_dest_ip4( data ); + struct packet *header = get_headerP( data ); #if 0 - fprintf( stderr, "PKT %s %d\n", tell_ip( ip4 ), length ); + fprintf( stderr, "PKT %s %d\n", tell_ip( header ), length ); #endif if ( length >= 100 ) { unsigned char *host = http_host( data, length ); #if 1 - fprintf( stderr, "HTTP HOST %s %s\n", tell_ip( ip4 ), host ); + fprintf( stderr, "HTTP HOST %s %s\n", tell_ip( header ), host ); #endif if ( host == 0 ) { host = ssl_host( data, length ); #if 1 - fprintf( stderr, "SSL HOST %s %s\n", tell_ip( ip4 ), host ); + fprintf( stderr, "SSL HOST %s %s\n", tell_ip( header ), host ); #endif } if ( host ) { @@ -196,7 +246,7 @@ static int cb( add_cache( host, ix ); #if 1 fprintf( stderr, "%s %d %s ** %d\n", - tell_ip( ip4 ), hash_code( host ), host, ix ); + tell_ip( header ), hash_code( host ), host, ix ); #endif if ( ix > 0 ) { verdict = NF_DROP;