# HG changeset patch # User Mahlon E. Smith # Date 1314394851 25200 # Node ID eac7211fe5222184cc0cb8e00ecb835d7ebc3213 Initial commit of an experimental little Squid redirector. diff -r 000000000000 -r eac7211fe522 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Fri Aug 26 14:40:51 2011 -0700 @@ -0,0 +1,4 @@ +^volta$ +^parser.c$ +^parser_state.* +.*debug diff -r 000000000000 -r eac7211fe522 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Fri Aug 26 14:40:51 2011 -0700 @@ -0,0 +1,25 @@ + +CFLAGS=-O2 -Wall +CFLAGS_DEBUG=-Wall -DDEBUG -DPROG='"volta (debugmode)"' +LIBS=-lsqlite3 + +volta: parser.c volta.c volta.h + $(CC) $(CFLAGS) $(LIBS) -o $@ *.c + strip $@ + +parser.c: parser.rl + ragel -L -C -e -G2 parser.rl -o $@ + +debug: volta_debug + +volta_debug: parser_debug.c volta.h + $(CC) $(CFLAGS_DEBUG) $(LIBS) -o volta *.c + +parser_debug.c: parser.c + ragel -V parser.rl > parser_state.dot + ragel -C -e -G2 -V -x parser.rl -o parser_state.xml + dot -Tpng parser_state.dot > parser_state.png + +clean: + @rm -rf volta volta_debug* parser.c parser_state.* + diff -r 000000000000 -r eac7211fe522 parser.rl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parser.rl Fri Aug 26 14:40:51 2011 -0700 @@ -0,0 +1,51 @@ +/* vim: set noet nosta sw=4 ts=4 ft=ragel : */ + +#include "volta.h" + +/* state machine data */ +%%{ + machine redirector; + + action yay { + printf( "YAH\n" ); + } + + # http://, ftp://, https://, etc + proto = alpha{3,5} . '://'; + + # http://mahlon:password@example.com or http://mahlon@example.com + # username optional password + creds = ( alnum | [+._\-] )+ . ( ':' . any+ )? . '@'; + + main := ( proto . creds ) | proto @yay '\n'; +}%% +%% write data; + +int +parse( char *p ) +{ + /* initial machine state */ + short int cs = 0; + + /* the client request object */ + request c_request; + request *cp_request = &c_request; + + /* + char ip[ INET_ADDRSTRLEN ]; + inet_pton( AF_INET, "127.0.0.1", &cp_request->ip ); + inet_ntop( AF_INET, &cp_request->ip, ip, INET_ADDRSTRLEN ); + */ + + /* initalize state machine with current line */ + char *pe = p + strlen(p) + 1; + + /* enter state machine */ + %% write init; + %% write exec; + + /* reset the request */ + /* c_request = reset_request; */ + return( 0 ); +} + diff -r 000000000000 -r eac7211fe522 volta.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/volta.c Fri Aug 26 14:40:51 2011 -0700 @@ -0,0 +1,103 @@ +/* vim: set noet nosta sw=4 ts=4 ft=c : */ +/* Squid docs: +--------------------------------------------------------------------------- +TAG: url_rewrite_program +Specify the location of the executable for the URL rewriter. +Since they can perform almost any function there isn't one included. + +For each requested URL rewriter will receive on line with the format + +URL client_ip "/" fqdn user method [ kvpairs] + +In the future, the rewriter interface will be extended with +key=value pairs ("kvpairs" shown above). Rewriter programs +should be prepared to receive and possibly ignore additional +whitespace-separated tokens on each input line. + +And the rewriter may return a rewritten URL. The other components of +the request line does not need to be returned (ignored if they are). + +The rewriter can also indicate that a client-side redirect should +be performed to the new URL. This is done by prefixing the returned +URL with "301:" (moved permanently) or 302: (moved temporarily). + +By default, a URL rewriter is not used. +--------------------------------------------------------------------------- */ + +/* + * TODO + * + * flush stdout on writes + * empty struct not necessary? + * inet_pton( AF_INET, *char src, dest ) + * + */ + +#include "volta.h" + +int +main( int argc, char *argv[] ) { + + int opt; + + /* storage for line received from squid */ + char line[ LINE_BUFSIZE ]; + + while ( (opt = getopt( argc, argv, "a:hv" )) != -1 ) { + switch ( opt ) { + case 'a': + printf( "a -> '%s' (no-op at the moment)\n", optarg ); + break; + case 'h': + usage( argv[0] ); + return( 0 ); + case 'v': + printf( "%s version %s\n", PROG, VERSION ); + return( 0 ); + case '?': + default: + break; + } + } + argc -= optind; + argv += optind; + + /* start stdin line loop */ + while( fgets( line, LINE_BUFSIZE, stdin ) != NULL ) parse( line ); + + /* stdin closed */ + debug( "End of stream, shutting down.\n" ); + return( 0 ); +} + +/* + * Basic usage + */ +void +usage( char *prg ) +{ + printf( "%s [-vh] [-a ]\n", prg ); + printf( " -v Display version\n" ); + printf( " -h Usage (you're lookin' at it)\n" ); + printf( " -a Perform an action:\n" ); + printf( " init: Initialize a new database\n" ); + printf( "\n" ); + return; +} + + +/* + * Debug function, only output to stderr if -DDEBUG set + */ +void +debug( const char *fmt, ... ) +{ + va_list args; + va_start( args, fmt ); +#ifdef DEBUG + fprintf( stderr, "%s %d: ", PROG, getpid() ); + vfprintf( stderr, fmt, args ); +#endif + va_end( args ); +} + diff -r 000000000000 -r eac7211fe522 volta.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/volta.h Fri Aug 26 14:40:51 2011 -0700 @@ -0,0 +1,45 @@ + +#ifndef _VOLTA_H +#define _VOLTA_H + +#ifndef PROG +#define PROG "volta" +#endif +#define VERSION "$Version$" /* expanded by mercurial */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* Maximum length per line from Squid */ +#define LINE_BUFSIZE 2048 + +/* URL client_ip "/" fqdn user method [ kvpairs] */ +typedef struct request { + char *url; + char *host; + struct sockaddr_in ip; + char *ip_fqdn; + char *user; + char *method; + char *kvpairs; +} request; + +/* An "empty" request struct used for re-assignment */ +static const struct request reset_request; + +/* Prototypes */ +void usage( char *prg ); +void debug( const char *fmt, ... ); +int parse( char *p ); + +#endif +