Hi,
I need cyrus-imapd to register it's services to an slp daemon, if it is running. I prepared a patch against 2.2.3 using calls to functions of libslp of the OpenSLP project: http://www.openslp.org/ [...] What is SLP? Service Location Protocol is an IETF standards track protocol that provides a framework to allow networking applications to discover the existence, location, and configuration of networked services in enterprise networks. (click here for full introduction ) http://www.openslp.org/#What%20is%20SLP? [...] I patched only master/master.c master/Makefile.in and configure.in similar to what contrib/drac_auth.patch does. The SLP behaviour is currently not configurable with my patch, but usually, that should not be neccessary, as a SLPRegister() call will just quickly come back in case of no running slpd instance. Also the server name of the service url should maybe be configurable like with servername in imapd.conf. The patch is attached. In case of common interest, I'll submit it also to bugzilla.andrew.cmu.edu. Btw.: Is there a specific reason, why the drac_auth patch is still not integrated? -- With best regards, Carsten Hoeger
--- configure.in +++ configure.in 2004/02/17 14:15:49 @@ -950,6 +950,19 @@ SNMP_SUBDIRS="" AC_SUBST(SNMP_SUBDIRS) +dnl +dnl Test for OpenSLP +dnl +SLPLIBS= +AC_ARG_WITH(openslp, [ --with-openslp=DIR use OpenSLP library in <DIR> [no] ], + if test -d "$withval"; then + LDFLAGS="$LDFLAGS -L${withval}" + AC_CHECK_LIB(slp, SLPOpen, + AC_DEFINE(USE_SLP,[],[Compile with OpenSLP?]) + SLPLIBS="-lslp") + fi) +AC_SUBST(SLPLIBS) + CMU_LIBWRAP CMU_UCDSNMP --- master/Makefile.in +++ master/Makefile.in 2004/02/17 14:09:47 @@ -58,7 +58,7 @@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ @COM_ERR_LDFLAGS@ -LIBS = ../lib/libcyrus_min.a @LIB_UCDSNMP@ @LIBS@ @COM_ERR_LIBS@ +LIBS = ../lib/libcyrus_min.a @LIB_UCDSNMP@ @LIBS@ @COM_ERR_LIBS@ @SLPLIBS@ SHELL = /bin/sh MAKEDEPEND = @MAKEDEPEND@ --- master/master.c +++ master/master.c 2004/02/17 15:49:46 @@ -97,6 +97,10 @@ #endif +#ifdef USE_SLP +#include <slp.h> +#endif + #include "masterconf.h" #include "master.h" @@ -106,6 +110,16 @@ #include "xmalloc.h" +#ifdef USE_SLP +#define URL_MAX 1024 +SLPHandle phslp; +struct slpurl { + char srvurl[URL_MAX]; + struct slpurl *next; +}; +struct slpurl *start = NULL; +#endif + enum { become_cyrus_early = 1, child_table_size = 10000, @@ -161,10 +175,41 @@ void limit_fds(rlim_t); void schedule_event(struct event *a); +#ifdef USE_SLP +void SLPRegReportCB(SLPHandle hslp, SLPError errcode, void* cookie) +{ + /* return the error code in the cookie */ + *(SLPError*)cookie = errcode; + + /* You could do something else here like print out */ + /* the errcode, etc. Remember, as a general rule, */ + /* do not try to do too much in a callback because */ + /* it is being executed by the same thread that is */ + /* reading slp packets from the wire. */ +} + +void SLPshutdown(void) +{ + struct slpurl *ttmp,*tmp = start; + SLPError callbackerr; + while( tmp ) { + syslog(LOG_INFO,"SLPderegister [%s]",tmp->srvurl); + SLPDereg(phslp, tmp->srvurl, SLPRegReportCB, &callbackerr); + ttmp = tmp; + tmp = tmp->next; + free(ttmp); + } + SLPClose(&phslp); +} +#endif + void fatal(const char *msg, int code) { syslog(LOG_CRIT, "%s", msg); syslog(LOG_NOTICE, "exiting"); +#ifdef USE_SLP + SLPshutdown(); +#endif exit(code); } @@ -475,7 +520,90 @@ s->socket = 0; continue; } - + +#ifdef USE_SLP + if ((!strcmp(s->proto, "tcp")) && s->listen[0] != '/' ) { + SLPError err; + SLPError callbackerr; + char *listen, *service; + char *listen_addr; + int port; + char hname[URL_MAX]; + char dname[URL_MAX]; + char turl[URL_MAX]; + struct slpurl *u; + char registered = 0; + + + /* parse_listen() and resolve_host() are destructive, + * so make a work copy of s->listen + */ + listen = xstrdup(s->listen); + + if ((service = parse_listen(listen)) == NULL) { + /* listen IS the port */ + service = listen; + listen_addr = NULL; + } else { + /* s->listen is now just the address */ + listen_addr = parse_host(listen); + if (*listen_addr == '\0') + listen_addr = NULL; + } + port = ntohs(((struct sockaddr_in *)(res)->ai_addr)->sin_port); + gethostname(hname,URL_MAX); + getdomainname(dname,URL_MAX); + + snprintf(turl,URL_MAX,"service:%s://%s.%s:%d", + service, + hname, dname, + port); + + /* check, whether we already registered the service */ + u = start; + while( u ) { + if( ! strcmp(u->srvurl,turl) ) registered = 1; + u = u->next; + } + + if( ! registered ) { + u = (struct slpurl *)calloc(1,sizeof(struct slpurl)); + if( ! u ) + fatal("out of memory", EX_UNAVAILABLE); + + strncpy(u->srvurl,turl,URL_MAX); + + if( start == NULL ) { + start = u; + } else { + struct slpurl *tmp = start; + while( tmp->next ) tmp = tmp->next; + tmp->next = u; + } + syslog(LOG_INFO,"SLPRegister [%s]",u->srvurl); + + err = SLPReg(phslp, + u->srvurl, + SLP_LIFETIME_MAXIMUM, + 0, + "", + SLP_TRUE, + SLPRegReportCB, + &callbackerr ); + + if(( err != SLP_OK) || (callbackerr != SLP_OK)) + { + syslog(LOG_ERR,"Error registering service with slp %i",err); + } + + if( callbackerr != SLP_OK) + { + syslog(LOG_ERR,"Error registering service with slp %i",callbackerr); + } + } + } +#endif + s->ready_workers = 0; s->associate = nsocket; @@ -986,6 +1114,9 @@ /* tell master agent we're exiting */ snmp_shutdown("cyrusMaster"); #endif +#ifdef USE_SLP + SLPshutdown(); +#endif syslog(LOG_INFO, "exiting on SIGTERM/SIGINT"); exit(0); @@ -1858,6 +1989,16 @@ syslog(LOG_NOTICE, "process started"); +#ifdef USE_SLP + { + int slperr; + if ( (slperr = SLPOpen(NULL, SLP_FALSE, &phslp)) != SLP_OK ) { + syslog(LOG_ERR, "SLPOpen() failed, return code: %d", slperr); + } + } +#endif + + #ifdef HAVE_UCDSNMP /* initialize SNMP agent */
pgp00000.pgp
Description: PGP signature