void __cdecl main(int argc, char **argv) { SERVICE_TABLE_ENTRY dispatchTable[] = { { G_SERVICENAME, (LPSERVICE_MAIN_FUNCTION)SLPDServiceMain}, { NULL, NULL} }; /*------------------------*/ /* Parse the command line */ /*------------------------*/ if(SLPDParseCommandLine(argc,argv)) { SLPFatal("Invalid command line\n"); } switch(G_SlpdCommandLine.action) { case SLPD_DEBUG: SLPDCmdDebugService(argc, argv); break; case SLPD_INSTALL: SLPDCmdInstallService(); break; case SLPD_REMOVE: SLPDCmdRemoveService(); break; default: SLPDPrintUsage(); StartServiceCtrlDispatcher(dispatchTable); 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; 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; }
/*=========================================================================*/ 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; }
/*-------------------------------------------------------------------------*/ int Daemonize(const char* pidfile) /* Turn the calling process into a daemon (detach from tty setuid(), etc */ /* */ /* Returns: zero on success non-zero if slpd could not daemonize (or if */ /* slpd is already running . */ /*-------------------------------------------------------------------------*/ { pid_t pid; FILE* fd; struct passwd* pwent; char pidstr[13]; if(G_SlpdCommandLine.detach) { /*-------------------------------------------*/ /* Release the controlling tty and std files */ /*-------------------------------------------*/ switch(fork()) { case -1: return -1; case 0: /* child lives */ break; default: /* parent dies */ exit(0); } close(0); close(1); close(2); setsid(); /* will only fail if we are already the process group leader */ } /*------------------------------------------*/ /* make sure that we're not running already */ /*------------------------------------------*/ /* read the pid from the file */ fd = fopen(pidfile,"r"); if(fd) { fread(pidstr,13,1,fd); fclose(fd); pid = atoi(pidstr); if(pid) { if(kill(pid,0) == 0) { /* we are already running */ SLPFatal("slpd daemon is already running\n"); return -1; } } } /* write my pid to the pidfile */ fd = fopen(pidfile,"w"); if(fd) { sprintf(pidstr,"%i",getpid()); fwrite(pidstr,strlen(pidstr),1,fd); fclose(fd); } /*----------------*/ /* suid to daemon */ /*----------------*/ /* TODO: why do the following lines mess up my signal handlers? */ pwent = getpwnam("daemon"); if(pwent) { if( setgroups(1, &pwent->pw_gid) < 0 || setgid(pwent->pw_gid) < 0 || setuid(pwent->pw_uid) < 0 ) { /* TODO: should we log here and return fail */ } } 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 SLPDPropertyInit(const char* conffile) /*=========================================================================*/ { struct in_addr ifaddr; struct utsname myname; struct hostent* myhostent; int i; SLPPropertyReadFile(conffile); memset(&G_SlpdProperty,0,sizeof(G_SlpdProperty)); /*-------------------------------------------------------------*/ /* Set the properties with out hard defaults */ /*-------------------------------------------------------------*/ G_SlpdProperty.isBroadcastOnly = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.isBroadcastOnly")); G_SlpdProperty.passiveDADetection = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.passiveDADetection")); G_SlpdProperty.activeDADetection = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.activeDADetection")); G_SlpdProperty.activeDiscoveryAttempts = G_SlpdProperty.activeDADetection * 3; G_SlpdProperty.multicastTTL = atoi(SLPPropertyGet("net.slp.multicastTTL")); G_SlpdProperty.multicastMaximumWait = atoi(SLPPropertyGet("net.slp.multicastMaximumWait")); G_SlpdProperty.unicastMaximumWait = atoi(SLPPropertyGet("net.slp.unicastMaximumWait")); G_SlpdProperty.randomWaitBound = atoi(SLPPropertyGet("net.slp.randomWaitBound")); G_SlpdProperty.traceMsg = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.traceMsg")); G_SlpdProperty.traceReg = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.traceReg")); G_SlpdProperty.traceDrop = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.traceDrop")); G_SlpdProperty.traceDATraffic = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.traceDATraffic")); G_SlpdProperty.DAAddresses = SLPPropertyGet("net.slp.DAAddresses"); G_SlpdProperty.DAAddressesLen = strlen(G_SlpdProperty.DAAddresses); G_SlpdProperty.useScopes = SLPPropertyGet("net.slp.useScopes"); G_SlpdProperty.useScopesLen = strlen(G_SlpdProperty.useScopes); G_SlpdProperty.isDA = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.isDA")); G_SlpdProperty.locale = SLPPropertyGet("net.slp.locale"); G_SlpdProperty.localeLen = strlen(G_SlpdProperty.locale); /*-------------------------------------*/ /* Set the net.slp.interfaces property */ /*-------------------------------------*/ G_SlpdProperty.interfaces = SLPPropertyGet("net.slp.interfaces"); if(*G_SlpdProperty.interfaces == 0) { /* put in all interfaces if none specified */ if(uname(&myname) >= 0) { myhostent = gethostbyname(myname.nodename); if(myhostent != 0) { if(myhostent->h_addrtype == AF_INET) { /* count the interfaces */ for(i=0; myhostent->h_addr_list[i];i++); /* allocate memory 16 bytes per interface*/ G_SlpdProperty.interfaces = (char*)malloc((i * 16) + 1); if(G_SlpdProperty.interfaces == 0) { SLPFatal("slpd is out of memory!\n"); } *(char*)G_SlpdProperty.interfaces = 0; /* null terminate */ for(i=0; myhostent->h_addr_list[i];i++) { memcpy(&ifaddr,myhostent->h_addr_list[i],sizeof(ifaddr)); if(i) { strcat((char*)G_SlpdProperty.interfaces,","); } strcat((char*)G_SlpdProperty.interfaces,inet_ntoa(ifaddr)); } } } } } if(G_SlpdProperty.interfaces) { G_SlpdProperty.interfacesLen = strlen(G_SlpdProperty.interfaces); } /*---------------------------------------------------------*/ /* Set the value used internally as the url for this agent */ /*---------------------------------------------------------*/ G_SlpdProperty.myUrl = (const char*)malloc(25 + strlen(myname.nodename)); if(G_SlpdProperty.myUrl == 0) { SLPFatal("slpd is out of memory!\n"); } if(G_SlpdProperty.isDA) { strcpy((char*)G_SlpdProperty.myUrl,"service:directory-agent://"); } else { strcpy((char*)G_SlpdProperty.myUrl,"service:service-agent://"); } if(uname(&myname) >= 0) { /* 25 is the length of "service:directory-agent://" */ strcat((char*)G_SlpdProperty.myUrl,myname.nodename); } G_SlpdProperty.myUrlLen = strlen(G_SlpdProperty.myUrl); }
/*=========================================================================*/ 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; }
/*=========================================================================*/ 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; }