aboutsummaryrefslogtreecommitdiff
path: root/src/op/op.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/op/op.c')
-rw-r--r--src/op/op.c920
1 files changed, 0 insertions, 920 deletions
diff --git a/src/op/op.c b/src/op/op.c
deleted file mode 100644
index 797f2f50b..000000000
--- a/src/op/op.c
+++ /dev/null
@@ -1,920 +0,0 @@
-/**
- * op.c
- * Onion Proxy
- *
- * Matej Pfajfar <mp292@cam.ac.uk>
- */
-
-/*
- * Changes :
- * $Log$
- * Revision 1.2 2002/07/12 18:14:16 montrose
- * removed loglevel from global namespace. severity level is set using log() with a NULL format argument now. example: log(LOG_ERR,NULL);
- *
- * Revision 1.1.1.1 2002/06/26 22:45:50 arma
- * initial commit: current code
- *
- * Revision 1.37 2002/06/14 20:45:56 mp292
- * *** empty log message ***
- *
- * Revision 1.36 2002/04/02 14:28:01 badbytes
- * Final finishes.
- *
- * Revision 1.35 2002/04/02 10:21:07 badbytes
- * *** empty log message ***
- *
- * Revision 1.34 2002/03/29 08:35:12 badbytes
- * Link encryption is now done on the entire cell header for simplicity.
- *
- * Revision 1.33 2002/03/28 17:57:59 badbytes
- * Bug fix.
- *
- * Revision 1.32 2002/03/28 11:01:43 badbytes
- * Now does link-encryption and link-padding.
- *
- * Revision 1.31 2002/03/12 23:40:32 mp292
- * Started on op<->router connection padding.
- *
- * Revision 1.30 2002/01/29 02:22:58 mp292
- * Put a timeout on all network I/O.
- *
- * Revision 1.29 2002/01/26 23:01:55 mp292
- * Reviewed according to Secure-Programs-HOWTO.
- *
- * Revision 1.28 2002/01/18 20:42:06 mp292
- * Reflects changes to common/onion.c:new_route()
- *
- * Revision 1.27 2002/01/17 23:49:15 mp292
- * Added size of public key to one of the debugging messages.
- *
- * Revision 1.26 2002/01/16 23:01:58 mp292
- * First phase of system testing completed (main functionality).
- *
- * Revision 1.25 2002/01/16 17:01:56 mp292
- * There was a bug in checking whether the incoming connection is local or not.
- *
- * Revision 1.24 2002/01/16 16:09:32 mp292
- * A pointer cast was missing. Fixed.
- *
- * Revision 1.23 2002/01/14 13:05:39 badbytes
- * System testing in progress.
- *
- * Revision 1.22 2002/01/11 15:47:25 badbytes
- * *** empty log message ***
- *
- * Revision 1.21 2002/01/09 09:18:35 badbytes
- * Now handles EINTR error from accept().
- *
- * Revision 1.20 2002/01/09 07:57:18 badbytes
- * Ciphers got out of sync, hopefully fixed.
- *
- * Revision 1.19 2001/12/19 11:15:41 badbytes
- * Corrected AF_INET to PF_INET in socket() calls.
- *
- * Revision 1.18 2001/12/19 08:38:38 badbytes
- * Zombie problems hopefully fixed.
- *
- * Revision 1.17 2001/12/19 08:29:29 badbytes
- * Tested. Still some problems with zombies in both op and smtpap.
- *
- * Revision 1.16 2001/12/18 15:51:58 badbytes
- * Connection with onion router established. Will continue testing tomorrow.
- *
- * Revision 1.15 2001/12/18 14:12:05 badbytes
- * Tested up to connect() to onion router.
- *
- * Revision 1.14 2001/12/18 12:21:11 badbytes
- * Forgot to convert port to network order :-)
- *
- * Revision 1.13 2001/12/18 11:52:27 badbytes
- * Coding completed. Proceeding to test.
- *
- * Revision 1.12 2001/12/17 13:36:15 badbytes
- * Writing handle_connection()
- *
- * Revision 1.11 2001/12/17 08:42:44 badbytes
- * getrouters() now returns an array of routers and also writes the length of the array to an int*.
- *
- * Revision 1.10 2001/12/14 14:45:13 badbytes
- * Added range checking for CoinWeight.
- *
- * Revision 1.9 2001/12/14 14:08:50 badbytes
- * getrouters() now returns an array of pointers rather than a linked list
- *
- * Revision 1.8 2001/12/14 13:31:20 badbytes
- * *** empty log message ***
- *
- * Revision 1.7 2001/12/14 13:17:12 badbytes
- * Corrected references to types.h
- *
- * Revision 1.6 2001/12/14 13:00:30 badbytes
- * Changed my mind, routers.c and routers.h stay where they are :-)
- *
- * Revision 1.5 2001/12/14 12:56:55 badbytes
- * Moved routers* to common/
- *
- * Revision 1.4 2001/12/14 12:42:50 badbytes
- * References to onion.h and onion.o now point to the common/ directory.
- *
- * Revision 1.3 2001/12/14 12:40:26 badbytes
- * Was being stupid - op doesn't need a private key!! Have removed ...
- *
- * Revision 1.2 2001/12/14 11:27:16 badbytes
- * Configuration and server setup completed.
- *
- * Revision 1.1 2001/12/13 15:15:11 badbytes
- * Started coding the onion proxy.
- *
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <signal.h>
-#include <wait.h>
-
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-
-#include "../common/log.h"
-#include "../common/version.h"
-#include "../common/onion.h"
-#include "../common/utils.h"
-#include "../common/cell.h"
-#include "../common/scheduler.h"
-
-#include "config.h"
-#include "routers.h"
-#include "args.h"
-#include "auth.h"
-#include "op.h"
-#include "ss.h"
-#include "crypto.h"
-#include "buffers.h"
-
-/* global variables */
-
-/* default logging threshold */
-struct timeval conn_tout;
-struct timeval *conn_toutp = &conn_tout;
-
-/* valid command-line options */
-static char *args = "hf:p:l:";
-
-/* valid config file options */
-static config_opt_t options[] =
-{
- {"RouterFile", CONFIG_TYPE_STRING, {0}, 0},
- {"CoinWeight", CONFIG_TYPE_DOUBLE, {0}, 0},
- {"MaxConn", CONFIG_TYPE_INT, {0}, 0},
- {"ConnTimeout", CONFIG_TYPE_INT, {0}, 0},
- {"Bandwidth", CONFIG_TYPE_INT, {0}, 0},
- {0}
-};
-enum opts {
- RouterFile=0, CoinWeight, MaxConn, ConnTimeout, Bandwidth
-};
-
-int connections = 0; /* number of active connections */
-
-/* local host info */
-struct hostent *local_host;
-char local_hostname[512];
-
-struct sockaddr_in local, remote; /* local and remote address info */
-struct sockaddr_in or_addr; /* onion router address */
-
-int request_sock; /* where we listen for connections */
-int new_sock; /* for accepted connections */
-int or_sock; /* for connecting to the first onion router */
-
-/* router array */
-routent_t **routerarray = NULL;
-int rarray_len = 0;
-
-/* end of global variables */
-
-void send_to_router(int s,unsigned char **outbuf, size_t *outbuflen, size_t *outbuf_dataoffset, size_t *outbuf_datalen, struct timeval *lastsend, struct timeval *interval, sched_t *scheduler, EVP_CIPHER_CTX *ctx)
-{
- int retval;
- int cells;
- int datacells;
- int paddingcells;
- int i;
- int x;
- char *px;
- struct timeval now;
- cell_t cipher;
- cell_t *padding;
- int cipherlen;
- unsigned long elapsed;
-
- /* calculate the number of cells that need to be sent */
- retval = gettimeofday(&now,NULL);
- if (retval == -1)
- {
- log(LOG_ERR,"Could not get current time!");
- return;
- }
-
- elapsed = 1000000*(now.tv_sec-lastsend->tv_sec) + now.tv_usec-lastsend->tv_usec;
-
- if (elapsed < 1000000)
- {
- cells = ((options[Bandwidth].r.i) * 512) / /* number of bytes per second, divided by two */
- (1000000/elapsed); /* fractions of second since last send */
- }
- else
- {
- cells = ((options[Bandwidth].r.i) * 512) * /* number of bytes per second, divided by two */
- (elapsed/1000000); /* 1/fractions of second since last send */
- }
- cells /= sizeof(cell_t);
-
- datacells = (*outbuf_datalen)/sizeof(cell_t); /* number of data cells available */
- if (datacells > cells)
- datacells = cells;
- paddingcells = cells - datacells;
-
- /* send the data cells first */
- for (i=0; i<datacells; i++)
- {
- /* link-encrypt the cell header */
- printf("Cell header plaintext: ");
- for(x=0;x<8;x++) {
- printf("%u ",*(char *)(*outbuf+*outbuf_dataoffset+x));
- }
- printf("\n");
- retval = EVP_EncryptUpdate(ctx, (unsigned char *)&cipher, &cipherlen, *outbuf+*outbuf_dataoffset, 8);
- if (!retval)
- {
- log(LOG_ERR,"Link encryption failed. Exiting.");
- exit(-1);
- }
- printf("Cell header crypttext: ");
- px = (char *)&cipher;
- for(x=0;x<8;x++) {
- printf("%u ",px[x]);
- }
- printf("\n");
-
- /* copy the payload */
- memcpy((void *)cipher.payload, (void *)(*outbuf+*outbuf_dataoffset+8), CELL_PAYLOAD_SIZE);
-
- /* send the cell */
- log(LOG_DEBUG,"send_to_router(): Trying to send a data/create cell to router.");
- retval = write_tout(s,(unsigned char *)&cipher, sizeof(cell_t), conn_toutp);
- if (retval < sizeof(cell_t))
- {
- log(LOG_ERR,"Connection to the router seems to be lost. Exiting.");
- exit(-1);
- }
- *outbuf_dataoffset += sizeof(cell_t);
- *outbuf_datalen -= sizeof(cell_t);
-
- }
-
- /* send padding */
- for (i=0; i<cells-datacells; i++)
- {
- padding = new_padding_cell();
- if (!padding)
- {
- log(LOG_ERR,"Memory allocation error. Exiting.");
- exit(-1);
- }
-
- /* link encrypt the cell header */
- retval = EVP_EncryptUpdate(ctx, (unsigned char *)&cipher, &cipherlen, (unsigned char *)padding, 8);
- if (!retval)
- {
- log(LOG_ERR,"Link encryption failed. Exiting.");
- exit(-1);
- }
-
- /* copy the payload */
- memcpy((void *)cipher.payload, (void *)((unsigned char *)padding+8), CELL_PAYLOAD_SIZE);
-
- /* send the cell */
- log(LOG_DEBUG,"send_to_router(): Trying to send a padding cell to router.");
- retval = write_tout(s, (unsigned char *)&cipher, sizeof(cell_t), conn_toutp);
- if (retval < sizeof(cell_t))
- {
- log(LOG_ERR,"Connection to the router seems to be lost. Exiting.");
- exit(-1);
- }
-
- free((void *)padding);
- }
-
- /* update scheduler state, if we've sent anything to the router */
- if (cells)
- {
- retval = update_sched_entry(scheduler, *lastsend, *interval, now, *interval);
- if (retval == -1)
- {
- log(LOG_ERR,"Scheduler error. Exiting.");
- exit(-1);
- }
- memcpy((void *)lastsend,(void *)&now, sizeof(struct timeval));
- }
-
-}
-
-/* deal with a client */
-int handle_connection()
-{
- int retval = 0;
- int routelen = 0; /* length of the route */
- unsigned int *route = NULL; /* hops in the route as an array of indexes into rarray */
- routent_t *firsthop = NULL;
-
- uint32_t aci; /* ACI for this connection */
-
- unsigned char *onion = NULL; /* holds the onion */
- int onionlen = 0; /* onion length in host order */
-
- crypt_path_t **cpath = NULL; /* defines the crypt operations that need to be performed on incoming/outgoing data */
- char *dest_addr = NULL; /* destination address in ASCII format */
-
- int dest_addrlen = 0;
- char *dest_port = NULL; /* destination port in ASCII format */
- int dest_portlen = 0;
- ss_t *ss; /* standard structure */
-
- uint32_t router_addr_net; /* address of the first onion router in network order */
-
- unsigned char inbuf[1024]; /* buffer for forwarding data between ap and or */
-
- unsigned char *outbuf = NULL; /* buffer for cells which are to be transmitted to the first core onion router in the route */
- size_t outbuflen = 0;
- size_t outbuf_dataoffset = 0; /* offset to the beginning of the data */
- size_t outbuf_datalen = 0; /* length of the data stored in the buffer */
-
- cell_t cellbuf;
- int cellbuflen = 0;
-
- struct timeval lastsend; /* time of last transmission to the onion router */
- struct timeval interval; /* transmission interval */
-
- /* link encryption */
- unsigned char f_session_key[8];
- unsigned char f_session_iv[8] = {0,0,0,0,0,0,0,0};
- unsigned char b_session_key[8];
- unsigned char b_session_iv[8] = {0,0,0,0,0,0,0,0};
- EVP_CIPHER_CTX f_ctx;
- EVP_CIPHER_CTX b_ctx;
-
- /* scheduler */
- sched_t *scheduler;
-
- /* for use with select() */
- fd_set rmask, mask;
- int maxfd;
- struct timeval *timeout;
-
- /* get the standard structure */
- retval = process_ss(new_sock, conn_toutp, &ss,&dest_addr, &dest_addrlen, &dest_port, &dest_portlen);
- if (retval == -1)
- {
- log(LOG_ERR,"Error processing the standard structure.");
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Destination = %s:%s",dest_addr,dest_port);
-
- /* choose a route */
- route = (unsigned int *)new_route(options[CoinWeight].r.d, routerarray,rarray_len, &routelen);
- if (!route)
- {
- log(LOG_ERR,"Error choosing a route through the OR network.");
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Chosen a route of length %u : ",routelen);
- for (retval=routelen-1;retval>=0;retval--)
- {
- log(LOG_DEBUG,"handle_connection() : %u : %s:%u, %u",routelen-retval,(routerarray[route[retval]])->address,ntohs((routerarray[route[retval]])->port),RSA_size((routerarray[route[retval]])->pkey));
- }
-
- /* allocate memory for the crypt path */
- cpath = malloc(routelen * sizeof(crypt_path_t *));
- if (!cpath)
- {
- log(LOG_ERR,"Error allocating memory.");
- free(route);
- return -1;
- }
- /* create an onion and calculate crypto keys */
- onion = create_onion(routerarray,rarray_len,route,routelen,&onionlen,cpath);
- if (!onion)
- {
- log(LOG_ERR,"Error creating an onion.");
- free(route);
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Created an onion of size %u bytes.",onionlen);
- log(LOG_DEBUG,"handle_connection() : Crypt path :");
- for (retval=0;retval<routelen;retval++)
- {
- log(LOG_DEBUG,"handle_connection() : %u/%u",(cpath[retval])->forwf, (cpath[retval])->backf);
- }
-
- /* connect to first onion router */
- or_sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
- if (or_sock < 0)
- {
- free(route);
- free(onion);
- free(cpath);
- close(new_sock);
- log(LOG_ERR,"Error creating socket.");
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Socket created.");
-
- firsthop = routerarray[route[routelen-1]];
- memset((void *)&or_addr,0,sizeof(or_addr));
- or_addr.sin_family=AF_INET;
- or_addr.sin_port=firsthop->entry_port;
- router_addr_net = firsthop->addr;
- memcpy(&or_addr.sin_addr,&router_addr_net,sizeof(struct sockaddr_in));
- log(LOG_DEBUG,"handle_connection() : Trying to connect to %s:%u",inet_ntoa(or_addr.sin_addr), ntohs(or_addr.sin_port));
- retval = connect(or_sock,(struct sockaddr *)&or_addr, sizeof(or_addr));
- if (retval == -1)
- {
- log(LOG_ERR,"Could not connect to onion router.");
- free(route);
- free(onion);
- free(cpath);
- close(or_sock);
- close(new_sock);
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Connected to first onion router.");
-
- /* send session key and bandwidth info */
- retval = send_auth(or_sock, options[Bandwidth].r.i, firsthop->pkey, f_session_key, b_session_key);
- if (retval == -1)
- {
- close(or_sock);
- close(new_sock);
- log(LOG_ERR,"Lost connection to an onion router. Exiting.");
- return -1;
- }
- /* initialize crypto engines */
- EVP_CIPHER_CTX_init(&f_ctx);
- EVP_CIPHER_CTX_init(&b_ctx);
- EVP_EncryptInit(&f_ctx, EVP_des_ofb(), f_session_key, f_session_iv);
- EVP_DecryptInit(&b_ctx, EVP_des_ofb(), b_session_key, b_session_iv);
-
- /* chose an ACI */
- do
- {
- retval = RAND_pseudo_bytes((unsigned char *)&aci, 2);
- if (retval==-1)
- {
- log(LOG_ERR,"Random data generator doesn't seem to work. Exiting.");
- return -1;
- }
- } while(!aci); /* don't allow zero ACIs */
- log(LOG_DEBUG,"handle_connection() : ACI %u chosen.",aci);
-
- /* initialize last time of transmission to now */
- retval = gettimeofday(&lastsend, NULL);
- if (retval == -1)
- {
- log(LOG_ERR,"Could not get current time.");
- return -1;
- }
- /* calculate the transmission interval */
- interval.tv_sec = 0;
- interval.tv_usec = 250000/options[Bandwidth].r.i;
- /* initialize the scheduler */
- scheduler = new_sched();
- if (!scheduler)
- {
- log(LOG_ERR,"Could not initialize scheduler.");
- return -1;
- }
- retval = add_sched_entry(scheduler, lastsend, interval);
- if (retval == -1)
- {
- log(LOG_ERR,"Could not initialize scheduler.");
- return -1;
- }
- timeout = NULL;
-
- /* write the onion into the output buffer */
- retval = buffer_create(aci, (unsigned char *)onion, onionlen, &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
- if (retval == -1)
- {
- log(LOG_DEBUG,"handle_connection() : Could not buffer the onion.");
- close(or_sock);
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Onion buffered for output.");
-
- /* send standard structure */
- log(LOG_DEBUG,"handle_connection() : Calling send_crypt ... routelen=%u, sizeof(SS) = %u",routelen,sizeof(ss_t));
- retval = buffer_data(aci, (unsigned char *)ss, sizeof(ss_t), &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
- if (retval == -1)
- {
- log(LOG_DEBUG,"handle_connection() : Could not buffer the standard structure for output.");
- close(or_sock);
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Buffered the standard structure header.");
- retval = buffer_data(aci, dest_addr,dest_addrlen, &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
- if (retval == -1)
- {
- log(LOG_DEBUG,"handle_connection() : Could not buffer the standard structure (dest. address) for output.");
- close(or_sock);
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Buffered the destination address.");
- retval = buffer_data(aci, dest_port, dest_portlen, &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
- if (retval == -1)
- {
- log(LOG_DEBUG,"handle_connection() : Could not buffer the standard structure (dest. port) for output.");
- close(or_sock);
- return -1;
- }
- log(LOG_DEBUG,"handle_connection() : Buffered the destination port.");
-
-
- /* forward data in both directions, crypt as necessary */
- /* use select() */
-
- FD_ZERO(&mask);
- FD_SET(new_sock, &mask);
- FD_SET(or_sock, &mask);
- if (new_sock > or_sock)
- maxfd = new_sock;
- else
- maxfd = or_sock;
-
- while(1)
- {
- rmask = mask;
-
- /* delete old timeout */
- if (timeout)
- free((void *)timeout);
- /* get the new one */
- retval = sched_trigger(scheduler, &timeout);
- if (retval == -1)
- {
- log(LOG_DEBUG,"Scheduler error.");
- break;
- }
- retval = select(maxfd+1,&rmask,NULL,NULL,timeout);
- if (retval < 0)
- {
- log(LOG_DEBUG,"handle_connection() : select() returned negative integer");
- break;
- }
-
- if (FD_ISSET(new_sock,&rmask))
- {
- log(LOG_DEBUG,"handle_connection() : FD_ISSET(new_sock)");
- retval = read_tout(new_sock, inbuf, 1024, 0, conn_toutp);
- if (retval <= 0)
- {
- log(LOG_DEBUG,"handle_connection() : Received EOF on new_sock.");
- break;
- }
- log(LOG_DEBUG,"handle_connection() : Received %u bytes from client.",retval);
- retval = buffer_data(aci, inbuf, retval, &outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, cpath, routelen);
-
- if (retval < 0)
- {
- log(LOG_DEBUG,"handle_connection() : Could not buffer data for output to OR.");
- break;
- }
- log(LOG_DEBUG,"handle_connection() : Buffered %u bytes for output to the OR.",retval);
- }
-
- if (FD_ISSET(or_sock, &rmask))
- {
- log(LOG_DEBUG,"handle_connection() : FD_ISSET(or_sock)");
- /* read the remainder of the cell (or whatever we can get) */
- retval = read_tout(or_sock, ((unsigned char *)&cellbuf)+cellbuflen, sizeof(cell_t) - cellbuflen, 0, conn_toutp);
- if (retval <= 0)
- {
- log(LOG_DEBUG,"handle_connection() : Received EOF on or_sock.");
- break;
- }
- log(LOG_DEBUG,"handle_connection() : Received %u bytes from router.",retval);
- cellbuflen += retval;
-
- if (cellbuflen == sizeof(cell_t)) /* received an entire cell */
- {
- /* link decrypt the cell header */
- retval = EVP_DecryptUpdate(&b_ctx, (unsigned char *)inbuf, &cellbuflen, (unsigned char *)&cellbuf, 8);
- if (!retval)
- {
- log(LOG_ERR,"Decryption error. Closing the connection and exiting.");
- break;
- }
-
- if (((cell_t *)inbuf)->command == CELL_PADDING) /* padding, discard */
- {
- log(LOG_DEBUG,"Received a PADDING cell. Discarding.");
- ; /* discard */
- }
- else if (((cell_t *)inbuf)->command == CELL_DATA) /* only process DATA cells , discard otherwise */
- {
- /* decrypt the payload length */
- retval = crypt_b((unsigned char *)&((cell_t *)inbuf)->length, 1, cpath, routelen);
- if (retval == -1)
- {
- log(LOG_ERR,"Decryption error. Closing the connection and exiting.");
- break;
- }
-
- /* decrypt the payload */
- retval = crypt_b((unsigned char *)cellbuf.payload, CELL_PAYLOAD_SIZE, cpath, routelen);
- if (retval == -1)
- {
- log(LOG_ERR,"Decryption error. Closing the connection and exiting.");
- break;
- }
-
- /* send the payload to the application proxy */
- retval = write_tout(new_sock, (unsigned char *)cellbuf.payload, ((cell_t *)inbuf)->length, conn_toutp);
- if (retval < ((cell_t *)inbuf)->length)
- {
- log(LOG_ERR,"Connection to the application proxy seems to be lost.");
- break;
- }
- log(LOG_DEBUG,"handle_connection() : Sent %u bytes to client.",retval);
- }
- else
- log(LOG_DEBUG,"handle_connection() : Recived cell has incorrect command or ACI. Discarding.");
-
- cellbuflen = 0; /* get ready for the next cell */
- }
- }
-
- /* send cells to the router */
- send_to_router(or_sock,&outbuf, &outbuflen, &outbuf_dataoffset, &outbuf_datalen, &lastsend, &interval, scheduler, &f_ctx);
- }
-
- /* clean up */
- log(LOG_DEBUG,"handle_connection() : handle_connection() exiting.");
- close(or_sock);
-
- return 0;
-}
-
-/* used for reaping zombie processes */
-void sigchld_handler(int s)
-{
- while (wait(NULL) > 0);
- connections--;
-}
-
-int main(int argc, char *argv[])
-{
- int one = 1;
- int retval = 0;
-
- char *cp; /* temporary storage */
- int i=0; /* iteration counter */
-
- char *conf_filename = NULL; /* configuration file */
-
- size_t sin_size; /* for accept() calls */
-
- u_short p; /* onion proxy port */
-
- /* used for reaping zombie processes */
- struct sigaction sa;
-
- int islocal = 0; /* is the incoming connection local? */
-
- struct rlimit cd_limit; /* resource limit to prevent core dumps */
-
- log(LOG_ERR,NULL); /* assign severity level for logger */
-
- /* prevent core dump */
- retval = getrlimit(RLIMIT_CORE, &cd_limit);
- if (retval == -1)
- {
- log(LOG_ERR,"Could not tell the OS to prevent core dumps for the process.");
- return -1;
- }
- cd_limit.rlim_cur = 0;
- retval = setrlimit(RLIMIT_CORE, &cd_limit);
- if (retval == -1)
- {
- log(LOG_ERR,"Could not tell the OS to prevent core dumps for the process.");
- return -1;
- }
-
- /* get command-line arguments */
- retval = getargs(argc,argv,args,&p,&conf_filename,&loglevel);
- if (retval == -1)
- {
- log(LOG_ERR,"Error processing command-line arguments.");
- exit(1);
- }
-
- /* load config file */
- retval = getconfig(conf_filename,options);
- if (retval == -1)
- {
- log(LOG_ERR,"Error loading configuration file.");
- exit(1);
- }
-
- if (options[RouterFile].err != 1)
- {
- log(LOG_ERR,"RouterFile option required, but not found.");
- exit(1);
- }
-
- if (options[CoinWeight].err == -1)
- {
- log(LOG_ERR,"Error reading the CoinWeight option.");
- exit(1);
- }
-
- if (options[CoinWeight].err == 0)
- {
- /* this is optional, so if not found, set default value */
- options[CoinWeight].r.d = OP_DEFAULT_COIN_WEIGHT;
- }
- else if ((options[CoinWeight].r.d < 0) || (options[CoinWeight].r.d >= 1))
- {
- /* must be a value in [0,1) */
- log(LOG_ERR,"CoinWeight option must be >= 0 and < 1.");
- exit(1);
- }
-
- if (options[Bandwidth].err == 0)
- {
- /* optional, set to default */
- options[Bandwidth].r.i = OP_DEFAULT_BANDWIDTH;
- }
- else if (options[Bandwidth].r.i <= 0)
- {
- log(LOG_ERR,"The Bandwidth option must be an integer greater than zero.");
- exit(1);
- }
-
- if (options[ConnTimeout].err != 1)
- {
- conn_tout.tv_sec = OP_DEFAULT_CONN_TIMEOUT;
- conn_tout.tv_usec = 0;
- }
- else
- {
- if (!options[ConnTimeout].r.i)
- conn_toutp = NULL;
- else
- conn_tout.tv_sec = options[ConnTimeout].r.i;
- conn_tout.tv_usec = 0;
- }
-
- /* load the routers file */
- routerarray = getrouters(options[RouterFile].r.str,&rarray_len);
- if (!routerarray)
- {
- log(LOG_ERR,"Error loading router list.");
- exit(1);
- }
-
- /* get local address so that we know where to allow connections from*/
- retval = gethostname(local_hostname, (size_t)512);
- if (retval < 0)
- {
- log(LOG_ERR,"Error getting local hostname.");
- return -1;
- }
- local_host = gethostbyname(local_hostname);
- if (!local_host)
- {
- log(LOG_ERR,"Error getting local address.");
- return -1;
- }
- log(LOG_DEBUG,"main() : Got local address : %s.",local_hostname);
-
- /* get the server up and running */
- request_sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
- if (request_sock < 0)
- {
- log(LOG_ERR,"Error opening socket.");
- return -1;
- }
- setsockopt(request_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- log(LOG_DEBUG,"main() : Socket opened.");
-
- memset((void *)&local,0,sizeof(local)); /* clear the structure first */
- /* set up the sockaddr_in structure */
- local.sin_family=AF_INET;
- local.sin_addr.s_addr = INADDR_ANY;
- local.sin_port=htons(p);
- /* bind it to the socket */
- retval = bind(request_sock,(struct sockaddr *)&local, sizeof(local));
- if (retval < 0)
- {
- log(LOG_ERR,"Error binding socket to local port %d.",p);
- return retval;
- }
- log(LOG_DEBUG,"main() : Socket bound to port %d.",p);
- /* listen for connections */
- retval = listen(request_sock,SOMAXCONN);
- if (retval < 0)
- {
- log(LOG_ERR,"Could not listen for connections.");
- return retval;
- }
- log(LOG_DEBUG,"main() : Listening for connections.");
- /* server should now be up and running */
-
- /* install the signal handler for making sure zombie processes are killed */
- sa.sa_handler = sigchld_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- retval = sigaction(SIGCHLD,&sa,NULL);
- if (retval < 0)
- {
- log(LOG_ERR,"Could not install a signal handler.");
- return -1;
- }
-
- /* main server loop */
- /* I use a forking server technique - this isn't the most efficient way to do it,
- * but it is simpler. */
- while(1)
- {
- sin_size = sizeof(struct sockaddr_in);
- new_sock = accept(request_sock,(struct sockaddr *)&remote,&sin_size);
- if (new_sock == -1)
- {
- if (errno != EINTR)
- log(LOG_ERR,"Could not accept socket connection.");
- else
- log(LOG_DEBUG,"main() : Interrupt received.");
- continue;
- }
-
- if (connections == options[MaxConn].r.i)
- {
- close(new_sock);
- log(LOG_NOTICE,"Maximum connection limit exceeded. Rejecting incoming request.");
- }
- connections++;
- log(LOG_DEBUG,"main() : Accepted a connection from %s.",inet_ntoa(remote.sin_addr));
-
- /* see if the connection is local, otherwise reject */
- /* first check that the connection is from the local host, otherwise reject */
- if (*(uint32_t *)&remote.sin_addr == inet_addr("127.0.0.1"))
- islocal=1;
- for (i=0; (local_host->h_addr_list[i] != NULL) && (!islocal); i++)
- {
- cp = local_host->h_addr_list[i];
- if (!memcmp(&remote.sin_addr, cp,sizeof(struct in_addr)))
- islocal = 1;
- }
-
- if (!islocal)
- {
- log(LOG_DEBUG,"main() : Incoming connection is not local. Will reject.");
- close(new_sock);
- }
- else
- {
- log(LOG_DEBUG,"main() : Incoming connection seems to be local. Will accept.");
- /* fork a process to deal with the customer */
- if (!fork()) /* this is the child process */
- {
- close(request_sock); /* the child doesn't need the request socket anymore */
-
- /* Main logic of op. */
- retval = handle_connection();
- log(LOG_DEBUG,"main() : Handle connection returned %d.",retval);
- /* End main logic */
-
- exit(retval); /* done, exit */
- }
-
- close(new_sock); /* don't need this anymore */
- }
- }
-
- return retval;
-
-}
-