cleanup and polish master 0.1
authorRalph Ronnquist <rrq@rrq.au>
Tue, 18 Feb 2025 13:22:58 +0000 (00:22 +1100)
committerRalph Ronnquist <rrq@rrq.au>
Tue, 18 Feb 2025 13:22:58 +0000 (00:22 +1100)
README.adoc
src/blockdomains.c
src/cache.c
src/database.c

index 6fe912d81e6477a91a5b1963a83c6be83133677c..81cedcdab6ad4a2878cc0fcc3189a464805c6bff 100644 (file)
@@ -47,7 +47,7 @@ some  other useful files
 
 == Setup and Confguration
 
 
 == Setup and Confguration
 
-The blockdomains utility uses blocklist files that nominates the
+The blockdomains utility uses block list files that nominate the
 domains to block. Control scripting supports the notion of a
 configuration root directory `/etc/blockdomains/` with two sub
 direcotries `acl/` and `blocked/`. The idea is that `acl/` contains
 domains to block. Control scripting supports the notion of a
 configuration root directory `/etc/blockdomains/` with two sub
 direcotries `acl/` and `blocked/`. The idea is that `acl/` contains
index 046e5923f9a9f8a659ade6ebb31f10d1b58d15e9..a8f144b1aafc40bdd74f29bcf5d64e1609bcaa1a 100644 (file)
@@ -9,15 +9,20 @@
 #include <string.h>
 #include <unistd.h>
 #include <linux/netfilter.h>            /* for NF_ACCEPT */
 #include <string.h>
 #include <unistd.h>
 #include <linux/netfilter.h>            /* for NF_ACCEPT */
-
 #include <libnetfilter_queue/libnetfilter_queue.h>
 
 #include <libnetfilter_queue/libnetfilter_queue.h>
 
-// Caching of verdicts
+/**
+ * This file implements the overall program logic by setting up a
+ * netfilter queue callback for analysing packets and make an ACCEPT
+ * or REJECT verdict for them.
+ */
+
+// API for caching of verdicts
 unsigned int lookup_cache(unsigned char *domain);
 void add_cache(unsigned char *domain,unsigned int ix);
 int hash_code(unsigned char *domain);
 
 unsigned int lookup_cache(unsigned char *domain);
 void add_cache(unsigned char *domain,unsigned int ix);
 int hash_code(unsigned char *domain);
 
-// BAD domains database
+// API for BAD domains database
 unsigned int check_domain(unsigned char *domain);
 void load_domains(char *file);
 void start_domain_database_loading(void);
 unsigned int check_domain(unsigned char *domain);
 void load_domains(char *file);
 void start_domain_database_loading(void);
@@ -31,33 +36,39 @@ static u_int32_t get_packet_id(struct nfq_data *tb) {
     return ( ph )? ntohl( ph->packet_id ) : 0;
 }
 
     return ( ph )? ntohl( ph->packet_id ) : 0;
 }
 
+/**
+ * Packet header if ipv4 packet.
+ */
 struct ipv4_pkt {
     struct ip first;          // .ip_dst[4 bytes]
     struct tcphdr second;
 };
 
 struct ipv4_pkt {
     struct ip first;          // .ip_dst[4 bytes]
     struct tcphdr second;
 };
 
+/**
+ * Packet header if ipv6 packet.
+ */
 struct ipv6_pkt {
     struct ip6_hdr first;     // .ip6_dst[16 bytes]
     struct tcphdr second;
 };
 
 struct ipv6_pkt {
     struct ip6_hdr first;     // .ip6_dst[16 bytes]
     struct tcphdr second;
 };
 
-// Payload packet
+/**
+ * Convenience type for network packets of undetermined family.
+ */
 struct packet {
     union {
        struct ipv4_pkt pkt4;
        struct ipv6_pkt pkt6;
     } p;
 struct packet {
     union {
        struct ipv4_pkt pkt4;
        struct ipv6_pkt pkt6;
     } p;
-    //unsigned char pad[12]; // ??
 };
 
 };
 
+/**
+ * Locates the header of a packet byte blob.
+ */
 static struct packet *get_headerP(unsigned char *data) {
     return (struct packet *) data;
 }
 
 static struct packet *get_headerP(unsigned char *data) {
     return (struct packet *) data;
 }
 
-///////// 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.pkt4.first.ip_v ) {
 static const char *tell_ip(struct packet *ip) {
     static char THEIP[200];
     switch ( ip->p.pkt4.first.ip_v ) {
@@ -225,34 +236,20 @@ static int cb(
     int length = nfq_get_payload( nfa, &data);
     int verdict = NF_ACCEPT;
     struct packet *header = get_headerP( data );
     int length = nfq_get_payload( nfa, &data);
     int verdict = NF_ACCEPT;
     struct packet *header = get_headerP( data );
-#if 0
-    fprintf( stderr, "PKT %s %d\n", tell_ip( header ), length );
-#endif
     if ( length >= 100 ) {
        unsigned char *host = http_host( data, length );
     if ( length >= 100 ) {
        unsigned char *host = http_host( data, length );
-#if 1
-       if ( host ) {
-           fprintf( stderr, "HTTP HOST %s %s\n", tell_ip( header ), host );
-       }
-#endif
        if ( host == 0 ) {
            host = ssl_host( data, length );
        if ( host == 0 ) {
            host = ssl_host( data, length );
-#if 1
-           if ( host ) {
-               fprintf( stderr, "SSL HOST %s %s\n", tell_ip( header ), host );
-           }
-#endif
        }
        if ( host ) {
            int i = lookup_cache( host );
            if ( i < 0 ) {
                unsigned int ix = check_domain( host );
                add_cache( host, ix );
        }
        if ( host ) {
            int i = lookup_cache( host );
            if ( i < 0 ) {
                unsigned int ix = check_domain( host );
                add_cache( host, ix );
-#if 1
-               fprintf( stderr, "%s %d %s ** %d\n",
-                        tell_ip( header ), hash_code( host ), host, ix );
-#endif
                if ( ix > 0 ) {
                if ( ix > 0 ) {
+                   // Notify "new" domain blocking
+                   fprintf( stderr, "%d: block %s at %s by %d\n",
+                            hash_code( host ), host, tell_ip( header ), ix );
                    verdict = NF_DROP;
                }
            } else if ( i > 0 ) {
                    verdict = NF_DROP;
                }
            } else if ( i > 0 ) {
@@ -264,14 +261,15 @@ static int cb(
 }
 
 /**
 }
 
 /**
- * Program main function.
+ * Program main function. Load block lists, register netfilter
+ * calllback and go for it.
  */
 int main(int argc, char **argv) {
     // Load the database
     start_domain_database_loading();
     int n = 1;
     for ( ; n < argc; n++ ) {
  */
 int main(int argc, char **argv) {
     // Load the database
     start_domain_database_loading();
     int n = 1;
     for ( ; n < argc; n++ ) {
-       fprintf( stderr, "Loading block list %s\n", argv[ n ] );
+       fprintf( stderr, "blockdomains loads block list %s\n", argv[ n ] );
        load_domains( argv[ n ] );
     }
     end_domain_database_loading();
        load_domains( argv[ n ] );
     }
     end_domain_database_loading();
@@ -283,36 +281,36 @@ int main(int argc, char **argv) {
     int rv;
     char buf[4096] __attribute__ ((aligned));
     
     int rv;
     char buf[4096] __attribute__ ((aligned));
     
-    fprintf( stderr, "opening library handle\n");
+    fprintf( stderr, "blockdomains opens library handle\n");
     h = nfq_open();
     if ( !h ) {
     h = nfq_open();
     if ( !h ) {
-       fprintf(stderr, "error during nfq_open()\n");
+       fprintf(stderr, "blockdomains error during nfq_open()\n");
        exit(1);
     }
     
        exit(1);
     }
     
-    fprintf( stderr, "unbinding any existing nf_queue handler\n" );
+    fprintf( stderr, "blockdomains unbinds any existing nf_queue handler\n" );
     if ( nfq_unbind_pf(h, AF_INET) < 0 ) {
        fprintf(stderr, "error during nfq_unbind_pf()\n");
        exit(1);
     }
     
     if ( nfq_unbind_pf(h, AF_INET) < 0 ) {
        fprintf(stderr, "error during nfq_unbind_pf()\n");
        exit(1);
     }
     
-    fprintf( stderr, "binding nfnetlink_queue as nf_queue handler\n" );
+    fprintf( stderr, "blockdomains binds as nf_queue handler\n" );
     if ( nfq_bind_pf(h, AF_INET) < 0 ) {
        fprintf(stderr, "error during nfq_bind_pf()\n");
        exit(1);
     }
 
 #define THEQUEUE 99
     if ( nfq_bind_pf(h, AF_INET) < 0 ) {
        fprintf(stderr, "error during nfq_bind_pf()\n");
        exit(1);
     }
 
 #define THEQUEUE 99
-    fprintf( stderr, "binding this socket to queue '%d'\n", THEQUEUE );
+    fprintf( stderr, "blockdomains registers to queue '%d'\n", THEQUEUE );
     qh = nfq_create_queue( h,  THEQUEUE, &cb, NULL );
     if ( !qh ) {
     qh = nfq_create_queue( h,  THEQUEUE, &cb, NULL );
     if ( !qh ) {
-       fprintf(stderr, "error during nfq_create_queue()\n");
+       fprintf(stderr, "blockdomains error during nfq_create_queue()\n");
        exit(1);
     }
     
        exit(1);
     }
     
-    fprintf( stderr, "setting copy_packet mode\n" );
+    fprintf( stderr, "blockdomains setting copy_packet mode\n" );
     if ( nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff ) < 0) {
     if ( nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff ) < 0) {
-       fprintf(stderr, "can't set packet_copy mode\n");
+       fprintf(stderr, "blockdomains can't set packet_copy mode\n");
        exit(1);
     }
     
        exit(1);
     }
     
@@ -323,17 +321,17 @@ int main(int argc, char **argv) {
        nfq_handle_packet(h, buf, rv);
     }
     
        nfq_handle_packet(h, buf, rv);
     }
     
-    fprintf( stderr, "unbinding from queue %d\n", THEQUEUE);
+    fprintf( stderr, "blockdomains unbinding from queue %d\n", THEQUEUE);
     nfq_destroy_queue(qh);
     
 #ifdef INSANE
     /* normally, applications SHOULD NOT issue this command, since it
        detaches other programs/sockets from AF_INET, too ! */
     nfq_destroy_queue(qh);
     
 #ifdef INSANE
     /* normally, applications SHOULD NOT issue this command, since it
        detaches other programs/sockets from AF_INET, too ! */
-    fprintf( stderr, "unbinding from AF_INET\n");
+    fprintf( stderr, "blockdomains unbinding from AF_INET\n");
     nfq_unbind_pf(h, AF_INET);
 #endif
     
     nfq_unbind_pf(h, AF_INET);
 #endif
     
-    fprintf( stderr, "closing library handle\n");
+    fprintf( stderr, "blockdomains closing library handle\n");
     nfq_close( h );
     
     exit( 0 );
     nfq_close( h );
     
     exit( 0 );
index 2afb37ad5031b5d5ff53e329816169652a461466..c4df75dfbf1a33497ea5e74b0019e613e9180c61 100644 (file)
@@ -2,16 +2,34 @@
 #include <string.h>
 #include <sys/types.h>
 
 #include <string.h>
 #include <sys/types.h>
 
+/**
+ * This file implements a "cache" of "known" domains together with
+ * their verdicts.
+ */
+
+/**
+ * This is the CacheEntry type of a malloc-ed cstring domain and a
+ * verdict.
+ */
 typedef struct _CacheEntry {
     unsigned char *domain;
     unsigned int ix;
 } CacheEntry;
 
 typedef struct _CacheEntry {
     unsigned char *domain;
     unsigned int ix;
 } CacheEntry;
 
+/**
+ * This is the cache root structure as apointer to the CacheEntry
+ * array and its size.
+ */
 struct {
     CacheEntry *table;
     int size;
 } cache;
 
 struct {
     CacheEntry *table;
     int size;
 } cache;
 
+/**
+ * This computes a hash code for a domain which is its cache index.
+ * This hashing simply adds the domain characters modulo cache table
+ * size.
+ */
 int hash_code(unsigned char *domain) {
     int i = 0;
     for ( ; *domain; domain++ ) {
 int hash_code(unsigned char *domain) {
     int i = 0;
     for ( ; *domain; domain++ ) {
@@ -20,6 +38,10 @@ int hash_code(unsigned char *domain) {
     return i % cache.size;
 }
 
     return i % cache.size;
 }
 
+/**
+ * Look up a domain in the cache and return its cached verdict, or -1
+ * of not present.
+ */
 int lookup_cache(unsigned char *domain) {
     if ( cache.table ) {
        int i = hash_code( domain );
 int lookup_cache(unsigned char *domain) {
     if ( cache.table ) {
        int i = hash_code( domain );
@@ -31,6 +53,12 @@ int lookup_cache(unsigned char *domain) {
     return -1;
 }
 
     return -1;
 }
 
+/**
+ * Add a domain and verdict into the cache. The domain hash code is
+ * used as index into the table, to replace any prior CacheEntry
+ * setting. The domain is a NUL terminated string that is copied into
+ * the cache.
+ */
 void add_cache(unsigned char *domain,unsigned int ix) {
     if ( cache.table == 0 ) {
        cache.size = 1024;
 void add_cache(unsigned char *domain,unsigned int ix) {
     if ( cache.table == 0 ) {
        cache.size = 1024;
index 02bb8dc364c0a2e8e5d3361e2e20afcbcbf34fe1..0edcf80db64b7bedecfc0bae19c0de22b28432cf 100644 (file)
@@ -140,36 +140,9 @@ static int wordlen(unsigned char *p) {
     return q - p;
 }
 
     return q - p;
 }
 
-#if 0
-static void add_domain(char *domain) {
-    if ( database.fill >= database.size ) {
-       grow();
-    }
-    int length = wordlen( domain );
-    int i = index_domain( domain, length, 0 );
-    if ( i < 0 ) {
-       i = -i-1;
-       int tail = database.fill - i;
-       if ( tail ) {
-           memmove( &database.table[ i+1 ],
-                    &database.table[i],
-                    tail * sizeof( Entry ) );
-       }
-       database.table[ i ].domain = domain;
-       database.table[ i ].length = length;
-       database.fill++;
-    } else {
-       char *p1 = strndup( domain, length );
-       char *p2 = strndup( database.table[i].domain,
-                           database.table[i].length );
-       fprintf( stderr, "fill = %d %d %s  == %s\n",
-                i, database.fill, p1, p2 );
-       free( p1 );
-       free( p2 );
-    }
-}
-#endif 
-
+/**
+ * Add an Entry for a given domain string and length.
+ */
 static void fast_add_domain(unsigned char *domain,int length) {
     int fill = database.fill;
     if ( fill >= database.size ) {
 static void fast_add_domain(unsigned char *domain,int length) {
     int fill = database.fill;
     if ( fill >= database.size ) {
@@ -180,6 +153,11 @@ static void fast_add_domain(unsigned char *domain,int length) {
     database.fill++;
 }
 
     database.fill++;
 }
 
+/**
+ * Return a marker of the sort order of two given Entry records, with
+ * a<b marked by a negative integer, a=b by zero, and a>b by
+ * (non-zero) positive integer.
+ */
 static int table_order(Entry *a,Entry *b) {
     int k = ( a->length < b->length )? a->length : b->length;
     int c = tail_compare( a->domain + a->length,
 static int table_order(Entry *a,Entry *b) {
     int k = ( a->length < b->length )? a->length : b->length;
     int c = tail_compare( a->domain + a->length,
@@ -191,34 +169,28 @@ static int table_order(Entry *a,Entry *b) {
 }
 
 /**
 }
 
 /**
- * External call to check a given domain.
+ * External call to check whether a given domain is in the database,
+ * returning 0 if not and non-zero if the domain is present.
  */
 unsigned int check_domain(unsigned char *domain) {
     int i = index_domain( domain, wordlen( domain ), 1 );
     return ( i < 0 )? 0 : ( i + 1 );
 }
 
  */
 unsigned int check_domain(unsigned char *domain) {
     int i = index_domain( domain, wordlen( domain ), 1 );
     return ( i < 0 )? 0 : ( i + 1 );
 }
 
+/**
+ * This function doesn't do anything at all but is present for the
+ * sake of the ABI.
+ */
 void start_domain_database_loading(void) {
 }
 
 void start_domain_database_loading(void) {
 }
 
-#if 0
-static void dump_table() {
-    fprintf( stderr, "Table fill=%d size=%d\n", database.fill, database.size );
-    int i = 0;
-    for ( ; i < database.fill; i++ ) {
-       char *p = strndup( database.table[i].domain,
-                          database.table[i].length );
-       fprintf( stderr, "[%d] %d %p %s\n",
-                i, database.table[i].length, database.table[i].domain, p );
-       free( p );
-    }
-}
-#endif
-
+/**
+ * This function sorts the database to support the lookup by binary
+ * search.
+ */
 void end_domain_database_loading(void) {
     qsort( database.table, database.fill, sizeof( Entry ),
           (__compar_fn_t) table_order );
 void end_domain_database_loading(void) {
     qsort( database.table, database.fill, sizeof( Entry ),
           (__compar_fn_t) table_order );
-    //dump_table();
 }
 
 /**
 }
 
 /**
@@ -255,18 +227,14 @@ void load_domains(char *file) {
     }
     //fprintf( stderr, "processing %s %p %p\n", file, data, end );
     unsigned char *p = data;
     }
     //fprintf( stderr, "processing %s %p %p\n", file, data, end );
     unsigned char *p = data;
-#if 0
-    int count = 0;
-#endif
-    while( p < end ) {
-#if 0
-       if ( ( ++count % 10000 ) == 0 ) {
-           fprintf( stderr, "%d rules\n", count );
+    while( p < end ) { // Consume a line
+       if ( *p <= ' ' ) {
+           p++;
+           continue;
        }
        }
-#endif
        if ( *p == '.' ) {
            unsigned char *domain = ++p;
        if ( *p == '.' ) {
            unsigned char *domain = ++p;
-           while ( *p > ' ' ) {
+           while ( p < end && *p > ' ' ) {
                p++;
            }
            fast_add_domain( domain, p - domain );
                p++;
            }
            fast_add_domain( domain, p - domain );