diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2017-10-26 16:44:17 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2017-10-26 16:44:17 (GMT) |
commit | 79d64f400391ce81b4eda73977cb40099256b348 (patch) | |
tree | 47afaed270cf59335dbaf4eb7965eac64a02a687 /xpa/xpans.c | |
parent | 1377ae8b2142276c24d28d65865e459038984c62 (diff) | |
download | blt-79d64f400391ce81b4eda73977cb40099256b348.zip blt-79d64f400391ce81b4eda73977cb40099256b348.tar.gz blt-79d64f400391ce81b4eda73977cb40099256b348.tar.bz2 |
upgrade XPA
Diffstat (limited to 'xpa/xpans.c')
-rw-r--r-- | xpa/xpans.c | 1935 |
1 files changed, 0 insertions, 1935 deletions
diff --git a/xpa/xpans.c b/xpa/xpans.c deleted file mode 100644 index af727aa..0000000 --- a/xpa/xpans.c +++ /dev/null @@ -1,1935 +0,0 @@ -/* - * Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory - */ - -#include <xpap.h> - -#if HAVE_LIBPTHREAD -#include <pthread.h> -static pthread_mutex_t xpans_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif - -#define MAX_ERRORS 5 - -static int doproxy=0; -static unsigned int localhost_ip=0; - -extern char *optarg; -extern int optind; - -typedef struct entrec{ - struct entrec *next; - char *method; - char *xclass; - char *name; - char *type; - char *user; - char *info; -} *Entry, EntryRec; - -typedef struct reqrec{ - struct reqrec *next; - int sock; - unsigned int ip; - int port; - Entry entry; -} *Req, ReqRec; - -static char *helpbuf = "xpans commands:\nhelp\t\t\t\t# print this help message\nlist\t\t\t\t# list all entries\nlookup class:name type user\t# lookup entries of this type and user\n"; - -static int keepalive=0; -static int ksec=0; -static int mtype = 0; -static int nentry = 0; -static int exconn=0; -static int sock=-1; -static char *logfile=NULL; -static time_t lastt=(time_t)0; -static time_t curt=(time_t)0; -static FILE *securefp=NULL; -static Req reqhead=NULL; - -static int LookupReq _PRx((Req xreq, char *lbuf, int flag)); -static int ListReq _PRx((Req xreq, int flag)); -static void HelpReq _PRx((Req xreq, int flag)); -#ifdef __STDC__ -static void SecureLog(char *format, ...); -#else -static void SecureLog(); -#endif - -#if HAVE_LIBPTHREAD -/* - *---------------------------------------------------------------------------- - * - * Routine: doxpaloop - * - * Purpose: start up XPAMainLoop in another thread - * - * Returns: NONE - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -void *doxpaloop(void *arg) -#else -void *doxpaloop(arg) - void *arg; -#endif -{ - XPAMainLoop(); - return (void *)NULL; -} -#endif - -/* - *---------------------------------------------------------------------------- - * - * Routine: receive_proxy - * - * Purpose: receive callback for a proxy request - * - * Returns: 0 for success, -1 for failure - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -receive_proxy (void *client_data, void *call_data, char *paramlist, - char *buf, int len) -#else -int receive_proxy(client_data, call_data, paramlist, buf, len) - void *client_data; - void *call_data; - char *paramlist; - char *buf; - int len; -#endif -{ - XPA xpa = (XPA)call_data; - char *xtemplate; - char *mode; - char *err; - char *s; - char xmode[SZ_LINE]; - char tbuf[SZ_LINE]; - int fd=0; - int pfd=-1; - int got=0; - Req req=NULL; - - xtemplate = xpa->comm->target; - mode = xpa->comm->info; - fd = xpa->comm->datafd; - - /* get proxy fd and associated xpans request struct */ - if( mode ){ - strcpy(xmode, mode); - if( keyword(xmode, "nsproxy", tbuf, SZ_LINE) ){ - pfd = strtol(tbuf, &s, 0); - if( s != tbuf ){ - for(req=reqhead; req!=NULL; req=req->next){ - if( req->sock == pfd ){ - break; - } - } - } - } - } - if( pfd < 0 ){ - snprintf(tbuf, SZ_LINE, "invalid or missing proxy fd"); - XPAError(xpa, tbuf); - return(-1); - } - else if( req == NULL ){ - snprintf(tbuf, SZ_LINE, "could not find xpans fd for proxy fd %d", pfd); - XPAError(xpa, tbuf); - return(-1); - } - - FPRINTF((stderr, "%sreceive_proxy: fd=%d xtmpl=%s mode=%s paramlist=%s\n", - _sp, xpa->comm->cmdfd, xtemplate, mode, - paramlist?paramlist:"NONE")); - - if( XPASetFd(xpa, xtemplate, paramlist, mode, fd, NULL, &err, 1) ){ - /* display errors and free up strings */ - if( err != NULL ){ - XPAError(xpa, err); - xfree(err); - got = -1; - } - } - else{ - got = -1; - } - - FPRINTF((stderr, "%sreceive_proxy done\n", _sp)); - return(got); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: send_proxy - * - * Purpose: send callback for a proxy request - * - * Returns: 0 for success, -1 for failure - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -send_proxy (void *client_data, void *call_data, char *paramlist, - char **buf, size_t *len) -#else -static int send_proxy(client_data, call_data, paramlist, buf, len) - void *client_data; - void *call_data; - char *paramlist; - char **buf; - size_t *len; -#endif -{ - XPA xpa = (XPA)call_data; - char *xtemplate; - char *mode; - char *err; - char *s; - char xmode[SZ_LINE]; - char tbuf[SZ_LINE]; - int fd=0; - int pfd=-1; - int got=0; - Req req=NULL; - - xtemplate = xpa->comm->target; - mode = xpa->comm->info; - fd = xpa->comm->datafd; - - /* get proxy fd and associated xpans request struct */ - if( mode ){ - strcpy(xmode, mode); - if( keyword(xmode, "nsproxy", tbuf, SZ_LINE) ){ - pfd = strtol(tbuf, &s, 0); - if( s != tbuf ){ - for(req=reqhead; req!=NULL; req=req->next){ - if( req->sock == pfd ){ - break; - } - } - } - } - } - if( pfd < 0 ){ - snprintf(tbuf, SZ_LINE, "invalid or missing proxy fd"); - XPAError(xpa, tbuf); - return(-1); - } - else if( req == NULL ){ - snprintf(tbuf, SZ_LINE, "could not find xpans fd for proxy fd %d", pfd); - XPAError(xpa, tbuf); - return(-1); - } - - FPRINTF((stderr, "%ssend_proxy: fd=%d xtemplate=%s mode=%s paramlist=%s\n", - _sp, xpa->comm->cmdfd, xtemplate, mode, paramlist?paramlist:"NONE")); - - if( XPAGetFd(xpa, xtemplate, paramlist, mode, &fd, NULL, &err, 1) ){ - /* display errors and free up strings */ - if( err != NULL ){ - XPAError(xpa, err); - xfree(err); - got = -1; - } - } - else{ - got = -1; - } - - FPRINTF((stderr, "%ssend_proxy done\n", _sp)); - return(got); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: receive_cb - * - * Purpose: receive callback for XPA access point - * - * Returns: 0 for success, -1 for failure - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -receive_cb (void *client_data, void *call_data, char *paramlist, - char *buf, size_t len) -#else -int receive_cb(client_data, call_data, paramlist, buf, len) - void *client_data; - void *call_data; - char *paramlist; - char *buf; - size_t len; -#endif -{ - XPA xpa = (XPA)call_data; - char tbuf[SZ_LINE]; - - /* if target is not xpans, we have a proxy request */ - snprintf(tbuf, SZ_LINE, "%s:%s", XPANS_CLASS, XPANS_NAME); - if( strcmp(xpa->comm->target, tbuf) ){ - if( doproxy ) - return(receive_proxy(client_data, call_data, paramlist, buf, len)); - else{ - XPAError(xpa, "proxy requests not enabled in this xpans"); - return(-1); - } - } - - /* nothing to do for normal receive callback */ - XPAError(xpa, "no receive function defined for xpans"); - return(-1); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: send_cb - * - * Purpose: send callback for XPA access point - * - * Returns: 0 for success, -1 for failure - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -send_cb (void *client_data, void *call_data, char *paramlist, - char **buf, size_t *len) -#else -static int send_cb(client_data, call_data, paramlist, buf, len) - void *client_data; - void *call_data; - char *paramlist; - char **buf; - size_t *len; -#endif -{ - XPA xpa = (XPA)call_data; - Req req; - char tbuf[SZ_LINE]; - char ebuf[SZ_LINE]; - char tmpl[SZ_LINE]; - char type[SZ_LINE]; - char users[SZ_LINE]; - int got=0; - int wp=0; - - /* if target is not xpans, we have a proxy request */ - snprintf(tbuf, SZ_LINE, "%s:%s", XPANS_CLASS, XPANS_NAME); - if( strcmp(xpa->comm->target, tbuf) ){ - if( doproxy ) - return(send_proxy(client_data, call_data, paramlist, buf, len)); - else{ - XPAError(xpa, "proxy requests not enabled in this xpans"); - return(-1); - } - } - - if( paramlist && *paramlist ) - SecureLog("xpaget from host %x:%d (%s): %s", - xpa->comm->cmdip, xpa->comm->cmdport, - getiphost(xpa->comm->cmdip), - (paramlist && *paramlist)?paramlist:"<no params>"); - else - SecureLog("xpaget from host %x:%d (%s)", - xpa->comm->cmdip, xpa->comm->cmdport, - getiphost(xpa->comm->cmdip)); - if( (req = (Req)xcalloc(1, sizeof(ReqRec))) == NULL ) - return(-1); - if( xpa_datafd(xpa) >= 0 ){ - req->sock = xpa_datafd(xpa); - } - -#if HAVE_LIBPTHREAD - /* lock the mutex before processing a request */ - if( doproxy >= 2 ) pthread_mutex_lock(&xpans_mutex); -#endif - - /* execute the appropriate routine */ - if( paramlist && *paramlist && word(paramlist, tbuf, &wp) ){ - if( !strcmp(tbuf, "list") ){ - ListReq(req, 0); - } - else if( !strcmp(tbuf, "help") ){ - HelpReq(req, 0); - } - else if( !strcmp(tbuf, "lookup") ){ - if( word(paramlist, tmpl, &wp ) ){ - /* look for type */ - if( !word(paramlist, type, &wp ) ) - strcpy(type, XPA_ACLS); - /* look for users */ - if( !word(paramlist, users, &wp ) ) - strcpy(users, "*"); - snprintf(tbuf, SZ_LINE, "%s %s %s", tmpl, type, users); - LookupReq(req, tbuf, 0); - } - else{ - strcpy(ebuf, - "XPA$ERROR 'lookup' requires class:name [type] [user]\n"); - XPAPuts(NULL, req->sock, ebuf, XPALongTimeout()); - got = -1; - } - } - else{ - snprintf(ebuf, SZ_LINE, "XPA$ERROR unknown command '%s'\n", tbuf); - XPAPuts(NULL, req->sock, ebuf, XPALongTimeout()); - got = -1; - } - } - else { - ListReq(req, 0); - } - -#if HAVE_LIBPTHREAD - /* unlock the mutex */ - if( doproxy >= 2 ) pthread_mutex_unlock(&xpans_mutex); -#endif - - /* clean up */ - if( req ) xfree(req); - return(got); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: Log - * - * Purpose: write all names to a backup log - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -Log (void) -#else -static void Log() -#endif -{ - FILE *fp; - Req req; - Entry entry; - - if( !logfile ) - return; - if( !strcasecmp(logfile, "stdout") ) - fp = stdout; - else if( (fp=fopen(logfile, "w")) == NULL ) - return; - for(req=reqhead; req!=NULL; req=req->next){ - for(entry=req->entry; entry!=NULL; entry=entry->next){ - fprintf(fp, "# add %s %s %s %s %s\n", - entry->method, entry->xclass, - entry->name, entry->type, entry->user); - /* last one */ - if( entry->next == NULL ) - fprintf(fp, "xpaset -p %s -nsconnect\n", entry->method); - } - } - if( fp != stdout ) - fclose(fp); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: SecureLog - * - * Purpose: write security info to a backup log - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef __STDC__ -void SecureLog(char *format, ...) -{ - char sbuf[SZ_LINE]; - time_t t; - va_list args; - va_start(args, format); -#else -void SecureLog(va_alist) va_dcl -{ - char *format; - char sbuf[SZ_LINE]; - time_t t; - va_list args; - - va_start(args); - format = va_arg(args, char *); -#endif - if( securefp == NULL ) - return; - t = time(NULL); - vsnprintf(sbuf, SZ_LINE, format, args); - fprintf(securefp, "%s", sbuf); - fprintf(securefp, "\t%s", ctime(&t)); - fflush(securefp); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: SplitArg - * - * Purpose: split the specified argument by changing a ":" to a space - * splitting is done in place - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -SplitArg (char *buf, int arg) -#else -static void SplitArg(buf, arg) - char *buf; - int arg; -#endif -{ - int i; - char *s; - - /* point to beginning of buffer */ - s = buf; - /* skip over previous args */ - for(i=0; i<arg; i++){ - /* skip up to white space */ - while( *s && !isspace((int)*s) ) - s++; - /* skip over white space to next arg */ - while( *s && isspace((int)*s) ) - s++; - } - /* we now are pointing at the arg in question. - look for a ':' (up to next white space) and change to space */ - while( *s && !isspace((int)*s) ){ - if( *s == ':' ){ - *s = ' '; - break; - } - else - s++; - } -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: NewEntry - * - * Purpose: allocate a new XPA entry - * - * Returns: entry struct - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -NewEntry (Req req, - char *method, char *xclass, char *name, - char *type, char *user, char *info) -#else -static int NewEntry(req, method, xclass, name, type, user, info) - Req req; - char *method; - char *xclass; - char *name; - char *type; - char *user; - char *info; -#endif -{ - Entry entry, cur; - Req xreq; - - /* don't duplicate with any other entry */ - for(xreq=reqhead; xreq!=NULL; xreq=xreq->next){ - for(entry=xreq->entry; entry!=NULL; entry=entry->next){ - if( !strcmp(entry->method, method) && - !strcmp(entry->xclass, xclass) && - !strcmp(entry->name, name) && - !strcmp(entry->type, type) && - !strcmp(entry->user, user) && - !strcmp(entry->info, info) ) - return(1); - } - } - - /* allocate new entry */ - if( (entry = (Entry)xcalloc(1, sizeof(EntryRec))) == NULL ) - return(-1); - - /* fill in the blanks */ - entry->xclass = xstrdup(xclass); - entry->name = xstrdup(name); - entry->method = xstrdup(method); - entry->type = xstrdup(type); - entry->user = xstrdup(user); - entry->info = xstrdup(info); - - FPRINTF((stderr, "%sNewEntry: %s %s %s %s %s %s\n", _sp, - xclass, name, method, type, user, info)); - - /* add this to end of the list */ - if( req->entry == NULL ){ - req->entry = entry; - } - else{ - for(cur=req->entry; cur->next!=NULL; cur=cur->next) - ; - cur->next = entry; - } - - /* inc the total number of entries */ - nentry++; - - /* return the news */ - return(0); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: FreeEntry - * - * Purpose: free up an XPA entry - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -FreeEntry (Req req, Entry entry) -#else -static void FreeEntry(req, entry) - Req req; - Entry entry; -#endif -{ - Entry cur; - - /* remove this entry from the list so it can't be found */ - if( entry == req->entry ){ - req->entry = req->entry->next; - } - else{ - for(cur=req->entry; cur!=NULL; cur=cur->next){ - if( entry == cur->next ){ - cur->next = entry->next; - break; - } - } - } - - FPRINTF((stderr, "%sFreeEntry: %s %s\n", _sp, entry->xclass, entry->name)); - - /* now free this struct */ - if( entry->method ) - xfree(entry->method); - if( entry->xclass ) - xfree(entry->xclass); - if( entry->name ) - xfree(entry->name); - if( entry->type ) - xfree(entry->type); - if( entry->user ) - xfree(entry->user); - if( entry->info ) - xfree(entry->info); - xfree(entry); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: DelEntry - * - * Purpose: Delete an XPA entry - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -DelEntry (Req req, char *method) -#else -static int DelEntry(req, method) - Req req; - char *method; -#endif -{ - Entry cur, tcur; - int got=-1; - - for(cur=req->entry; cur!=NULL; ){ - tcur = cur->next; - if( ((method == NULL) || (*method == '\0')) || - (!strcmp(method, "@") && (*cur->method == '@')) || - !strcmp(cur->method, method) ){ - FreeEntry(req, cur); - got = 0; - } - cur = tcur; - } - return(got); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: FirewallEntry - * - * Purpose: Correct the method to take a firewall into account - * we do this by taking the ip from the socket packet instead - * of the specified ip, if they differ - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -FirewallEntry (Req req, char *method) -#else -static void FirewallEntry(req, method) - Req req; - char *method; -#endif -{ - unsigned int ip; - unsigned short port; - - if( mtype != XPA_INET ) - return; - if( XPAParseIpPort(method, &ip, &port) ){ - if( (ip != req->ip) && (req->ip != localhost_ip) ){ - SecureLog("firewall %d: changing ip from %x to %x", - req->sock, ip, req->ip); - snprintf(method, SZ_LINE, "%x:%d", req->ip, port); - } - } -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: NewReq - * - * Purpose: allocate a new XPA request struct - * - * Returns: Req struct - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static Req -NewReq (int sock, unsigned int ip, int port) -#else -static Req NewReq(sock, ip, port) - int sock; - unsigned int ip; - int port; -#endif -{ - Req req; - Req cur; - - if( (req = (Req)xcalloc(1, sizeof(ReqRec))) == NULL ) - return(NULL); - - /* fill in the blanks */ - req->sock = sock; - req->ip = ip; - req->port = port; - - /* add this to end of the list */ - if( reqhead == NULL ){ - reqhead = req; - } - else{ - for(cur=reqhead; cur->next!=NULL; cur=cur->next) - ; - cur->next = req; - } - /* return the news */ - return(req); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: FreeReq - * - * Purpose: free up an XPA request entry - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -FreeReq (Req req) -#else -static void FreeReq(req) - Req req; -#endif -{ - Req cur; - /* remove this entry from the list so it can't be found */ - if( req == reqhead ){ - reqhead = req->next; - } - else{ - for(cur=reqhead; cur!=NULL; cur=cur->next){ - if( req == cur->next ){ - cur->next = req->next; - break; - } - } - } - /* close the communication channel */ - close(req->sock); - /* now free this struct */ - xfree(req); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: AddReq - * - * Purpose: add an XPA entry to the list - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -AddReq (Req req, char *lbuf, int flag) -#else -static void AddReq(req, lbuf, flag) - Req req; - char *lbuf; - int flag; -#endif -{ - int got; - char xclass[SZ_LINE]; - char name[SZ_LINE]; - char method[SZ_LINE]; - char omethod[SZ_LINE]; - char type[SZ_LINE]; - char user[SZ_LINE]; - char tbuf[SZ_LINE]; - - SplitArg(lbuf, 1); - got = sscanf(lbuf, "%s %s %s %s %s", method, xclass, name, type, user); - if( got == 5 ){ - /* fix method if we can determine its been through a firewall */ - strcpy(omethod, method); - FirewallEntry(req, method); - if( !strcmp(omethod, method) ) - strcpy(tbuf, method); - else - snprintf(tbuf, SZ_LINE, "%s,%s", method, omethod); - /* add the new entry */ - got = NewEntry(req, tbuf, xclass, name, type, user, XPA_DEF_CLIENT_INFO); - Log(); - if( flag ){ - switch(got){ - case -1: - XPAPuts(NULL, req->sock, "XPA$ERROR could not add entry\n", - XPALongTimeout()); - break; - case 0: - XPAPuts(NULL, req->sock, "XPA$OK\n", XPALongTimeout()); - break; - case 1: - XPAPuts(NULL, req->sock, "XPA$EXISTS entry already exists\n", - XPALongTimeout()); - break; - default: - XPAPuts(NULL, req->sock, "XPA$ERROR could not add entry\n", - XPALongTimeout()); - break; - } - } - } - else{ - strcpy(tbuf, - "XPA$ERROR 'add' requires 4 args: ip:port class:name type user\n"); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - } -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: AddProxyReq - * - * Purpose: add an XPA proxy entry to the list - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -AddProxyReq (Req req, char *lbuf, int flag) -#else -static void AddProxyReq(req, lbuf, flag) - Req req; - char *lbuf; - int flag; -#endif -{ - int got=0; - char xclass[SZ_LINE]; - char name[SZ_LINE]; - char method[SZ_LINE]; - char omethod[SZ_LINE]; - char type[SZ_LINE]; - char user[SZ_LINE]; - char info[SZ_LINE]; - char tbuf[SZ_LINE]; - - /* make sure we are accepting proxy requests */ - if( !doproxy ){ - strcpy(tbuf, - "XPA$ERROR: proxy requests not enabled in this xpans\n"); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - return; - } - - SplitArg(lbuf, 1); - got = sscanf(lbuf, "%s %s %s %s %s", method, xclass, name, type, user); - if( got == 5 ){ - if( XPAMethod(method) == XPA_INET ){ - /* fix method if we can determine its been through a firewall */ - strcpy(omethod, method); - FirewallEntry(req, method); - if( !strcmp(omethod, method) ) - snprintf(tbuf, SZ_LINE, "@%s", method); - else - snprintf(tbuf, SZ_LINE, "@%s,%s", method, omethod); - } - else{ - strcpy(tbuf, - "XPA$ERROR 'proxy' requires INET method\n"); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - return; - } - /* save info */ - snprintf(info, SZ_LINE, "nsproxy=%d,ns=(%s,%s,%s,%s),dofork=true", - req->sock, xclass, name, method, omethod); - /* add the new entry */ - got = NewEntry(req, tbuf, xclass, name, type, user, info); - Log(); - if( flag ){ - switch(got){ - case -1: - XPAPuts(NULL, req->sock, "XPA$ERROR could not add entry\n", - XPALongTimeout()); - break; - case 0: - XPAPuts(NULL, req->sock, "XPA$OK\n", XPALongTimeout()); - break; - case 1: - XPAPuts(NULL, req->sock, "XPA$EXISTS entry already exists\n", - XPALongTimeout()); - break; - default: - XPAPuts(NULL, req->sock, "XPA$ERROR could not add entry\n", - XPALongTimeout()); - break; - } - } - } - else{ - strcpy(tbuf, - "XPA$ERROR 'proxy' requires 4 args: ip:port class:name type user\n"); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - } -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: DelReq - * - * Purpose: delete an XPA entry from the list - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -DelReq (Req req, char *lbuf, int flag) -#else -static void DelReq(req, lbuf, flag) - Req req; - char *lbuf; - int flag; -#endif -{ - int got=0; - char method[SZ_LINE]; - char omethod[SZ_LINE]; - char tbuf[SZ_LINE]; - - if( lbuf != NULL ){ - if( sscanf(lbuf, "%s", method) == 1 ){ - /* fix method if we can determine its been through a firewall */ - strcpy(omethod, method); - FirewallEntry(req, method); - if( !strcmp(omethod, method) ) - strcpy(tbuf, method); - else - snprintf(tbuf, SZ_LINE, "%s,%s", method, omethod); - got = DelEntry(req, tbuf); - Log(); - if( flag ){ - if( got == 0 ) - XPAPuts(NULL, req->sock, "XPA$OK\n", XPALongTimeout()); - else - XPAPuts(NULL, req->sock, "XPA$ERROR entry does not exist\n", - XPALongTimeout()); - } - } - else{ - strcpy(tbuf, "XPA$ERROR 'del' requires 1 arg: ip:port\n"); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - } - } - else{ - /* connection is closed -- free all entries for req, and delete req */ - FPRINTF((stderr, "%sxpans request really died: %d\n", _sp, req->sock)); - DelEntry(req, NULL); - FreeReq(req); - Log(); - } -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: DelProxyReq - * - * Purpose: delete an XPA entry from the list - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -DelProxyReq (Req req, char *lbuf, int flag) -#else -static void DelProxyReq(req, lbuf, flag) - Req req; - char *lbuf; - int flag; -#endif -{ - int got=0; - char method[SZ_LINE]; - char omethod[SZ_LINE]; - char tbuf[SZ_LINE]; - - /* make sure we are accepting proxy requests */ - if( !doproxy ){ - strcpy(tbuf, - "XPA$ERROR: proxy requests not enabled in this xpans\n"); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - return; - } - - if( lbuf != NULL ){ - if( sscanf(lbuf, "%s", method) == 1 ){ - /* fix method if we can determine its been through a firewall */ - strcpy(omethod, method); - FirewallEntry(req, method); - if( !strcmp(omethod, method) ) - strcpy(tbuf, method); - else - snprintf(tbuf, SZ_LINE, "@%s,%s", method, omethod); - /* free the specified entry */ - got = DelEntry(req, tbuf); - Log(); - if( flag ){ - if( got == 0 ) - XPAPuts(NULL, req->sock, "XPA$OK\n", XPALongTimeout()); - else - XPAPuts(NULL, req->sock, "XPA$ERROR entry does not exist\n", - XPALongTimeout()); - } - } - else{ - strcpy(tbuf, "XPA$ERROR 'del' requires 1 arg: ip:port\n"); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - } - } - else{ - /* connection is closed -- free all entries for req, and delete req */ - DelEntry(req, "@"); - /* if this is the last entry, delete the request struct as well */ - if( req->entry == NULL ){ - FreeReq(req); - } - Log(); - } -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: LookupReq - * - * Purpose: lookup a template in the XPA list - * - * Returns: number of matched lookups - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -LookupReq (Req xreq, char *lbuf, int flag) -#else -static int LookupReq(xreq, lbuf, flag) - Req xreq; - char *lbuf; - int flag; -#endif -{ - int i; - int nrec; - int got=0; - int domethod=0; - int slen=1024; - int *lens; - char args[4][SZ_LINE]; - char ctmpl[SZ_LINE]; - char ntmpl[SZ_LINE]; - char tbuf[SZ_LINE]; - char type[SZ_LINE]; - char users[SZ_LINE]; - char method[SZ_LINE]; - char *user; - char *usercopy; - char **strings; - char *tstring; - Req req; - Entry entry; - - SplitArg(lbuf, 0); - nrec = sscanf(lbuf, "%s %s %s %s", args[0], args[1], args[2], args[3]); - switch(nrec){ - case 0: - goto error; - case 1: - strcpy(ctmpl, "*"); - strcpy(ntmpl, args[0]); - strcpy(type, "*"); - strcpy(users, "*"); - if( *args[0] == '@' ){ - strcpy(method, args[0]); - domethod = 1; - } - break; - case 2: - strcpy(ctmpl, "*"); - strcpy(ntmpl, args[0]); - strcpy(type, args[1]); - strcpy(users, "*"); - if( *args[0] == '@' ){ - snprintf(method, SZ_LINE, "%s:%s", args[0], args[1]); - domethod = 1; - } - break; - case 3: - strcpy(ctmpl, "*"); - strcpy(ntmpl, args[0]); - strcpy(type, args[1]); - strcpy(users, args[2]); - if( *args[0] == '@' ){ - strcpy(method, args[0]); - domethod = 1; - } - break; - case 4: - strcpy(ctmpl, args[0]); - strcpy(ntmpl, args[1]); - strcpy(type, args[2]); - strcpy(users, args[3]); - if( *args[0] == '@' ){ - snprintf(method, SZ_LINE, "%s:%s", args[0], args[1]); - domethod = 1; - } - break; - case 5: - goto error; - } - strings = (char **)xmalloc(slen * sizeof(char *)); - lens = (int *)xmalloc(slen * sizeof(int)); - lens[0] = 0; - for(req=reqhead; req!=NULL; req=req->next){ - for(entry=req->entry; entry!=NULL; entry=entry->next){ - /* check method or class:name */ - if( domethod ){ - if( strcmp(entry->method, method) ) - continue; - } - else{ - if( !tmatch(entry->xclass, ctmpl) || !tmatch(entry->name, ntmpl) ) - continue; - } - /* check type */ - if( strcmp(type, "*") && !strpbrk(entry->type, type) ) - continue; - /* check user */ - if( !strcmp(users, "*") || !strcmp(users, entry->user) ){ - user = entry->user; - } - else{ - user = NULL; - usercopy = (char *)xstrdup(users); - for(user=(char *)strtok(usercopy, " :;,"); - user!=NULL; - user=(char *)strtok(NULL," :;,")){ - if ( !strcasecmp(user, entry->user) ){ - break; - } - } - if( usercopy ) - xfree(usercopy); - } - if( !user ) - continue; - /* made it through all checks! */ - if( domethod || (*entry->method == '@') ){ - snprintf(tbuf, SZ_LINE, "%s %s %s %s %s %s\n", - entry->xclass, entry->name, - entry->type, XPANSMethod(NULL,1), entry->user, entry->info); - FPRINTF((stderr, "%sLookupReq: method lookup found:\n%s", _sp, tbuf)); - } - else{ - snprintf(tbuf, SZ_LINE, "%s %s %s %s %s %s\n", - entry->xclass, entry->name, - entry->type, entry->method, entry->user, entry->info); - FPRINTF((stderr, "%sLookupReq: class/name lookup got:\n%s", - _sp, tbuf)); - } - if( got >= (slen-2) ){ - slen *= 2; - strings = (char **)xrealloc(strings, slen * sizeof(char *)); - lens = (int *)xrealloc(lens, slen * sizeof(int)); - } - strings[got] = xstrdup(tbuf); - lens[got+1] = lens[got] + strlen(strings[got]); - got++; - } - } - if( flag ){ - strings[got] = xstrdup("XPA$OK\n"); - lens[got+1] = lens[got] + strlen(strings[got]); - got++; - } - /* write one buffer load: we have to avoid multiple writes in a row - because tcp_delay buffers these (i.e., the Nagle algorithm) and kills - the performance */ - if( got > 0 ){ - tstring = (char *)xcalloc(lens[got]+1, sizeof(char)); - for(i=0; i<got; i++){ - if( strings[i] ){ - strcpy(&(tstring[lens[i]]), strings[i]); - } - } - XPAPutBuf(NULL, xreq->sock, tstring, lens[got], XPALongTimeout()); - for(i=0; i<got; i++){ - if( strings[i] ) - xfree(strings[i]); - } - if( tstring ) - xfree(tstring); - } - if( strings ) - xfree(strings); - if( lens ) - xfree(lens); - return(got); - -error: - strcpy(tbuf, - "XPA$ERROR xpans 'lookup' requires: class:name [type] [user]\n"); - XPAPuts(NULL, xreq->sock, tbuf, XPALongTimeout()); - return(0); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: HelpReq - * - * Purpose: send help message - * - * Returns: none - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -HelpReq (Req xreq, int flag) -#else -static void HelpReq(xreq, flag) - Req xreq; - int flag; -#endif -{ - /* XPAPuts(NULL, xreq->sock, helpbuf, XPALongTimeout()); */ - XPAPutBuf(NULL, xreq->sock, helpbuf, strlen(helpbuf), XPALongTimeout()); - if( flag ) - XPAPuts(NULL, xreq->sock, "XPA$OK\n", XPALongTimeout()); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: ListReq - * - * Purpose: list all entries in the XPA list - * - * Returns: number of entries listed - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -ListReq (Req xreq, int flag) -#else -static int ListReq(xreq, flag) - Req xreq; - int flag; -#endif -{ - int got=0; - char tbuf[SZ_LINE]; - Req req; - Entry entry; - - for(req=reqhead; req!=NULL; req=req->next){ - for(entry=req->entry; entry!=NULL; entry=entry->next){ - snprintf(tbuf, SZ_LINE, "%s %s %s %s %s\n", - entry->xclass, entry->name, - entry->type, entry->method, entry->user); - XPAPuts(NULL, xreq->sock, tbuf, XPALongTimeout()); - got++; - } - } - if( flag ) - XPAPuts(NULL, xreq->sock, "XPA$OK\n", XPALongTimeout()); - return(got); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: StatusReq - * - * Purpose: send short "alive" message to inquiring server - * - * Returns: NONE - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -StatusReq (Req xreq) -#else -static void StatusReq(xreq) - Req xreq; -#endif -{ - XPAPuts(NULL, xreq->sock, "XPA$OK\n", XPALongTimeout()); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: VersionReq - * - * Purpose: send version info to inquiring server - * - * Returns: NONE - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -VersionReq (Req xreq, char *vstr) -#else -static void VersionReq(xreq, vstr) - Req xreq; - char *vstr; -#endif -{ - int ip=0; - int dowarn=0; - char tbuf[SZ_LINE]; - - /* version check: server version should be <= our version */ - if( word(vstr, tbuf, &ip) ){ - dowarn = (XPAVersionCheck(XPA_VERSION, tbuf)>0); - } - else{ - strcpy(tbuf, "unknown/pre-2.1"); - dowarn = 1; - } - if( dowarn ) - XPAVersionWarn(tbuf, XPA_VERSION); - snprintf(tbuf, SZ_LINE, "XPA$VERSION %s\n", XPA_VERSION); - XPAPuts(NULL, xreq->sock, tbuf, XPALongTimeout()); -} - -#ifdef ANSI_FUNC -void -usage (char *s) -#else -void usage(s) - char *s; -#endif -{ - fprintf(stderr, "\n"); - fprintf(stderr, "usage: xpans [-h] [-e] [-k msec] [-l log] [-p port] [-s slog] [-P n] \n"); - fprintf(stderr, "switches:\n"); - fprintf(stderr, "\t-h\tprint this message\n"); - fprintf(stderr, "\t-e\texit when there are no more XPA connections\n"); - fprintf(stderr, "\t-k msec\tsend keepalive messages every n sec\n"); - fprintf(stderr, "\t-l file\tlog data base entries to specified file\n"); - fprintf(stderr, "\t-p port\tlisten for connections on specified port\n"); - fprintf(stderr, "\t-s file\tlog security info to specified file\n"); - fprintf(stderr, "\t-P 1|2\taccept proxy requests (1) using separate thread (2) \n"); - fprintf(stderr, "\t--version display version and exit\n"); - fprintf(stderr, "\n(version: %s)\n", XPA_VERSION); - exit(1); -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: KeepAliveReq - * - * Purpose: send keep alive to all open connections - * - * Returns: number of entries processed - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -KeepAliveReq (void) -#else -static int KeepAliveReq() -#endif -{ - int got=0; - Req req; - - /* return if keepalive is turned off */ - if( !keepalive ) - return(0); - /* get current time */ - curt = time(NULL); - /* if keep alive time has passed, send keep alive messages */ - if( (curt - lastt) > ksec ){ - for(req=reqhead; req!=NULL; req=req->next){ - send(req->sock, " ", 1, MSG_OOB); - got++; - } - lastt = curt; - } - return(got); -} - -#ifdef ANSI_FUNC -int -main (int argc, char **argv) -#else -int -main(argc, argv) - int argc; - char **argv; -#endif -{ - char lbuf[SZ_LINE]; - char tbuf[SZ_LINE]; - char cmd[SZ_LINE]; - char method[SZ_LINE]; - int c; - int sock2; - int width; - int got; - int wp; - int cmdport; - int sval; - int nerr=0; - int oum; - int llen; - int reuse_addr=1; - int keep_alive=1; - unsigned int ip; - unsigned int cmdip; - unsigned short port=0; - socklen_t slen=sizeof(struct sockaddr_in); - struct sockaddr_in sock_in; - struct sockaddr_in sock_in2; -#if HAVE_LIBPTHREAD - pthread_t tid; -#endif -#if HAVE_SYS_UN_H - struct sockaddr_un sock_un; - struct sockaddr_un sock_un2; - char lockfile[SZ_LINE]; - int lockfd=-1; - struct flock lock; -#endif - fd_set readfds; - struct timeval tv; - struct timeval *tvp; - Req req, treq; - XPA xpa; - - /* display version and exit, if necessary */ - if( (argc == 2) && !strcmp(argv[1], "--version") ){ - fprintf(stderr, "%s\n", XPA_VERSION); - exit(0); - } - - /* init the XPA environment */ - XPAInitEnv(); - - /* Disable SIGPIPE so we do not die if the client dies. - * Rather, we will get an EOF on reading or writing. - */ - xsignal_sigpipe(); - - /* we want the args in the same order in which they arrived, and - gnu getopt sometimes changes things without this */ - putenv("POSIXLY_CORRECT=true"); - - /* process command line args */ - while ((c = getopt(argc, argv, "ef:hk:l:p:P:s:")) != -1){ - switch(c){ - case 'h': - usage(argv[0]); - exit(0); - case 'e': - exconn = 1; - break; - case 'f': -#if HAVE_SYS_UN_H - /* method is unix with specified file */ - putenv(xstrdup("XPA_METHOD=unix")); - snprintf(tbuf, SZ_LINE, "XPA_NSUNIX=%s", optarg); - putenv(xstrdup(tbuf)); - break; -#else - fprintf(stderr, "XPA$ERROR: UNIX sockets not supported on this host\n"); - exit(1); - break; -#endif - case 'k': - fprintf(stderr, - "XPA$KEEPALIVE: URG TCP data is changed by some Cisco routers into in-band data.\n"); - fprintf(stderr, - "Encountering such a router will break the keep-alive function and may break your\n"); - fprintf(stderr, "XPA server as well. Proceed with caution!\n"); - keepalive = 1; - ksec = atoi(optarg); - if( ksec <= 0 ) - ksec = 1; - break; - case 'l': - logfile = optarg; - break; - case 'p': - /* method is inet with specified port */ - putenv(xstrdup("XPA_METHOD=inet")); - snprintf(tbuf, SZ_LINE, "XPA_NSINET=$host:%d", atoi(optarg)); - putenv(xstrdup(tbuf)); - break; - case 'P': - if( istrue(optarg) ) - doproxy = 1; - else if( isfalse(optarg) ) - doproxy = 0; - else - doproxy = atoi(optarg); - if( doproxy < 0 ) - doproxy = 0; -#if HAVE_LIBPTHREAD==0 - if( doproxy >= 2 ){ - fprintf(stderr, - "XPA$ERROR: xpans not built with thread support on this host\n"); - exit(1); - } -#endif - break; - case 's': - if( !strcasecmp(optarg, "stdout") ){ - securefp = stdout; - } - else if( (securefp=fopen(optarg, "w")) == NULL ){ - perror("securefp"); - exit(1); - } - break; - } - } - - /* get default ip and port */ - strcpy(method, XPANSMethod(NULL, 0)); - mtype = XPAMethod(method); - localhost_ip = gethostip("$localhost"); - - /* start secure logging, if necessary */ - SecureLog("Starting xpans: %s", method); - /* set up communication method */ - switch(mtype){ - case XPA_INET: - XPAParseIpPort(method, &ip, &port); - if( (sock = xsocket(AF_INET, SOCK_STREAM, 0)) < 0 ){ - if( XPAVerbosity() > 1 ) - perror("xpans socket()"); - exit(1); - } - setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, - (char *)&keep_alive, sizeof(keep_alive)); - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (char *)&reuse_addr, sizeof(reuse_addr)); - memset((char *)&sock_in, 0, sizeof(sock_in)); - sock_in.sin_family = AF_INET; - /* localhost only */ - if( ip == localhost_ip ) - sock_in.sin_addr.s_addr = htonl(ip); - /* any address will do */ - else - sock_in.sin_addr.s_addr = htonl(INADDR_ANY); - sock_in.sin_port = htons(port); - /* bind to a port -- an error indicates that another xpans is running */ - if( xbind(sock, (struct sockaddr *)&sock_in, sizeof(sock_in)) < 0 ){ - if( XPAVerbosity() > 1 ) - perror("xpans bind()"); - exit(1); - } - SecureLog("Opening INET socket: %d", sock); - break; -#if HAVE_SYS_UN_H - case XPA_UNIX: - /* with unix sockets, we lock a special file to signal any new xpans - process that it is not needed. This behavior mimicks the bind() - error with inet sockets */ - snprintf(lockfile, SZ_LINE, "%s-lock", method); - if( (lockfd=open(lockfile, O_CREAT|O_RDWR, 0666)) >=0 ){ - lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */ - lock.l_start = 0; /* byte offset, relative to l_whence */ - lock.l_whence = SEEK_SET; /* SEEK_SET, SEE_CUR, SEEK_END */ - lock.l_len = 1; /* #bytes (0 means to EOF) */ - /* if we can't get the lock, there is an xpans already running */ - if( xfcntl(lockfd, F_SETLK, &lock) < 0 ){ - close(lockfd); - if( XPAVerbosity() > 1 ) - fprintf(stderr, "XPA$ERROR: xpans already running\n"); - exit(1); - } - } - unlink(method); - if( (sock = xsocket(AF_UNIX, SOCK_STREAM, 0)) < 0 ){ - if( XPAVerbosity() > 1 ) - perror("xpans socket()"); - exit(1); - } - setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, - (char *)&keep_alive, sizeof(keep_alive)); - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (char *)&reuse_addr, sizeof(reuse_addr)); - memset((char *)&sock_un, 0, sizeof(sock_un)); - sock_un.sun_family = AF_UNIX; - strcpy(sock_un.sun_path, method); - /* unset umask so that everyone can read and write */ - oum = umask(0); - /* bind to a port */ - if( xbind(sock, (struct sockaddr *)&sock_un, sizeof(sock_un)) < 0 ){ - if( XPAVerbosity() > 1 ) - perror("xpans bind()"); - exit(1); - } - /* reset umask */ - umask(oum); - SecureLog("opened UNIX socket: %d", sock); - break; -#endif - default: - break; - } - - /* listen for connections */ - if( listen(sock, XPA_MAXLISTEN) < 0 ){ - if( XPAVerbosity() > 1 ) - perror("xpans listen()"); - exit(1); - } - /* make sure we close on exec */ - xfcntl(sock, F_SETFD, FD_CLOEXEC); - - /* add an XPA access point for external processing */ - if( !(xpa=XPANew(XPANS_CLASS, XPANS_NAME, helpbuf, - send_cb, NULL, "fillbuf=false", - receive_cb, NULL, "fillbuf=false")) ){ - if( XPAVerbosity() > 1 ) - fprintf(stderr, "XPA$ERROR: failed to create access point for xpans\n"); - exit(1); - } - SecureLog("XPA access point: %s", xpa->name); - - /* init select parameters */ - width = FD_SETSIZE; - -#if HAVE_LIBPTHREAD - /* start up new thread for XPA main loop, if necessary */ - if( doproxy >= 2 ){ - if( pthread_create(&tid, NULL, doxpaloop, NULL) != 0 ){ - fprintf(stderr, - "XPA$ERROR: can't create new thread for XPA handler in xpans\n"); - exit(1); - } - } -#endif - - /* enter processing loop */ - while( 1 ){ - /* reset flag */ - FD_ZERO(&readfds); - /* add main listening socket */ - FD_SET(sock, &readfds); - /* add request lines */ - for(got=0, req=reqhead; req!=NULL; req=req->next){ - FD_SET(req->sock, &readfds); - got++; - } - /* add XPA selections */ - if( doproxy < 2 ) XPAAddSelect(NULL, &readfds); - /* if we once had entries but do not have them now, we might be done */ - if( exconn && nentry && !got ){ - goto done; - } - if( keepalive ){ - tv.tv_sec = ksec; - tv.tv_usec = 0; - tvp = &tv; - } - else{ - tvp = NULL; - } - /* wait for next request */ - sval = xselect(width, &readfds, NULL, NULL, tvp); - if( sval > 0 ){ -#if HAVE_LIBPTHREAD - /* lock the mutex before processing a reqest */ - if( doproxy >= 2 ) pthread_mutex_lock(&xpans_mutex); -#endif - /* process a new major request */ - if( FD_ISSET(sock, &readfds) ){ - /* new request */ - switch(mtype){ - case XPA_INET: - while( 1 ){ - slen = sizeof(struct sockaddr_in); - if((sock2=xaccept(sock, (struct sockaddr *)&sock_in2, &slen))>=0){ - cmdip = ntohl(sock_in2.sin_addr.s_addr); - cmdport = ntohs(sock_in2.sin_port); - /* make sure we close on exec */ - xfcntl(sock2, F_SETFD, FD_CLOEXEC); - NewReq(sock2, cmdip, cmdport); - SecureLog("accept %d: %x:%d (%s)", - sock2, cmdip, cmdport, getiphost(cmdip)); - break; - } - else{ - if( errno == EINTR ) - continue; - else - break; - } - } - break; -#if HAVE_SYS_UN_H - case XPA_UNIX: - while( 1 ){ - slen = sizeof(struct sockaddr_un); - if( (sock2=xaccept(sock, (struct sockaddr *)&sock_un2, &slen))>=0){ - /* make sure we close on exec */ - xfcntl(sock2, F_SETFD, FD_CLOEXEC); - NewReq(sock2, 0, 0); - SecureLog("accept from local socket"); - break; - } - else{ - if( errno == EINTR ) - continue; - else - break; - } - } - break; -#endif - default: - break; - } - } - /* process an existing request line */ - for(got=0, req=reqhead; req!=NULL; ){ - treq = req->next; - if( FD_ISSET(req->sock, &readfds) ){ - FPRINTF((stderr, "%sxpans existing request: %d\n", _sp, req->sock)); - if( XPAGets(NULL, req->sock, lbuf, SZ_LINE, XPAShortTimeout()) >0 ){ - llen = strlen(lbuf) - 1; - if( (lbuf[llen]) == '\n' ){ - /* ignore a single new-line, its a keep-alive message */ - if( llen == 0){ - FPRINTF((stderr, "%sxpans ignoring keep-alive\n", _sp)); - req = treq; - continue; - } - /* else remove new-line */ - else{ - lbuf[llen] = '\0'; - } - } - FPRINTF((stderr, "%sxpans request: %s\n", _sp, lbuf)); - SecureLog("cmd %d: %s", req->sock, lbuf); - /* process another request from this process */ - wp = 0; - /* get first token: command */ - if( !word(lbuf, cmd, &wp) ){ - strcpy(tbuf, "XPA$ERROR no xpans command specified\n"); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - } - else{ - /* skip white space */ - while( isspace((int)lbuf[wp]) ) - wp++; - /* lookup the command */ - if( !strcmp(cmd, "status") ){ - StatusReq(req); - } - else if( !strcmp(cmd, "version") ){ - VersionReq(req, &(lbuf[wp])); - } - else if( !strcmp(cmd, "add") ){ - AddReq(req, &(lbuf[wp]), 1); - } - else if( !strcmp(cmd, "addproxy") ){ - AddProxyReq(req, &(lbuf[wp]), 1); - } - else if( !strcmp(cmd, "del") ){ - DelReq(req, &(lbuf[wp]), 1); - } - else if( !strcmp(cmd, "delproxy") ){ - DelProxyReq(req, &(lbuf[wp]), 1); - } - else if( !strcmp(cmd, "help") ){ - HelpReq(req, 1); - } - else if( !strcmp(cmd, "list") ){ - ListReq(req, 1); - } - else if( !strcmp(cmd, "lookup") ){ - LookupReq(req, &(lbuf[wp]), 1); - } - else{ - SecureLog("ignoring unknown command"); - snprintf(tbuf, SZ_LINE, - "XPA$ERROR unknown xpans request: %s\n", lbuf); - XPAPuts(NULL, req->sock, tbuf, XPALongTimeout()); - } - } - } - else{ - /* process dies: delete all entries associated with this sock */ - FPRINTF((stderr, "%sxpans request died: %d\n", _sp, req->sock)); - DelReq(req, NULL, 1); - } - } - req = treq; - } - - /* process xpa requests */ - if( doproxy < 2 ) XPAProcessSelect(&readfds, 0); -#if HAVE_LIBPTHREAD - /* unlock the mutex */ - if( doproxy >= 2 ) pthread_mutex_unlock(&xpans_mutex); -#endif - } - /* keep alive timer went off */ - else if( sval == 0 ){ - ; - } - /* error on select() */ - else{ - /* restart system call if interrupted */ - if( errno != EINTR ){ - /* all others are problematic */ - if( XPAVerbosity() > 1 ) - perror("xpans select()"); - if( ++nerr >= MAX_ERRORS ){ - if( XPAVerbosity() > 1 ) - fprintf(stderr, - "XPA$ERROR: too many select() errors in xpans\n"); - goto done; - } - } - } - /* see if its time to send keepalive probe */ - if( keepalive ) - KeepAliveReq(); - } - -done: - if( sock >=0 ) close(sock); - if( securefp && (securefp != stdout) ) fclose(securefp); -#if HAVE_SYS_UN_H - if( mtype == XPA_UNIX ){ - unlink(method); - if( lockfd >= 0 ){ - close(lockfd); - unlink(lockfile); - } - } -#endif - XPAFree(xpa); - return(0); -} |