From e7ba6b7b15d2771bf086ab4598e89ffb8916779c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 29 Mar 2008 18:37:07 +0000 Subject: [PATCH] first (and incomplete) pass at peer blocking. this commit is to get the API into SVN so the mac client can access them --- libtransmission/Makefile.am | 4 + libtransmission/blocklist.c | 169 +++++++++++++++++++++++++++++++++ libtransmission/blocklist.h | 20 ++++ libtransmission/ggets.c | 75 +++++++++++++++ libtransmission/ggets.h | 45 +++++++++ libtransmission/transmission.h | 20 ++++ 6 files changed, 333 insertions(+) create mode 100644 libtransmission/blocklist.c create mode 100644 libtransmission/blocklist.h create mode 100644 libtransmission/ggets.c create mode 100644 libtransmission/ggets.h diff --git a/libtransmission/Makefile.am b/libtransmission/Makefile.am index 64143d1c4..ebdcc4683 100644 --- a/libtransmission/Makefile.am +++ b/libtransmission/Makefile.am @@ -5,11 +5,13 @@ noinst_LIBRARIES = libtransmission.a libtransmission_a_SOURCES = \ bencode.c \ + blocklist.c \ clients.c \ completion.c \ crypto.c \ fastresume.c \ fdlimit.c \ + ggets.c \ handshake.c \ inout.c \ ipcparse.c \ @@ -38,11 +40,13 @@ libtransmission_a_SOURCES = \ noinst_HEADERS = \ bencode.h \ + blocklist.h \ clients.h \ crypto.h \ completion.h \ fastresume.h \ fdlimit.h \ + ggets.h \ handshake.h \ inout.h \ internal.h \ diff --git a/libtransmission/blocklist.c b/libtransmission/blocklist.c new file mode 100644 index 000000000..85de7e96b --- /dev/null +++ b/libtransmission/blocklist.c @@ -0,0 +1,169 @@ +/* + * This file Copyright (C) 2008 Charles Kerr + * + * This file is licensed by the GPL version 2. Works owned by the + * Transmission project are granted a special exemption to clause 2(b) + * so that the bulk of its code can remain under the MIT license. + * This exemption does not extend to derived works not owned by + * the Transmission project. + * + * $Id:$ + */ + +#include +#include /* free */ +#include + +#include +#include +#include +#include +#include +#include + +#include "ggets.h" + +#include "transmission.h" +#include "net.h" /* inet_aton() */ +#include "platform.h" /* tr_getPrefsDirectory() */ +#include "utils.h" /* tr_buildPath() */ + +static void * blocklist = NULL; +static size_t blocklistSize = 0; +static int blocklistFd = -1; + +static void +getFilename( char * buf, size_t buflen ) +{ + tr_buildPath( buf, buflen, tr_getPrefsDirectory(), "blocklist", NULL ); +} + +static void +closeBlocklist( void ) +{ + if( blocklist ) + { + munmap( blocklist, blocklistSize ); + close( blocklistFd ); + blocklist = NULL; + blocklistSize = 0; + blocklistFd = -1; + } +} + +static void +loadBlocklist( void ) +{ + int fd; + struct stat st; + char filename[MAX_PATH_LENGTH]; + getFilename( filename, sizeof( filename ) ); + + closeBlocklist( ); + + fd = open( filename, O_RDONLY ); + if( fd == -1 ) { + tr_err( _( "Couldn't read file \"%s\": %s" ), filename, tr_strerror(errno) ); + return; + } + if( fstat( fd, &st ) == -1 ) { + tr_err( _( "Couldn't read file \"%s\": %s" ), filename, tr_strerror(errno) ); + close( fd ); + return; + } + blocklist = mmap( 0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 ); + if( !blocklist ) { + tr_err( _( "Couldn't read file \"%s\": %s" ), filename, tr_strerror(errno) ); + close( fd ); + return; + } + + blocklistSize = st.st_size; + blocklistFd = fd; +} + +int +tr_isInBlocklist( const struct in_addr * addr UNUSED ) +{ + if( !blocklist ) + loadBlocklist( ); + + return FALSE; /* FIXME */ +} + + +static void +deleteBlocklist( tr_handle * handle UNUSED ) +{ + char filename[MAX_PATH_LENGTH]; + getFilename( filename, sizeof( filename ) ); + closeBlocklist( ); + unlink( filename ); +} + +void +tr_setBlocklist( tr_handle * handle, + const char * filename ) +{ + FILE * in; + FILE * out; + char * line; + char outfile[MAX_PATH_LENGTH]; + + if( filename == NULL ) { + deleteBlocklist( handle ); + return; + } + + in = fopen( filename, "r" ); + if( !in ) { + tr_err( _( "Couldn't read file \"%s\": %s" ), filename, tr_strerror(errno) ); + return; + } + + closeBlocklist( ); + + getFilename( outfile, sizeof( outfile ) ); +fprintf( stderr, "outfile is [%s]\n", outfile ); + out = fopen( outfile, "wb+" ); + if( !out ) { + tr_err( _( "Couldn't save file \"%s\": %s" ), outfile, tr_strerror( errno ) ); + fclose( in ); + return; + } + + while( !fggets( &line, in ) ) + { + char * rangeBegin; + char * rangeEnd; + struct in_addr in_addr; + uint32_t range[2]; +//fprintf( stderr, "got line [%s]\n", line ); + + rangeBegin = strrchr( line, ':' ); + if( !rangeBegin ) continue; + ++rangeBegin; + + rangeEnd = strchr( rangeBegin, '-' ); + if( !rangeEnd ) continue; + *rangeEnd++ = '\0'; + + //fprintf( stderr, "rangeBegin [%s] rangeEnd [%s]\n", rangeBegin, rangeEnd ); + if( !inet_aton( rangeBegin, &in_addr ) ) + fprintf( stderr, "skipping invalid address [%s]\n", rangeBegin ); + range[0] = ntohl( in_addr.s_addr ); + if( !inet_aton( rangeEnd, &in_addr ) ) + fprintf( stderr, "skipping invalid address [%s]\n", rangeEnd ); + range[1] = ntohl( in_addr.s_addr ); + + free( line ); + + if( fwrite( range, sizeof(uint32_t), 2, out ) != 2 ) { + tr_err( _( "Couldn't save file \"%s\": %s" ), outfile, tr_strerror( errno ) ); + break; + } + } + + fclose( out ); + fclose( in ); +} diff --git a/libtransmission/blocklist.h b/libtransmission/blocklist.h new file mode 100644 index 000000000..fcbb08299 --- /dev/null +++ b/libtransmission/blocklist.h @@ -0,0 +1,20 @@ +/* + * This file Copyright (C) 2008 Charles Kerr + * + * This file is licensed by the GPL version 2. Works owned by the + * Transmission project are granted a special exemption to clause 2(b) + * so that the bulk of its code can remain under the MIT license. + * This exemption does not extend to derived works not owned by + * the Transmission project. + * + * $Id:$ + */ + +#ifndef TR_BLOCKLIST_H +#define TR_BLOCKLIST_H + +struct in_addr; + +int tr_isInBlocklist( const struct in_addr * ); + +#endif diff --git a/libtransmission/ggets.c b/libtransmission/ggets.c new file mode 100644 index 000000000..164b9f981 --- /dev/null +++ b/libtransmission/ggets.c @@ -0,0 +1,75 @@ +/* File ggets.c - goodgets is a safe alternative to gets */ +/* By C.B. Falconer. Public domain 2002-06-22 */ +/* attribution appreciated. */ + +/* Revised 2002-06-26 New prototype. + 2002-06-27 Incomplete final lines + 2006-06-14 Simplified, using getc, not fgets + 2006-06-15 Fixed memory leak at EOF + */ + +/* fggets and ggets [which is fggets(ln, stdin)] set *ln to + a buffer filled with the next complete line from the text + stream f. The storage has been allocated within fggets, + and is normally reduced to be an exact fit. The trailing + \n has been removed, so the resultant line is ready for + dumping with puts. The buffer will be as large as is + required to hold the complete line. + + Note: this means a final file line without a \n terminator + has an effective \n appended, as EOF occurs within the read. + + If no error occurs fggets returns 0. If an EOF occurs on + the input file, EOF is returned. For memory allocation + errors some positive value is returned. In this case *ln + may point to a partial line. For other errors memory is + freed and *ln is set to NULL. + + Freeing of assigned storage is the callers responsibility + */ + +#include +#include +#include "ggets.h" + +#define INITSIZE 112 /* power of 2 minus 16, helps malloc */ +#define DELTASIZE (INITSIZE + 16) + +enum {OK = 0, NOMEM}; + +int fggets(char* *ln, FILE *f) +{ + int cursize, ch, ix; + char *buffer, *temp; + + *ln = NULL; /* default */ + if (NULL == (buffer = malloc(INITSIZE))) return NOMEM; + cursize = INITSIZE; + + ix = 0; + while ((EOF != (ch = getc(f))) && ('\n' != ch)) { + if (ix >= (cursize - 1)) { /* extend buffer */ + cursize += DELTASIZE; + if (NULL == (temp = realloc(buffer, (size_t)cursize))) { + /* ran out of memory, return partial line */ + buffer[ix] = '\0'; + *ln = buffer; + return NOMEM; + } + buffer = temp; + } + buffer[ix++] = ch; + } + if ((EOF == ch) && (0 == ix)) { + free(buffer); + return EOF; + } + + buffer[ix] = '\0'; + if (NULL == (temp = realloc(buffer, (size_t)ix + 1))) { + *ln = buffer; /* without reducing it */ + } + else *ln = temp; + return OK; +} /* fggets */ +/* End of ggets.c */ diff --git a/libtransmission/ggets.h b/libtransmission/ggets.h new file mode 100644 index 000000000..db35bb4a2 --- /dev/null +++ b/libtransmission/ggets.h @@ -0,0 +1,45 @@ +/* File ggets.h - goodgets is a safe alternative to gets */ +/* By C.B. Falconer. Public domain 2002-06-22 */ +/* attribution appreciated. */ + + +/* Revised 2002-06-26 New prototype. + 2002-06-27 Incomplete final lines + */ + +/* fggets and ggets [which is fggets(ln, stdin)] set *ln to + a buffer filled with the next complete line from the text + stream f. The storage has been allocated within fggets, + and is normally reduced to be an exact fit. The trailing + \n has been removed, so the resultant line is ready for + dumping with puts. The buffer will be as large as is + required to hold the complete line. + + Note: this means a final file line without a \n terminator + has an effective \n appended, as EOF occurs within the read. + + If no error occurs fggets returns 0. If an EOF occurs on + the input file, EOF is returned. For memory allocation + errors some positive value is returned. In this case *ln + may point to a partial line. For other errors memory is + freed and *ln is set to NULL. + + Freeing of assigned storage is the callers responsibility + */ + +#ifndef ggets_h_ +# define ggets_h_ + +# ifdef __cplusplus + extern "C" { +# endif + +int fggets(char* *ln, FILE *f); + +#define ggets(ln) fggets(ln, stdin) + +# ifdef __cplusplus + } +# endif +#endif +/* END ggets.h */ diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 24b47f5b4..90aec2ff3 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -289,6 +289,26 @@ void tr_setGlobalPeerLimit( tr_handle * handle, uint16_t tr_getGlobalPeerLimit( const tr_handle * handle ); +/** + * Specify a range of IPs for Transmission to block. + * + * filename must be an uncompressed ascii file, + * using the same format as the bluetack level1 file. + * + * libtransmission does not keep a handle to `filename' + * after this call returns, so the caller is free to + * keep or delete `filename' as it wishes. + * libtransmission makes its own copy of the file + * massaged into a format easier to search. + * + * The caller only needs to invoke this when the blocklist + * has changed. + * + * Passing NULL for a filename will clear the blocklist. + */ +void tr_setBlocklist( tr_handle * handle, + const char * filename ); + /***********************************************************************