/*=========================================================================*/ void SLPDLogTraceMsg(const char* prefix, struct sockaddr_in* peeraddr, SLPBuffer buf) /*=========================================================================*/ { SLPMessage msg; if(G_SlpdProperty.traceMsg) { msg = SLPMessageAlloc(); if(msg) { if(SLPMessageParseBuffer(buf,msg) == 0) { SLPLog("----------------------------------------\n"); SLPLog("traceMsg %s:\n",prefix); SLPLog("----------------------------------------\n"); SLPDLogPeerAddr(peeraddr); SLPDLogMessage(msg); SLPLog("\n"); } } SLPMessageFree(msg); } }
/*=========================================================================*/ int SLPDPredicateTest(int predicatever, const char* predicate, SLPAttributes attr) /* */ /* Determine whether the specified attribute list satisfies */ /* the specified predicate */ /* */ /* predicatever (IN) SLP version of the predicate string */ /* */ /* predicate (IN) the predicate string */ /* */ /* attr (IN) attribute list to test */ /* */ /* Returns: Zero if there is a match, a positive value if there was not a */ /* match, and a negative value if there was a parse error in the */ /* predicate string. */ /*=========================================================================*/ { const char *end; /* Pointer to the end of the parsed attribute string. */ FilterResult err; /***** An NULL or empty string is always true. *****/ if(predicate == 0 || *(char *)predicate == 0) { return 0; } /* We don't handle SLPv1 predicates yet */ if(predicatever == 1) { return 0; } err = filter(predicate, &end, attr, SLPD_ATTR_RECURSION_DEPTH); assert(err != FR_UNSET); /***** Check for trailing trash data. *****/ if((err == FR_EVAL_TRUE || err == FR_EVAL_FALSE)&& *end != 0) { return -1; } switch(err) { case(FR_EVAL_TRUE): return 0; case(FR_EVAL_FALSE): return 1; case(FR_INTERNAL_SYSTEM_ERROR): SLPLog("The predicate string \"%s\" caused an internal error\n", (char *)predicate); case(FR_PARSE_ERROR): case(FR_MEMORY_ALLOC_FAILED): return -1; default: SLPLog("SLPAttrEvalPred() returned an out of range value (%d) when evaluating \"%s\"\n", err, (char *)predicate); } return -1; }
/*-------------------------------------------------------------------------*/ void SLPDLogSrvRqstMessage(SLPSrvRqst* srvrqst) /*-------------------------------------------------------------------------*/ { SLPLog("Message SRVRQST:\n"); SLPLog(" srvtype = \"%*s\"\n", srvrqst->srvtypelen, srvrqst->srvtype); SLPLog(" scopelist = \"%*s\"\n", srvrqst->scopelistlen, srvrqst->scopelist); SLPLog(" predicate = \"%*s\"\n", srvrqst->predicatelen, srvrqst->predicate); }
/*-------------------------------------------------------------------------*/ void SLPDLogSrvRegMessage(SLPSrvReg* srvreg) /*-------------------------------------------------------------------------*/ { SLPLog("Message SRVREG:\n"); SLPLog(" type = \"%*s\"\n", srvreg->srvtypelen, srvreg->srvtype); SLPLog(" scope = \"%*s\"\n", srvreg->scopelistlen, srvreg->scopelist); SLPLog(" attributes = \"%*s\"\n", srvreg->attrlistlen, srvreg->attrlist); }
/*=========================================================================*/ void SLPDLogDATrafficMsg(const char* prefix, struct sockaddr_in* peeraddr, SLPMessage daadvert) /*=========================================================================*/ { if(G_SlpdProperty.traceDATraffic) { SLPLog("----------------------------------------\n"); SLPLog("traceDATraffic %s:\n",prefix); SLPLog("----------------------------------------\n"); SLPDLogPeerAddr(peeraddr); SLPDLogMessage(daadvert); SLPLog("\n\n"); } }
/*------------------------------------------------------------------------*/ void HandleSigHup() /*------------------------------------------------------------------------*/ { /* Reinitialize */ SLPLog("****************************************\n"); SLPLogTime(); SLPLog("SLPD daemon reset by SIGHUP\n"); SLPLog("****************************************\n\n"); /* unregister with all DAs */ SLPDKnownDADeinit(); /* re-read properties */ SLPDPropertyInit(G_SlpdCommandLine.cfgfile); /* Re-read the static registration file (slp.reg)*/ SLPDDatabaseReInit(G_SlpdCommandLine.regfile); /* Rebuild Known DA database */ SLPDKnownDAInit(); SLPLog("****************************************\n"); SLPLogTime(); SLPLog("SLPD daemon reset finished\n"); SLPLog("****************************************\n\n"); }
/*=========================================================================*/ int SLPDDatabaseInit(const char* regfile) /* Optionaly initialize the database with registrations from a regfile. */ /* */ /* regfile (IN) the regfile to register. */ /* */ /* Returns - zero on success or non-zero on error. */ /*=========================================================================*/ { FILE* fd; #ifdef WIN32 int mypid = GetCurrentProcessId(); int myuid = 0; /* TODO: find an equivalent to uid on Win32 */ #else int mypid = getpid(); int myuid = getuid(); #endif SLPDDatabaseEntry* entry; /* Remove all entries in the database if any */ FreeAllEntries(&G_DatabaseList); /*--------------------------------------*/ /* Read static registration file if any */ /*--------------------------------------*/ if(regfile) { fd = fopen(regfile,"rb"); if(fd) { SLPLog("Reading registration file %s\n",regfile); while(SLPDRegFileReadEntry(fd,&entry) != 0) { entry->pid = mypid; entry->uid = myuid; if(G_SlpdProperty.traceReg) { SLPDLogTraceReg("SrvReg (static)",entry); } SLPListLinkHead(&G_DatabaseList,(SLPListItem*)entry); } fclose(fd); } } return 0; }
/*------------------------------------------------------------------------*/ void HandleSigTerm() /*------------------------------------------------------------------------*/ { struct timeval timeout; fd_set readfds; fd_set writefds; int highfd; int fdcount = 0; SLPLog("****************************************\n"); SLPLogTime(); SLPLog("SLPD daemon shutting down\n"); SLPLog("****************************************\n"); /* close all incoming sockets */ SLPDIncomingDeinit(); /* unregister with all DAs */ SLPDKnownDADeinit(); timeout.tv_sec = 5; timeout.tv_usec = 0; /* Do a dead DA passive advert to tell everyone we're goin' down */ SLPDKnownDAPassiveDAAdvert(0, 1); /* if possible wait until all outgoing socket are done and closed */ while(SLPDOutgoingDeinit(1)) { FD_ZERO(&writefds); FD_ZERO(&readfds); LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds,&writefds); fdcount = select(highfd+1,&readfds,&writefds,0,&timeout); if(fdcount == 0) { break; } SLPDOutgoingHandler(&fdcount,&readfds,&writefds); } SLPDOutgoingDeinit(0); SLPLog("****************************************\n"); SLPLogTime(); SLPLog("SLPD daemon shut down\n"); SLPLog("****************************************\n"); #ifdef DEBUG SLPDDatabaseDeinit(); SLPDPropertyDeinit(); printf("Number of calls to SLPBufferAlloc() = %i\n",G_Debug_SLPBufferAllocCount); printf("Number of calls to SLPBufferFree() = %i\n",G_Debug_SLPBufferFreeCount); #endif }
/*=========================================================================*/ void SLPDLogKnownDA(const char* prefix, SLPDAEntry* daentry) /*=========================================================================*/ { SLPLog("----------------------------------------\n"); SLPLog("Known DA %s:\n",prefix); SLPLog("----------------------------------------\n"); SLPLog(" url = "); SLPLogBuffer(daentry->url, daentry->urllen); SLPLog("\n scope = "); SLPLogBuffer(daentry->scopelist, daentry->scopelistlen); SLPLog("\n\n"); }
/*-------------------------------------------------------------------------*/ void HandleDatagramRead(SLPDSocketList* list, SLPDSocket* sock) /*-------------------------------------------------------------------------*/ { int bytesread; int bytestowrite; bytesread = recvfrom(sock->fd, sock->recvbuf->start, SLP_MAX_DATAGRAM_SIZE, 0, &(sock->peerinfo.peeraddr), &(sock->peerinfo.peeraddrlen)); if(bytesread > 0) { sock->recvbuf->end = sock->recvbuf->start + bytesread; if(SLPDProcessMessage(&(sock->peerinfo), sock->recvbuf, sock->sendbuf) == 0) { /* check to see if we should send anything */ bytestowrite = sock->sendbuf->end - sock->sendbuf->start; if(bytestowrite > 0) { sendto(sock->fd, sock->sendbuf->start, sock->sendbuf->end - sock->sendbuf->start, 0, &(sock->peerinfo.peeraddr), sock->peerinfo.peeraddrlen); } } else { SLPLog("An error occured while processing message from %s\n", inet_ntoa(sock->peerinfo.peeraddr.sin_addr)); } } }
/*=========================================================================*/ int main(int argc, char* argv[]) /*=========================================================================*/ { fd_set readfds; fd_set writefds; int highfd; int fdcount = 0; /*------------------------------*/ /* Make sure we are root */ /*------------------------------*/ if(getuid() != 0) { SLPFatal("slpd must be started by root\n"); } /*------------------------*/ /* Parse the command line */ /*------------------------*/ if(SLPDParseCommandLine(argc,argv)) { SLPFatal("Invalid command line\n"); } /*------------------------------*/ /* Initialize the log file */ /*------------------------------*/ SLPLogFileOpen(G_SlpdCommandLine.logfile, 0); SLPLog("****************************************\n"); SLPLog("*** SLPD daemon started ***\n"); SLPLog("****************************************\n"); SLPLog("command line = %s\n",argv[0]); /*--------------------------------------------------*/ /* Initialize for the first time */ /*--------------------------------------------------*/ SLPDPropertyInit(G_SlpdCommandLine.cfgfile); SLPDDatabaseInit(G_SlpdCommandLine.regfile); SLPDIncomingInit(); SLPDOutgoingInit(); SLPDKnownDAInit(); /* TODO: Check error codes on all init functions */ /*---------------------------*/ /* make slpd run as a daemon */ /*---------------------------*/ if(Daemonize(G_SlpdCommandLine.pidfile)) { SLPFatal("Could not run as daemon\n"); } /*-----------------------*/ /* Setup signal handlers */ /*-----------------------*/ if(SetUpSignalHandlers()) { SLPFatal("Could not set up signal handlers.\n"); } /*------------------------------*/ /* Set up alarm to age database */ /*------------------------------*/ alarm(SLPD_AGE_INTERVAL); /*-----------*/ /* Main loop */ /*-----------*/ G_SIGALRM = 0; G_SIGTERM = 0; G_SIGHUP = 0; SLPLog("Initialization complete\n\n"); while(G_SIGTERM == 0) { /*--------------------------------------------------------*/ /* Load the fdsets up with all valid sockets in the list */ /*--------------------------------------------------------*/ highfd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); LoadFdSets(&G_IncomingSocketList, &highfd, &readfds,&writefds); LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds,&writefds); /*--------------------------------------------------*/ /* Before select(), check to see if we got a signal */ /*--------------------------------------------------*/ if(G_SIGALRM || G_SIGHUP) { goto HANDLE_SIGNAL; } /*-------------*/ /* Main select */ /*-------------*/ fdcount = select(highfd+1,&readfds,&writefds,0,0); if(fdcount > 0) /* fdcount will be < 0 when interrupted by a signal */ { SLPDIncomingHandler(&fdcount,&readfds,&writefds); SLPDOutgoingHandler(&fdcount,&readfds,&writefds); } /*----------------*/ /* Handle signals */ /*----------------*/ HANDLE_SIGNAL: if(G_SIGHUP) { /* Reinitialize */ SLPLog("****************************************\n"); SLPLog("*** SLPD daemon restarted ***\n"); SLPLog("****************************************\n"); SLPLog("Got SIGHUP reinitializing... \n"); SLPDPropertyInit(G_SlpdCommandLine.cfgfile); SLPDDatabaseInit(G_SlpdCommandLine.regfile); /* Don't reinitialize Incoming because we can't rebind to */ /* slp reserved port because we are not root now */ /* SLPDIncomingInit(); */ SLPDOutgoingInit(); SLPDKnownDAInit(); G_SIGHUP = 0; } if(G_SIGALRM) { /* TODO: add call to do passive DAAdvert */ SLPDIncomingAge(SLPD_AGE_INTERVAL); SLPDOutgoingAge(SLPD_AGE_INTERVAL); SLPDDatabaseAge(SLPD_AGE_INTERVAL); SLPDKnownDAActiveDiscovery(); G_SIGALRM = 0; alarm(SLPD_AGE_INTERVAL); } } /* End of main loop */ SLPLog("Got SIGTERM. Going down\n"); #if(defined DEBUG) SLPDIncomingDeinit(); SLPDOutgoingDeinit(); printf("Number of calls to SLPBufferAlloc() = %i\n",G_Debug_SLPBufferAllocCount); printf("Number of calls to SLPBufferFree() = %i\n",G_Debug_SLPBufferFreeCount); #endif return 0; }
/*=========================================================================*/ SLPDDatabaseEntry* SLPDRegFileReadEntry(FILE* fd, SLPDDatabaseEntry** entry) /* A really big and nasty function that reads an entry SLPDDatabase entry */ /* from a file. Don't look at this too hard or you'll be sick */ /* */ /* fd (IN) file to read from */ /* */ /* entry (OUT) Address of a pointer that will be set to the location of */ /* a dynamically allocated SLPDDatabase entry. The entry */ /* must be freed */ /* */ /* Returns *entry or null on error. */ /*=========================================================================*/ { char* slider1; char* slider2; char line[4096]; /* give the out param a value */ *entry = 0; /*----------------------------------------------------------*/ /* read the next non-white non-comment line from the stream */ /*----------------------------------------------------------*/ do { slider1 = RegFileReadLine(fd,line,4096); if(slider1 == 0) { /* read through the whole file and found no entries */ return 0; } }while(*slider1 == 0x0d || *slider1 == 0x0a); /*---------------------------*/ /* Allocate a database entry */ /*---------------------------*/ *entry = (SLPDDatabaseEntry*)malloc(sizeof(SLPDDatabaseEntry)); if(entry == 0) { SLPFatal("Out of memory!\n"); return 0; } memset(*entry,0,sizeof(SLPDDatabaseEntry)); /*---------------------*/ /* Parse the url-props */ /*---------------------*/ slider2 = strchr(slider1,','); if(slider2) { /* srvurl */ *slider2 = 0; /* squash comma to null terminate srvurl */ (*entry)->url = strdup(TrimWhitespace(slider1)); if((*entry)->url == 0) { SLPLog("Out of memory reading srvurl from regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->urllen = strlen((*entry)->url); /* derive srvtype from srvurl if srvurl is "service:" scheme URL */ if(strncasecmp(slider1,"service:",8)==0) { (*entry)->srvtype = strstr(slider1,"://"); if((*entry)->srvtype == 0) { SLPLog("Looks like a bad url on regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } *(*entry)->srvtype = 0; (*entry)->srvtype=strdup(TrimWhitespace(slider1)); (*entry)->srvtypelen = strlen((*entry)->srvtype); } slider1 = slider2 + 1; /*lang*/ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate lang */ (*entry)->langtag = strdup(TrimWhitespace(slider1)); if((*entry)->langtag == 0) { SLPLog("Out of memory reading langtag from regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->langtaglen = strlen((*entry)->langtag); slider1 = slider2 + 1; } else { SLPLog("Expected language tag near regfile line ->%s\n",line); goto SLPDREGFILEREADENTRY_ERROR1; } /* ltime */ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate ltime */ (*entry)->lifetime = atoi(slider1); slider1 = slider2 + 1; } else { (*entry)->lifetime = atoi(slider1); slider1 = slider2; } if((*entry)->lifetime < 1 || (*entry)->lifetime > 0xffff) { SLPLog("Invalid lifetime near regfile line ->%s\n",line); goto SLPDREGFILEREADENTRY_ERROR1; } /* get the srvtype if one was not derived by the srvurl*/ if((*entry)->srvtype == 0) { (*entry)->srvtype = strdup(TrimWhitespace(slider1)); if((*entry)->srvtype == 0) { SLPLog("Out of memory reading srvtype from regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->srvtypelen = strlen((*entry)->srvtype); if((*entry)->srvtypelen == 0) { SLPLog("Expected to derive service-type near regfile line -> %s\n",line); goto SLPDREGFILEREADENTRY_ERROR1; } } } else { SLPLog("Expected to find srv-url near regfile line -> %s\n",line); goto SLPDREGFILEREADENTRY_ERROR1; } /*-------------------------------------------------*/ /* Read all the attributes including the scopelist */ /*-------------------------------------------------*/ *line=0; while(1) { if(RegFileReadLine(fd,line,4096) == 0) { break; } if(*line == 0x0d || *line == 0x0a) { break; } /* Check to see if it is the scopes line */ if(strncasecmp(line,"scopes",6) == 0) { /* found scopes line */ slider1 = line; slider2 = strchr(slider1,'='); if(slider2) { slider2++; if(*slider2) { /* just in case some idiot puts multiple scopes lines */ if((*entry)->scopelist) { SLPLog("scopes already defined previous to regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->scopelist=strdup(TrimWhitespace(slider2)); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding scopes from regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->scopelistlen = strlen((*entry)->scopelist); } } } else { /* line contains an attribute (slow but it works)*/ /* TODO Fix this so we do not have to realloc memory each time! */ TrimWhitespace(line); (*entry)->attrlistlen += strlen(line) + 2; if((*entry)->attrlist == 0) { (*entry)->attrlist = malloc((*entry)->attrlistlen + 1); *(*entry)->attrlist = 0; } else { (*entry)->attrlist = realloc((*entry)->attrlist, (*entry)->attrlistlen + 1); } if((*entry)->attrlist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPDREGFILEREADENTRY_ERROR1; } strcat((*entry)->attrlist,"("); strcat((*entry)->attrlist,line); strcat((*entry)->attrlist,")"); } } /* Set the scope to default if not is set */ if((*entry)->scopelist == 0) { (*entry)->scopelist=strdup("DEFAULT"); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->scopelistlen = 7; } return *entry; SLPDREGFILEREADENTRY_ERROR1: if(*entry) { if((*entry)->srvtype) free((*entry)->srvtype); if((*entry)->url) free((*entry)->url); if((*entry)->langtag) free((*entry)->langtag); if((*entry)->scopelist) free((*entry)->scopelist); if((*entry)->attrlist) free((*entry)->attrlist); free(*entry); *entry = 0; } return 0; }
/*=========================================================================*/ void SLPDSocketInit(SLPDSocketList* list) /* Adds SLPSockets (UDP and TCP) for all the interfaces and the loopback */ /* */ /* list - pointer to SLPSocketList to initialize */ /* */ /* Returns - zero on success, -1 on failure. */ /*=========================================================================*/ { char* begin; char* end; int finished; struct in_addr myaddr; struct in_addr mcastaddr; struct in_addr bcastaddr; SLPDSocket* sock; /*----------------------------------------------------*/ /* Decide what address to use for multicast/broadcast */ /*----------------------------------------------------*/ mcastaddr.s_addr = htonl(SLP_MCAST_ADDRESS); bcastaddr.s_addr = htonl(0xffffffff); /*-----------------------------------------------------------------*/ /* Create SOCKET_LISTEN socket for LOOPBACK for the library to talk to*/ /*-----------------------------------------------------------------*/ sock = (SLPDSocket*)malloc(sizeof(SLPDSocket)); if(sock == 0) { return; } memset(sock,0,sizeof(SLPDSocket)); sock->fd = socket(PF_INET, SOCK_STREAM, 0); if(sock->fd >= 0) { if(BindSocketToLoopback(sock->fd) >= 0) { if(listen(sock->fd,5) == 0) { sock->state = SOCKET_LISTEN; if(SLPDSocketListAdd(list,sock) == 0) { SLPFatal("Out of memory"); } SLPLog("SLPLIB API socket listening\n"); } else { /* could not listen(), close the socket*/ close(sock->fd); free(sock); SLPLog("ERROR: Could not listen on loopback\n"); SLPLog("ERROR: No SLPLIB support will be available\n"); } } else { /* could not bind, close the socket*/ close(sock->fd); free(sock); SLPLog("ERROR: Could not bind loopback port 427.\n"); SLPLog("ERROR: slpd may already be running\n"); } } else { /* could not create the socket */ free(sock); SLPLog("ERROR: Could not create socket for loopback.\n"); SLPLog("ERROR: No SLPLIB support will be available\n"); } /*---------------------------------------------------------------------*/ /* Create sockets for all of the interfaces in the interfaces property */ /*---------------------------------------------------------------------*/ begin = (char*)G_SlpdProperty.interfaces; end = begin; finished = 0; while( finished == 0) { while(*end && *end != ',') end ++; if(*end == 0) finished = 1; while(*end <=0x2f) { *end = 0; end--; } /* begin now points to a null terminated ip address string */ myaddr.s_addr = inet_addr(begin); /*--------------------------------------------------------*/ /* Create socket that will handle multicast UDP */ /*--------------------------------------------------------*/ sock = (SLPDSocket*)malloc(sizeof(SLPDSocket)); if(sock == 0) { break; } sock->fd = socket(PF_INET, SOCK_DGRAM, 0); if(sock->fd >=0) { if(BindSocketToInetAddr(sock->fd, &mcastaddr) >= 0) { if(JoinSLPMulticastGroup(sock->fd, &myaddr) == 0) { sock->state = DATAGRAM_MULTICAST; sock->recvbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->peerinfo.peeraddrlen = sizeof(sock->peerinfo.peeraddr); sock->peerinfo.peertype = SLPD_PEER_REMOTE; if(sock->recvbuf == 0 || sock->sendbuf == 0) { SLPFatal("SLPD out of memory !!\n"); } SLPDSocketListAdd(list,sock); SLPLog("Multicast socket on %s ready\n",inet_ntoa(myaddr)); } else { /* could not add multicast membership */ close(sock->fd); free(sock); } } else { /* could not bind(), close the socket*/ close(sock->fd); free(sock); } } /*--------------------------------------------*/ /* Create socket that will handle unicast UDP */ /*--------------------------------------------*/ sock = (SLPDSocket*)malloc(sizeof(SLPDSocket)); if(sock == 0) { break; } sock->fd = socket(PF_INET, SOCK_DGRAM, 0); if(sock->fd >= 0) { if(BindSocketToInetAddr(sock->fd, &myaddr) >= 0) { sock->state = DATAGRAM_UNICAST; sock->recvbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->peerinfo.peertype = SLPD_PEER_REMOTE; if(sock->recvbuf == 0 || sock->sendbuf == 0) { SLPFatal("SLPD out of memory !!\n"); } SLPDSocketListAdd(list,sock); SLPLog("UDP socket on %s ready\n",inet_ntoa(myaddr)); } else { /* could not bind(), close the socket*/ close(sock->fd); free(sock); } } /*------------------------------------------------*/ /* Create TCP_LISTEN that will handle unicast TCP */ /*------------------------------------------------*/ sock = (SLPDSocket*)malloc(sizeof(SLPDSocket)); if(sock == 0) { break; } sock->fd = socket(PF_INET, SOCK_STREAM, 0); if(sock->fd >= 0) { if(BindSocketToInetAddr(sock->fd, &myaddr) >= 0) { if(listen(sock->fd,2) == 0) { sock->state = SOCKET_LISTEN; if(SLPDSocketListAdd(list,sock) == 0) { SLPFatal("Out of memory"); } SLPLog("TCP socket on %s listening\n",inet_ntoa(myaddr)); } else { /* could not listen(), close the socket*/ close(sock->fd); free(sock); } } else { /* could not bind, close the socket*/ close(sock->fd); free(sock); } } begin = end + 1; } /*--------------------------------------------------------*/ /* Create socket that will handle broadcast UDP */ /*--------------------------------------------------------*/ sock = (SLPDSocket*)malloc(sizeof(SLPDSocket)); if(sock == 0) { return; } sock->fd = socket(PF_INET, SOCK_DGRAM, 0); if(sock->fd >=0) { if(BindSocketToInetAddr(sock->fd, &bcastaddr) >= 0) { if(EnableBroadcast(sock->fd) == 0) { sock->state = DATAGRAM_BROADCAST; sock->recvbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->peerinfo.peeraddrlen = sizeof(sock->peerinfo.peeraddr); sock->peerinfo.peertype = SLPD_PEER_REMOTE; if(sock->recvbuf == 0 || sock->sendbuf == 0) { SLPFatal("SLPD out of memory !!\n"); } SLPDSocketListAdd(list,sock); SLPLog("Broadcast socket for %s ready\n", inet_ntoa(bcastaddr)); } else { /* could not add multicast membership */ close(sock->fd); free(sock); } } else { /* could not bind(), close the socket*/ close(sock->fd); free(sock); } } }
/*-------------------------------------------------------------------------*/ void SLPDLogAttrRplyMessage(SLPAttrRply* attrrply) /*-------------------------------------------------------------------------*/ { SLPLog("Message ATTRRPLY:\n"); SLPLog(" errorcode = %i\n",attrrply->errorcode); }
/*-------------------------------------------------------------------------*/ void SLPDLogDAAdvertMessage(SLPDAAdvert* daadvert) /*-------------------------------------------------------------------------*/ { SLPLog("Message DAADVERT:\n"); }
/*-------------------------------------------------------------------------*/ void HandleStreamRead(SLPDSocketList* list, SLPDSocket* sock) /*-------------------------------------------------------------------------*/ { int fdflags; int bytesread; char peek[16]; if(sock->state == STREAM_FIRST_READ) { fdflags = fcntl(sock->fd, F_GETFL, 0); fcntl(sock->fd,F_SETFL, fdflags | O_NONBLOCK); /*---------------------------------------------------------------*/ /* take a peek at the packet to get version and size information */ /*---------------------------------------------------------------*/ bytesread = recvfrom(sock->fd, peek, 16, MSG_PEEK, &(sock->peerinfo.peeraddr), &(sock->peerinfo.peeraddrlen)); if(bytesread > 0) { /* check the version */ if(*peek == 2) { /* allocate the recvbuf big enough for the whole message */ sock->recvbuf = SLPBufferRealloc(sock->recvbuf,AsUINT24(peek+2)); if(sock->recvbuf) { sock->state = STREAM_READ; } else { SLPLog("Slpd is out of memory!\n"); sock->state = SOCKET_CLOSE; } } else { SLPLog("Unsupported version %i received from %s\n", *peek, inet_ntoa(sock->peerinfo.peeraddr.sin_addr)); sock->state = SOCKET_CLOSE; } } else { if(errno != EWOULDBLOCK) { sock->state = SOCKET_CLOSE; return; } } /*------------------------------*/ /* recv the rest of the message */ /*------------------------------*/ bytesread = recv(sock->fd, sock->recvbuf->curpos, sock->recvbuf->end - sock->recvbuf->curpos, 0); if(bytesread > 0) { /*------------------------------*/ /* Reset the timestamp */ /*------------------------------*/ time(&(sock->timestamp)); sock->recvbuf->curpos += bytesread; if(sock->recvbuf->curpos == sock->recvbuf->end) { if(SLPDProcessMessage(&sock->peerinfo, sock->recvbuf, sock->sendbuf) == 0) { sock->state = STREAM_FIRST_WRITE; } else { /* An error has occured in SLPDProcessMessage() */ SLPLog("An error while processing message from %s\n", inet_ntoa(sock->peerinfo.peeraddr.sin_addr)); sock->state = SOCKET_CLOSE; } } } else { if(errno != EWOULDBLOCK) { /* error in recv() */ sock->state = SOCKET_CLOSE; } } } }
/*-------------------------------------------------------------------------*/ void SLPDLogAttrRqstMessage(SLPAttrRqst* attrrqst) /*-------------------------------------------------------------------------*/ { SLPLog("Message ATTRRQST:\n"); }
/*-------------------------------------------------------------------------*/ void SLPDLogSrvTypeRqstMessage(SLPSrvTypeRqst* srvtyperqst) /*-------------------------------------------------------------------------*/ { SLPLog("Message SRVTYPERQST:\n"); }
/*-------------------------------------------------------------------------*/ void SLPDLogSrvDeRegMessage(SLPSrvDeReg* srvdereg) /*-------------------------------------------------------------------------*/ { SLPLog("Message SRVDEREG:\n"); }
/*=========================================================================*/ int main(int argc, char* argv[]) /*=========================================================================*/ { fd_set readfds; fd_set writefds; int highfd; int fdcount = 0; /*------------------------*/ /* Parse the command line */ /*------------------------*/ if(SLPDParseCommandLine(argc,argv)) { SLPFatal("Invalid command line\n"); } /*------------------------------*/ /* Make sure we are root */ /*------------------------------*/ if(getuid() != 0) { SLPFatal("slpd must be started by root\n"); } /*--------------------------------------*/ /* Make sure we are not already running */ /*--------------------------------------*/ if(CheckPid(G_SlpdCommandLine.pidfile)) { SLPFatal("slpd is already running. Check %s\n", G_SlpdCommandLine.pidfile); } /*------------------------------*/ /* Initialize the log file */ /*------------------------------*/ if(SLPLogFileOpen(G_SlpdCommandLine.logfile, 1)) { SLPFatal("Could not open logfile %s\n",G_SlpdCommandLine.logfile); } /*------------------------*/ /* Seed the XID generator */ /*------------------------*/ SLPXidSeed(); /*---------------------*/ /* Log startup message */ /*---------------------*/ SLPLog("****************************************\n"); SLPLogTime(); SLPLog("SLPD daemon started\n"); SLPLog("****************************************\n"); SLPLog("Command line = %s\n",argv[0]); SLPLog("Using configuration file = %s\n",G_SlpdCommandLine.cfgfile); SLPLog("Using registration file = %s\n",G_SlpdCommandLine.regfile); /*--------------------------------------------------*/ /* Initialize for the first time */ /*--------------------------------------------------*/ if(SLPDPropertyInit(G_SlpdCommandLine.cfgfile) || SLPDDatabaseInit(G_SlpdCommandLine.regfile) || SLPDIncomingInit() || SLPDOutgoingInit() || SLPDKnownDAInit()) { SLPFatal("slpd initialization failed\n"); } SLPLog("Agent Interfaces = %s\n",G_SlpdProperty.interfaces); SLPLog("Agent URL = %s\n",G_SlpdProperty.myUrl); /*---------------------------*/ /* make slpd run as a daemon */ /*---------------------------*/ if(Daemonize(G_SlpdCommandLine.pidfile)) { SLPFatal("Could not daemonize\n"); } /*-----------------------*/ /* Setup signal handlers */ /*-----------------------*/ if(SetUpSignalHandlers()) { SLPFatal("Error setting up signal handlers.\n"); } /*------------------------------*/ /* Set up alarm to age database */ /*------------------------------*/ alarm(SLPD_AGE_INTERVAL); /*-----------*/ /* Main loop */ /*-----------*/ SLPLog("Startup complete entering main run loop ...\n\n"); G_SIGALRM = 0; G_SIGTERM = 0; G_SIGHUP = 0; while(G_SIGTERM == 0) { /*--------------------------------------------------------*/ /* Load the fdsets up with all valid sockets in the list */ /*--------------------------------------------------------*/ highfd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); LoadFdSets(&G_IncomingSocketList, &highfd, &readfds,&writefds); LoadFdSets(&G_OutgoingSocketList, &highfd, &readfds,&writefds); /*--------------------------------------------------*/ /* Before select(), check to see if we got a signal */ /*--------------------------------------------------*/ if(G_SIGALRM || G_SIGHUP) { goto HANDLE_SIGNAL; } /*-------------*/ /* Main select */ /*-------------*/ fdcount = select(highfd+1,&readfds,&writefds,0,0); if(fdcount > 0) /* fdcount will be < 0 when interrupted by a signal */ { SLPDIncomingHandler(&fdcount,&readfds,&writefds); SLPDOutgoingHandler(&fdcount,&readfds,&writefds); } /*----------------*/ /* Handle signals */ /*----------------*/ HANDLE_SIGNAL: if(G_SIGHUP) { HandleSigHup(); G_SIGHUP = 0; } if(G_SIGALRM) { HandleSigAlrm(); G_SIGALRM = 0; alarm(SLPD_AGE_INTERVAL); } } /* End of main loop */ /* Got SIGTERM */ HandleSigTerm(); return 0; }
/*-------------------------------------------------------------------------*/ void SLPDLogSrvTypeRplyMessage(SLPSrvTypeRply* srvtyperply) /*-------------------------------------------------------------------------*/ { SLPLog("Message SRVTYPERPLY:\n"); SLPLog(" errorcode = %i\n",srvtyperply->errorcode); }
/*-------------------------------------------------------------------------*/ void SLPDLogSAAdvertMessage(SLPSAAdvert* saadvert) /*-------------------------------------------------------------------------*/ { SLPLog("Message SAADVERT:\n"); }
/*-------------------------------------------------------------------------*/ void SLPDLogPeerAddr(struct sockaddr_in* peeraddr) /*-------------------------------------------------------------------------*/ { SLPLog("Peer Information:\n"); SLPLog(" IP address: %s\n",inet_ntoa(peeraddr->sin_addr)); }
/*=========================================================================*/ void SLPDLogTraceReg(const char* prefix, SLPDDatabaseEntry* entry) /* Logs at traceReg message to indicate that a service registration (or */ /* service de-registration has occured. */ /* */ /* prefix (IN) an appropriate prefix string like "reg" or "dereg" */ /* */ /* entry (IN) the database entry of the service */ /* */ /* returns: None */ /*=========================================================================*/ { if(G_SlpdProperty.traceReg) { SLPLog("----------------------------------------\n"); SLPLog("traceReg %s:\n",prefix); SLPLog("----------------------------------------\n"); SLPLog("language tag = "); SLPLogBuffer(entry->langtag, entry->langtaglen); SLPLog("\nlifetime = %i\n",entry->lifetime); SLPLog("url = "); SLPLogBuffer(entry->url, entry->urllen); SLPLog("\nscope = "); SLPLogBuffer(entry->scopelist, entry->scopelistlen); SLPLog("\nservice type = "); SLPLogBuffer(entry->srvtype, entry->srvtypelen); #ifdef USE_PREDICATES {/* Print attributes. */ char *str; SLPError err; //err = SLPAttrSerialize(entry->attr, NULL, &str, SLP_FALSE); if (err != SLP_OK) { SLPLog("\nerror %i when building attributes", err); } else { SLPLog("\nattributes = %s", str); free(str); } } #else SLPLog("\nAttributes = "); SLPLogBuffer(entry->attrlist, entry->attrlistlen); #endif SLPLog("\n\n"); } }
/*=========================================================================*/ int SLPDProcessMessage(struct sockaddr_in* peerinfo, SLPBuffer recvbuf, SLPBuffer* sendbuf) /* Processes the recvbuf and places the results in sendbuf */ /* */ /* recvfd - the socket the message was received on */ /* */ /* recvbuf - message to process */ /* */ /* sendbuf - results of the processed message */ /* */ /* Returns - zero on success SLP_ERROR_PARSE_ERROR or */ /* SLP_ERROR_INTERNAL_ERROR on ENOMEM. */ /*=========================================================================*/ { SLPMessage message = 0; int errorcode = 0; message = SLPMessageAlloc(); if(message == 0) { return SLP_ERROR_INTERNAL_ERROR; } errorcode = SLPMessageParseBuffer(recvbuf, message); #if defined(ENABLE_SLPv1) if(message->header.version == 1) return SLPDv1ProcessMessage(peerinfo, recvbuf, sendbuf, message, errorcode); #endif /* Log trace message */ SLPDLogTraceMsg("IN",peerinfo,recvbuf); switch(message->header.functionid) { case SLP_FUNCT_SRVRQST: errorcode = ProcessSrvRqst(peerinfo, message, sendbuf, errorcode); break; case SLP_FUNCT_SRVREG: errorcode = ProcessSrvReg(peerinfo, message,sendbuf, errorcode); if(errorcode == 0) { SLPDKnownDAEcho(peerinfo, message, recvbuf); } break; case SLP_FUNCT_SRVDEREG: errorcode = ProcessSrvDeReg(peerinfo, message,sendbuf, errorcode); if(errorcode == 0) { SLPDKnownDAEcho(peerinfo, message, recvbuf); } break; case SLP_FUNCT_SRVACK: errorcode = ProcessSrvAck(peerinfo, message,sendbuf, errorcode); break; case SLP_FUNCT_ATTRRQST: errorcode = ProcessAttrRqst(peerinfo, message,sendbuf, errorcode); break; case SLP_FUNCT_DAADVERT: errorcode = ProcessDAAdvert(peerinfo, message, sendbuf, errorcode); /* If necessary log that we received a DAAdvert */ SLPDLogDATrafficMsg("IN", peerinfo, message); break; case SLP_FUNCT_SRVTYPERQST: errorcode = ProcessSrvTypeRqst(peerinfo, message, sendbuf, errorcode); break; case SLP_FUNCT_SAADVERT: errorcode = ProcessSAAdvert(peerinfo, message, sendbuf, errorcode); break; default: /* This may happen on a really early parse error or version not */ /* supported error */ /* TODO log errorcode here */ break; } /* Log traceMsg of message was received and the one that will be sent */ SLPDLogTraceMsg("OUT",peerinfo,*sendbuf); SLPMessageFree(message); /* Log reception of important errors */ switch(errorcode) { case SLP_ERROR_DA_BUSY_NOW: SLPLog("DA_BUSY from %s\n", inet_ntoa(peerinfo->sin_addr)); break; case SLP_ERROR_INTERNAL_ERROR: SLPLog("INTERNAL_ERROR from %s\n", inet_ntoa(peerinfo->sin_addr)); break; case SLP_ERROR_PARSE_ERROR: SLPLog("PARSE_ERROR from %s\n", inet_ntoa(peerinfo->sin_addr)); break; case SLP_ERROR_VER_NOT_SUPPORTED: SLPLog("VER_NOT_SUPPORTED from %s\n", inet_ntoa(peerinfo->sin_addr)); break; } return errorcode; }
/*-------------------------------------------------------------------------*/ void SLPDLogSrvAckMessage(SLPSrvAck* srvack) /*-------------------------------------------------------------------------*/ { SLPLog("Message SRVACK:\n"); SLPLog(" errorcode = %i\n",srvack->errorcode); }
/*-------------------------------------------------------------------------*/ void SLPDLogSrvRplyMessage(SLPSrvRply* srvrply) /*-------------------------------------------------------------------------*/ { SLPLog("Message SRVRPLY:\n"); SLPLog(" errorcode = %i\n",srvrply->errorcode); }
/*-------------------------------------------------------------------------*/ void SLPDLogMessage(SLPMessage message) /*-------------------------------------------------------------------------*/ { SLPLog("Header:\n"); SLPLog(" version = %i\n",message->header.version); SLPLog(" functionid = %i\n",message->header.functionid); SLPLog(" length = %i\n",message->header.length); SLPLog(" flags = %i\n",message->header.flags); SLPLog(" extoffset = %i\n",message->header.extoffset); SLPLog(" xid = %i\n",message->header.xid); SLPLog(" langtaglen = %i\n",message->header.langtaglen); SLPLog(" langtag = "); SLPLogBuffer(message->header.langtag, message->header.langtaglen); SLPLog("\n"); switch(message->header.functionid) { case SLP_FUNCT_SRVRQST: SLPDLogSrvRqstMessage(&(message->body.srvrqst)); break; case SLP_FUNCT_SRVRPLY: SLPDLogSrvRplyMessage(&(message->body.srvrply)); break; case SLP_FUNCT_SRVREG: SLPDLogSrvRegMessage(&(message->body.srvreg)); break; case SLP_FUNCT_SRVDEREG: SLPDLogSrvDeRegMessage(&(message->body.srvdereg)); break; case SLP_FUNCT_SRVACK: SLPDLogSrvAckMessage(&(message->body.srvack)); break; case SLP_FUNCT_ATTRRQST: SLPDLogAttrRqstMessage(&(message->body.attrrqst)); break; case SLP_FUNCT_ATTRRPLY: SLPDLogAttrRplyMessage(&(message->body.attrrply)); break; case SLP_FUNCT_DAADVERT: SLPDLogDAAdvertMessage(&(message->body.daadvert)); break; case SLP_FUNCT_SRVTYPERQST: SLPDLogSrvTypeRqstMessage(&(message->body.srvtyperqst)); break; case SLP_FUNCT_SRVTYPERPLY: SLPDLogSrvTypeRplyMessage(&(message->body.srvtyperply)); break; case SLP_FUNCT_SAADVERT: SLPDLogSAAdvertMessage(&(message->body.saadvert)); break; default: SLPLog("Message UNKNOWN:\n"); SLPLog(" This is really bad\n"); break; } }
/*=========================================================================*/ SLPDDatabaseEntry* SLPDRegFileReadEntry(FILE* fd, SLPDDatabaseEntry** entry) /* A really big and nasty function that reads an entry SLPDDatabase entry */ /* from a file. Don't look at this too hard or you'll be sick */ /* */ /* fd (IN) file to read from */ /* */ /* entry (OUT) Address of a pointer that will be set to the location of */ /* a dynamically allocated SLPDDatabase entry. The entry */ /* must be freed */ /* */ /* Returns *entry or null on error. */ /*=========================================================================*/ { char* slider1; char* slider2; char line[4096]; /* give the out param a value */ *entry = 0; /*----------------------------------------------------------*/ /* read the next non-white non-comment line from the stream */ /*----------------------------------------------------------*/ do { slider1 = RegFileReadLine(fd,line,4096); if(slider1 == 0) { /* read through the whole file and found no entries */ return 0; } }while(*slider1 == 0x0d || *slider1 == 0x0a); /*---------------------------*/ /* Allocate a database entry */ /*---------------------------*/ *entry = SLPDDatabaseEntryAlloc(); if(entry == 0) { SLPFatal("Out of memory!\n"); return 0; } /* entries read from the .reg file are always local */ (*entry)->islocal = 1; /*---------------------*/ /* Parse the url-props */ /*---------------------*/ slider2 = strchr(slider1,','); if(slider2) { /* srvurl */ *slider2 = 0; /* squash comma to null terminate srvurl */ (*entry)->url = strdup(TrimWhitespace(slider1)); if((*entry)->url == 0) { SLPLog("Out of memory reading srvurl from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->urllen = strlen((*entry)->url); /* derive srvtype from srvurl */ (*entry)->srvtype = strstr(slider1,"://"); if((*entry)->srvtype == 0) { SLPLog("Looks like a bad url on regfile line ->%s",line); goto SLPD_ERROR; } *(*entry)->srvtype = 0; (*entry)->srvtype=strdup(TrimWhitespace(slider1)); (*entry)->srvtypelen = strlen((*entry)->srvtype); slider1 = slider2 + 1; /*lang*/ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate lang */ (*entry)->langtag = strdup(TrimWhitespace(slider1)); if((*entry)->langtag == 0) { SLPLog("Out of memory reading langtag from regfile line ->%s",line); goto SLPD_ERROR; }(*entry)->langtaglen = strlen((*entry)->langtag); slider1 = slider2 + 1; } else { SLPLog("Expected language tag near regfile line ->%s\n",line); goto SLPD_ERROR; } /* ltime */ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate ltime */ (*entry)->lifetime = atoi(slider1); slider1 = slider2 + 1; } else { (*entry)->lifetime = atoi(slider1); slider1 = slider2; } if((*entry)->lifetime < 1 || (*entry)->lifetime > 0xffff) { SLPLog("Invalid lifetime near regfile line ->%s\n",line); goto SLPD_ERROR; } /* get the srvtype if one was not derived by the srvurl*/ if((*entry)->srvtype == 0) { (*entry)->srvtype = strdup(TrimWhitespace(slider1)); if((*entry)->srvtype == 0) { SLPLog("Out of memory reading srvtype from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->srvtypelen = strlen((*entry)->srvtype); if((*entry)->srvtypelen == 0) { SLPLog("Expected to derive service-type near regfile line -> %s\n",line); goto SLPD_ERROR; } } } else { SLPLog("Expected to find srv-url near regfile line -> %s\n",line); goto SLPD_ERROR; } /*-------------------------------------------------*/ /* Read all the attributes including the scopelist */ /*-------------------------------------------------*/ *line=0; while(1) { if(RegFileReadLine(fd,line,4096) == 0) { break; } if(*line == 0x0d || *line == 0x0a) { break; } /* Check to see if it is the scopes line */ /* FIXME We can collapse the scope stuff into the value getting and * just make it a special case (do strcmp on the tag as opposed to the * line) of attribute getting. */ if(strncasecmp(line,"scopes",6) == 0) { /* found scopes line */ slider1 = line; slider2 = strchr(slider1,'='); if(slider2) { slider2++; if(*slider2) { /* just in case some idiot puts multiple scopes lines */ if((*entry)->scopelist) { SLPLog("scopes already defined previous to regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->scopelist=strdup(TrimWhitespace(slider2)); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding scopes from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->scopelistlen = strlen((*entry)->scopelist); } } } else { #ifdef USE_PREDICATES char *tag; /* Will point to the start of the tag. */ char *val; /* Will point to the start of the value. */ char *end; char *tag_end; tag = line; /*** Elide ws. ***/ while(isspace(*tag)) { tag++; } tag_end = tag; /*** Find tag end. ***/ while(*tag_end && (!isspace(*tag_end)) && (*tag_end != '=')) { tag_end++; } while(*tag_end && *tag_end != '=') { tag_end++; } *tag_end = 0; /*** Find value start. ***/ val = tag_end + 1; /*** Elide ws. ***/ while(isspace(*val)) { val++; } /*** Elide trailing ws. ***/ end = val; /** Find tag end. **/ while(*end != 0) { end++; } /*** Back up over trailing whitespace. ***/ end--; while(isspace(*end)) { *end = 0; /* Overwrite ws. */ end--; } SLPAttrSet_guess((*entry)->attr, tag, val, SLP_ADD); #else /* line contains an attribute (slow but it works)*/ /* TODO Fix this so we do not have to realloc memory each time! */ TrimWhitespace(line); (*entry)->attrlistlen += strlen(line) + 2; if((*entry)->attrlist == 0) { (*entry)->attrlist = malloc((*entry)->attrlistlen + 1); *(*entry)->attrlist = 0; } else { (*entry)->attrlist = realloc((*entry)->attrlist, (*entry)->attrlistlen + 2); strcat((*entry)->attrlist,","); } if((*entry)->attrlist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPD_ERROR; } strcat((*entry)->attrlist,"("); strcat((*entry)->attrlist,line); strcat((*entry)->attrlist,")"); #endif } } /* Set the scope set in properties if not is set */ if((*entry)->scopelist == 0) { (*entry)->scopelist=strdup(G_SlpdProperty.useScopes); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPD_ERROR; } (*entry)->scopelistlen = G_SlpdProperty.useScopesLen; } return *entry; SLPD_ERROR: if(*entry) { SLPDDatabaseEntryFree(*entry); *entry = 0; } return 0; }
/*=========================================================================*/ int main(int argc, char* argv[]) /*=========================================================================*/ { fd_set readfds; fd_set writefds; int highfd = 0; int fdcount = 0; SLPDSocket* sock = 0; SLPDSocket* del = 0; SLPDSocketList socketlist = {0,0}; /*------------------------------*/ /* Make sure we are root */ /*------------------------------*/ if(getuid() != 0) { SLPFatal("slpd must be started by root\n"); } /*------------------------*/ /* Parse the command line */ /*------------------------*/ if(SLPDParseCommandLine(argc,argv)) { SLPFatal("Invalid command line\n"); } /*------------------------------*/ /* Initialize the log file */ /*------------------------------*/ SLPLogFileOpen(G_SlpdCommandLine.logfile, 0); SLPLog("****************************************\n"); SLPLog("*** SLPD daemon started ***\n"); SLPLog("****************************************\n"); SLPLog("command line = %s\n",argv[0]); /*--------------------------------------------------*/ /* Initialize for the first time */ /*--------------------------------------------------*/ SLPDPropertyInit(G_SlpdCommandLine.cfgfile); SLPDDatabaseInit(G_SlpdCommandLine.regfile); SLPDSocketInit(&socketlist); /*---------------------------*/ /* make slpd run as a daemon */ /*---------------------------*/ if(Daemonize(G_SlpdCommandLine.pidfile)) { SLPFatal("Could not run as daemon\n"); } /*-----------------------*/ /* Setup signal handlers */ /*-----------------------*/ if(SetUpSignalHandlers()) { SLPFatal("Could not set up signal handlers.\n"); } /*------------------------------*/ /* Set up alarm to age database */ /*------------------------------*/ alarm(SLPD_AGE_TIMEOUT); /*-----------*/ /* Main loop */ /*-----------*/ while(G_SIGTERM == 0) { if(G_SIGHUP) { /* Reinitialize */ SLPLog("****************************************\n"); SLPLog("*** SLPD daemon restarted ***\n"); SLPLog("****************************************\n"); SLPLog("Got SIGHUP reinitializing... \n"); SLPDPropertyInit(G_SlpdCommandLine.cfgfile); SLPDDatabaseInit(G_SlpdCommandLine.regfile); SLPDSocketInit(&socketlist); G_SIGHUP = 0; } /*--------------------------------------------------------*/ /* Load the fdsets up with all of the sockets in the list */ /*--------------------------------------------------------*/ highfd = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); sock = socketlist.head; while(sock) { if(sock->fd > highfd) { highfd = sock->fd; } switch(sock->state) { case DATAGRAM_UNICAST: case DATAGRAM_MULTICAST: FD_SET(sock->fd,&readfds); break; case SOCKET_LISTEN: if(socketlist.count < SLPD_MAX_SOCKETS) { FD_SET(sock->fd,&readfds); } break; case STREAM_READ: case STREAM_FIRST_READ: FD_SET(sock->fd,&readfds); break; case STREAM_WRITE: case STREAM_FIRST_WRITE: FD_SET(sock->fd,&writefds); break; case SOCKET_CLOSE: default: break; } sock = (SLPDSocket*)sock->listitem.next; } /*-----------------------------------------------*/ /* Check to see if we we should age the database */ /*-----------------------------------------------*/ /* there is a reason this is here instead of somewhere else, but I */ /* can't remember what it was. */ if(G_SIGALRM) { SLPDDatabaseAge(SLPD_AGE_TIMEOUT); G_SIGALRM = 0; alarm(SLPD_AGE_TIMEOUT); } /*-------------*/ /* Main select */ /*-------------*/ fdcount = select(highfd+1,&readfds,&writefds,0,0); if(fdcount > 0) { sock = socketlist.head; while(sock && fdcount) { if(FD_ISSET(sock->fd,&readfds)) { switch(sock->state) { case SOCKET_LISTEN: HandleSocketListen(&socketlist,sock); break; case DATAGRAM_UNICAST: case DATAGRAM_MULTICAST: HandleDatagramRead(&socketlist,sock); break; case STREAM_READ: case STREAM_FIRST_READ: HandleStreamRead(&socketlist,sock); break; default: break; } fdcount --; } if(FD_ISSET(sock->fd,&writefds)) { HandleStreamWrite(&socketlist,sock); fdcount --; } /* Should we close the socket */ /* TODO: Close aged sockets */ if(sock->state == SOCKET_CLOSE) { del = sock; sock = (SLPDSocket*)sock->listitem.next; HandleSocketClose(&socketlist,del); } else { sock = (SLPDSocket*)sock->listitem.next; } } } } SLPLog("Got SIGTERM. Going down\n"); return 0; }