/* File: proxy_init.c Description: Initialization functions for proxy data structure. */ #include #include #include #include #include #include #include #include #include "config.h" #include "proxy_protos.h" /* allocate memory for the main data structure */ struct mdata * init_mdata ( char *l_name, unsigned short l_port, char *s_name, unsigned short s_port, char *log_file, int verbose ) { struct hostent *he; struct mdata *md = NULL; int ok = 0; /* first try to resolve the server's IP address */ if ( (he = gethostbyname(s_name)) ) { /* now allocate memory for the main data structure */ if ( (md = calloc(1,sizeof(struct mdata))) ) { /* get max number of open files */ md->nofile = getdtablesize(); /* verbosity */ md->verbose = verbose; /* set the server address in the main data structure */ md->server_port = s_port; md->local_port = l_port; md->sa.sin_family = AF_INET; md->sa.sin_port = htons(s_port); memcpy(&(md->sa.sin_addr), he->h_addr_list[0], sizeof(unsigned long)); memcpy(md->server_name, s_name, sizeof(md->server_name)-1); he = gethostbyname(l_name); md->la.sin_family = AF_INET; md->la.sin_port = htons(l_port); memcpy(&(md->la.sin_addr), he->h_addr_list[0], sizeof(unsigned long)); memcpy(md->local_name, l_name, sizeof(md->local_name)-1); /* try to open the log file if one was specified. */ memcpy(md->log_file, log_file, sizeof(md->log_file)-1); if ( md->log_file[0] ) { md->log_fp = fopen(md->log_file,"a"); setlinebuf(md->log_fp); log_msg(md,"===> %s version %s started",PACKAGE,VERSION); log_msg(md,"Local host: %s",md->local_name); log_msg(md,"Local port: %u",md->local_port); log_msg(md,"Server host: %s",md->server_name); log_msg(md,"Server port: %u",md->server_port); } /* otherwise, just use stderr. */ if ( md->log_fp == NULL ) md->log_fp = stderr; /* allocate state structures for the file descriptors */ md->r = calloc(md->nofile,sizeof(struct rdata)); /* allocate a memory pool for the queue buffers */ md->m = g_mem_chunk_create(qdata,65536,G_ALLOC_AND_FREE); ok = (md->r && md->m); } } if ( !ok ) { deinit_mdata(md); md = NULL; } return md; } /* set up event queue, bind to local port, listen for connections */ int pay_attention ( struct mdata *md ) { struct kevent ke; int err = 1; /* create the kernel event queue */ if ( (md->kq = kqueue()) != -1 ) { /* create a socket for binding to port PROXY_PORT */ if ((md->server_sock = socket(PF_INET, SOCK_STREAM, 0)) != -1) { /* make reusable */ setsockopt(md->server_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&err, sizeof(int)); if ( bind(md->server_sock,(struct sockaddr *)&(md->la),sizeof(md->la)) != -1 ) { /* listen for incoming connections */ if ( listen(md->server_sock,SOMAXCONN) != -1 ) { md->r[md->server_sock].status = FD_OPEN; /* register the file descriptor with the event queue */ ke.ident = md->server_sock; ke.filter = EVFILT_READ; ke.flags = EV_ADD; ke.udata = accept_client; if ( kevent(md->kq,&ke,1,NULL,0,NULL) != -1 ) { err = 0; } else { md->kevent_errors++; } } } } } return !err; }