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 */
     

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to