first (and incomplete) pass at peer blocking. this commit is to get the API into SVN so the mac client can access them

This commit is contained in:
Charles Kerr 2008-03-29 18:37:07 +00:00
parent faf5af0959
commit e7ba6b7b15
6 changed files with 333 additions and 0 deletions

View File

@ -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 \

169
libtransmission/blocklist.c Normal file
View File

@ -0,0 +1,169 @@
/*
* This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
*
* 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 <stdio.h>
#include <stdlib.h> /* free */
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#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 );
}

View File

@ -0,0 +1,20 @@
/*
* This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
*
* 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

75
libtransmission/ggets.c Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#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 */

45
libtransmission/ggets.h Normal file
View File

@ -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 */

View File

@ -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 );
/***********************************************************************