File openslp.initda.diff of Package openslp

--- ./common/Makefile.am.orig	2010-09-30 10:42:25.789407000 +0000
+++ ./common/Makefile.am	2010-09-30 10:43:08.404049000 +0000
@@ -48,6 +48,7 @@ libcommonslpd_la_SOURCES = \
 	slp_predicate.c \
 	slp_dhcp.c \
 	slp_mdns.c \
+	slp_network.c \
 	$(slp_v1message_SRCS) \
 	$(slp_security_SRCS)
 	
--- ./common/slp_message.h.orig	2010-09-30 10:42:26.243407000 +0000
+++ ./common/slp_message.h	2010-09-30 10:43:08.413054000 +0000
@@ -170,6 +170,7 @@ typedef UINT32*         PUINT32;
 #define SLP_REG_SOURCE_REMOTE   1  /* from a remote host    */
 #define SLP_REG_SOURCE_LOCAL    2  /* from localhost or IPC */
 #define SLP_REG_SOURCE_STATIC   3  /* from the slp.reg file */
+#define SLP_REG_SOURCE_PULL_PEER_DA 4 /* from another DA pulled at startup */
 
 #define SLP_REG_WATCH_TCP	(1<<0)
 #define SLP_REG_WATCH_UDP	(1<<1)
--- ./common/slp_property.c.orig	2010-09-30 10:42:25.817415000 +0000
+++ ./common/slp_property.c	2010-09-30 10:43:08.422048000 +0000
@@ -213,6 +213,10 @@ int SetDefaultValues()
 #else /* UNIX */
     result |= SLPPropertySet("net.slp.OpenSLPVersion", VERSION);
 #endif
+    result |= SLPPropertySet("net.slp.DASyncReg","false");
+    result |= SLPPropertySet("net.slp.isDABackup","false");
+    result |= SLPPropertySet("net.slp.DABackupInterval","900");
+    result |= SLPPropertySet("net.slp.DABackupLocalReg","false");
 
     return result;
 }
--- ./etc/slp.conf.orig	2002-06-11 17:25:40.000000000 +0000
+++ ./etc/slp.conf	2010-09-30 10:43:08.426050000 +0000
@@ -40,6 +40,20 @@
 # if isDA is false.
 ;net.slp.DAHeartBeat = 10800
 
+# Enables backup of registrations to /etc/slp.reg.d/slpd/DABackup.
+;net.slp.isDABackup = true
+
+# A 32 bit integer giving the number of seconds for the DABackup file update.
+# Default is 15 minutes (900 seconds). Ignored if isDA is false.
+;net.slp.DABackupInterval = 900
+
+# Include local registrations in the backup, too. The default is false.
+;net.slp.DABackupLocalReg = true
+
+# Enables slpd to sync service registration between SLP DAs on startup
+# Default is false
+;net.slp.DASyncReg = true
+
 
 #----------------------------------------------------------------------------
 # SA Specific Configuration
--- ./slpd/Makefile.am.orig	2010-09-30 10:42:25.901413000 +0000
+++ ./slpd/Makefile.am	2010-09-30 10:43:08.432047000 +0000
@@ -39,6 +39,7 @@ slpd_knownda.c \
 slpd_incoming.c \
 slpd_outgoing.c \
 slpd_mdns.c \
+slpd_initda.c \
 slpd.h \
 slpd_knownda.h \
 slpd_process.h \
@@ -51,6 +52,7 @@ slpd_outgoing.h \
 slpd_regfile.h \
 slpd_incoming.h \
 slpd_mdns.h \
+slpd_initda.h \
 slpd_socket.h
     
 slpd_LDADD      =  ../common/libcommonslpd.la \
--- ./slpd/slpd_database.c.orig	2010-09-30 10:42:26.270411000 +0000
+++ ./slpd/slpd_database.c	2010-09-30 10:43:37.168731000 +0000
@@ -76,6 +76,7 @@ FILE *regfileFP;
 /* standard header files                                                   */
 /*=========================================================================*/
 #include <dirent.h>
+#include <time.h>
 #include <linux/netlink.h>
 #include <linux/inet_diag.h>
 #include <sched.h>
@@ -212,6 +213,7 @@ int SLPDDatabaseReg(SLPMessage msg, SLPB
                     /* Check to ensure the source addr is the same */
                     /* as the original */
                     if ( G_SlpdProperty.checkSourceAddr &&
+			 entryreg->source != SLP_REG_SOURCE_PULL_PEER_DA &&
                          memcmp(&(entry->msg->peer.sin_addr),
                                 &(msg->peer.sin_addr),
                                 sizeof(struct in_addr)) )
@@ -228,6 +230,13 @@ int SLPDDatabaseReg(SLPMessage msg, SLPB
                         return SLP_ERROR_AUTHENTICATION_FAILED;
                     }
 #endif  
+		    if (reg->source == SLP_REG_SOURCE_PULL_PEER_DA && entryreg->source != SLP_REG_SOURCE_PULL_PEER_DA)
+		    {
+			/* Do not update not-pulled registrations with pulled ones */
+                        SLPDatabaseClose(dh);
+                        return 0;
+		    }
+			
                     /* Remove the identical entry */
                     SLPDatabaseRemove(dh,entry);
                     break;
@@ -322,6 +331,7 @@ int SLPDDatabaseDeReg(SLPMessage msg)
                     /* Check to ensure the source addr is the same as */
                     /* the original */
                     if ( G_SlpdProperty.checkSourceAddr &&
+			 entry->msg->body.srvreg.source != SLP_REG_SOURCE_PULL_PEER_DA &&
                          memcmp(&(entry->msg->peer.sin_addr),
                                 &(msg->peer.sin_addr),
                                 sizeof(struct in_addr)) )
@@ -465,6 +475,12 @@ int SLPDDatabaseSrvRqstStart(SLPMessage
                             }
                         }
 #endif
+			if (srvrqst->predicatelen == 29 && !strncmp(srvrqst->predicate, "(!(openslp-pulled-from-da=*))", 29))
+			{
+			    /* this is the special "no pulled entries" predicate used in DA syncing */
+			    if (entryreg->source == SLP_REG_SOURCE_PULL_PEER_DA)
+				continue;	/* skip it */
+			}
                         if ( (*result)->urlcount + 1 > G_SlpdDatabase.urlcount )
                         {
                             /* Oops we did not allocate a big enough result */
@@ -1203,7 +1219,7 @@ int SLPDDatabaseReInit()
     if ( regfileFP )
     {
         rewind(regfileFP);
-        while ( SLPDRegFileReadSrvReg(regfileFP, &msg, &buf) == 0 )
+        while ( SLPDRegFileReadSrvReg(regfileFP, SLP_REG_SOURCE_STATIC, &msg, &buf) == 0 )
         {
             SLPDDatabaseReg(msg, buf);
         }   
@@ -1223,7 +1239,7 @@ int SLPDDatabaseReInit()
                   strcmp(filename+strlen(filename)-4, ".reg") == 0 &&
                   (fd=fopen(filename,"rb")) )
              {
-                 while ( SLPDRegFileReadSrvReg(fd, &msg, &buf) == 0 )
+                 while ( SLPDRegFileReadSrvReg(fd, SLP_REG_SOURCE_STATIC, &msg, &buf) == 0 )
                  {
                      SLPDDatabaseReg(msg, buf);
                  }   
@@ -1238,6 +1254,69 @@ int SLPDDatabaseReInit()
     return 0;
 }
 
+/*=========================================================================*/
+void SLPDDatabaseReadDABackup(FILE *fp)
+/*=========================================================================*/
+{
+    SLPMessage          msg;
+    SLPBuffer           buf;
+    time_t timediff;
+    long l;
+
+    SLPDLog("Reading registration backup file...\n");
+    rewind(fp);
+    if (fscanf(fp, "# Update timestamp: %ld\n", &l) != 1)
+	return;
+    timediff = time(NULL) - (time_t)l;
+    if (timediff < 0)
+	timediff = 0;
+    while (SLPDRegFileReadSrvReg(fp, SLP_REG_SOURCE_REMOTE, &msg, &buf) == 0)
+    {
+	if (!G_SlpdProperty.DABackupLocalReg && msg->body.srvreg.source == SLP_REG_SOURCE_LOCAL)
+	{
+	    SLPMessageFree(msg);
+	    SLPBufferFree(buf);
+	    continue;
+	}
+	msg->body.srvreg.urlentry.lifetime -= timediff;
+	if (msg->body.srvreg.urlentry.lifetime > 0)
+	    SLPDDatabaseReg(msg, buf);
+	else
+	{
+	    SLPMessageFree(msg);
+	    SLPBufferFree(buf);
+	}
+    }
+}
+
+/*=========================================================================*/
+void SLPDDatabaseWriteDABackup(FILE *fp)
+/*=========================================================================*/
+{
+    SLPDatabaseHandle   dh;
+    SLPDatabaseEntry*   entry;
+
+    SLPDLog("Writing registration backup file...\n");
+    rewind(fp);
+    (void)ftruncate(fileno(fp), 0);
+    fprintf(fp, "# Update timestamp: %ld\n\n", (long)time(NULL));
+    dh = SLPDatabaseOpen(&G_SlpdDatabase.database);
+    if (dh)
+    {
+	while ((entry = SLPDatabaseEnum(dh)) != NULL)
+	{
+	    if (entry->msg->body.srvreg.source == SLP_REG_SOURCE_STATIC)
+		continue;
+	    if (!G_SlpdProperty.DABackupLocalReg && entry->msg->body.srvreg.source == SLP_REG_SOURCE_LOCAL)
+		continue;
+	    SLPDRegFileWriteSrvReg(fp, entry->msg);
+	}
+	SLPDatabaseClose(dh);
+    }
+    fflush(fp);
+}
+
+
 #ifdef DEBUG
 /*=========================================================================*/
 void SLPDDatabaseDeinit(void)
--- ./slpd/slpd_database.h.orig	2010-09-30 10:42:25.916410000 +0000
+++ ./slpd/slpd_database.h	2010-09-30 10:43:08.464052000 +0000
@@ -286,6 +286,14 @@ int SLPDDatabaseReInit();
 
 void SLPDDatabaseWatcher(void);
 
+/*=========================================================================*/
+void SLPDDatabaseReadDABackup(FILE *fp);
+/*=========================================================================*/
+
+/*=========================================================================*/
+void SLPDDatabaseWriteDABackup(FILE *fp);
+/*=========================================================================*/
+
 #ifdef DEBUG
 /*=========================================================================*/
 void SLPDDatabaseDeinit(void);
--- ./slpd/slpd_initda.c.orig	2010-09-30 10:43:08.469052000 +0000
+++ ./slpd/slpd_initda.c	2010-09-30 10:43:08.472049000 +0000
@@ -0,0 +1,407 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <slpd.h>
+#include <slp_message.h>
+#include <slp_property.h>
+#include <slp_network.h>
+#include <slpd_database.h>
+#include <slpd_regfile.h>
+#include <slpd_property.h>
+#include <slpd_log.h>
+
+
+#define SLP_NETWORK_TIMED_OUT		-19
+#define SLP_MEMORY_ALLOC_FAILED		-21
+#define SLP_NETWORK_ERROR		-23
+
+/*=========================================================================*/
+static int SLPDUnicastRqstRply(int sock,
+			struct sockaddr_in* destaddr,
+		        const char* langtag,
+		        char* buf,
+		        char buftype,
+		        int bufsize,
+		        int (*callback)(SLPMessage message, void *cookie),
+		        void * cookie)
+/*=========================================================================*/
+{
+    struct timeval      timeout;
+    SLPBuffer           sendbuf         = 0;
+    SLPBuffer           recvbuf         = 0;
+    SLPMessage          message         = 0;
+    int                 result          = 0;
+    int                 langtaglen      = 0; 
+    int                 xid             = 0;
+    int                 mtu             = 0;
+    int                 size            = 0;
+    int                 maxwait         = 0;
+    int                 timeouts[1];
+
+    /*----------------------------------------------------*/
+    /* Save off a few things we don't want to recalculate */
+    /*----------------------------------------------------*/
+    langtaglen = strlen(langtag);
+    xid = SLPXidGenerate();
+    mtu = SLPPropertyAsInteger(SLPPropertyGet("net.slp.MTU"));
+    sendbuf = SLPBufferAlloc(mtu);
+    if(sendbuf == 0)
+    {
+        result = SLP_MEMORY_ALLOC_FAILED;
+	goto FINISHED;
+    }
+    maxwait = SLPPropertyAsInteger(SLPPropertyGet("net.slp.unicastMaximumWait"));
+    SLPPropertyAsIntegerVector(SLPPropertyGet("net.slp.unicastTimeouts"), timeouts, 1);
+    timeout.tv_sec = timeouts[0] / 1000;
+    timeout.tv_usec = (timeouts[0] % 1000) * 1000;
+    size = 16 + langtaglen + bufsize;
+    if((sendbuf = SLPBufferRealloc(sendbuf,size)) == 0)
+    {
+	result = SLP_MEMORY_ALLOC_FAILED;
+	goto FINISHED;
+    }
+    /*-----------------------------------*/
+    /* Add the header to the send buffer */
+    /*-----------------------------------*/
+    /*version*/
+    *(sendbuf->start)       = 2;
+    /*function id*/
+    *(sendbuf->start + 1)   = buftype;
+    /*length*/
+    ToUINT24(sendbuf->start + 2, size);
+    /*flags*/
+    ToUINT16(sendbuf->start + 5, SLP_FLAG_UCAST);  /*this is a unicast */
+    /*ext offset*/
+    ToUINT24(sendbuf->start + 7,0);
+    /*xid*/
+    ToUINT16(sendbuf->start + 10,xid);
+    /*lang tag len*/
+    ToUINT16(sendbuf->start + 12,langtaglen);
+    /*lang tag*/
+    memcpy(sendbuf->start + 14, langtag, langtaglen);
+    sendbuf->curpos = sendbuf->start + langtaglen + 14 ;
+    ToUINT16(sendbuf->curpos,0);
+    sendbuf->curpos = sendbuf->curpos + 2;
+    /*-----------------------------*/
+    /* Add the rest of the message */
+    /*-----------------------------*/
+    memcpy(sendbuf->curpos, buf, bufsize);
+    /*----------------------*/
+    /* send the send buffer */
+    /*----------------------*/
+
+    result = SLPNetworkSendMessage(sock, SOCK_STREAM, sendbuf, destaddr, &timeout);
+    if (result != 0)
+    {
+	result = errno == ETIMEDOUT ? SLP_NETWORK_TIMED_OUT : SLP_NETWORK_ERROR;
+	goto FINISHED;
+    }
+    result = SLPNetworkRecvMessage(sock, SOCK_STREAM, &recvbuf, destaddr, &timeout);
+    if (result != 0)
+    {
+	result = errno == ETIMEDOUT ? SLP_NETWORK_TIMED_OUT : SLP_NETWORK_ERROR;
+	goto FINISHED;
+    }
+    if(AsUINT16(recvbuf->start+10) != xid)
+    {
+	result = SLP_NETWORK_ERROR;
+	goto FINISHED;
+    }
+    message = SLPMessageAlloc();
+    result = SLPMessageParseBuffer(destaddr, recvbuf, message);
+    if (result == 0)
+    {
+	result = callback(message, cookie);
+    }
+FINISHED:
+    SLPMessageFree(message);
+    SLPBufferFree(sendbuf);
+    SLPBufferFree(recvbuf);
+    return result;
+}
+
+typedef struct SLPURL {
+    struct SLPURL *next;
+    struct SLPURL *last;
+    char *serviceURL;
+    char *attrs;
+    char* scopelist;
+    char* serviceType;      
+    unsigned short ltime;
+} SLPUrl;
+
+
+//Cache collection structure
+typedef struct SLPUrlList {
+    char *services; /* list of all services */
+    SLPUrl *slpUrl; /* linked list of URLs for all services */
+    SLPUrl *currentSLPUrl;  /* next location to be used for update */
+    char* currentScope;
+    char* currentServiceType;
+} SLPUrlList;  
+
+static SLPUrl* AllocateSLPUrl()
+{
+    SLPUrl* slpUrl          = (SLPUrl*)malloc(sizeof(SLPUrl));
+    slpUrl->serviceURL      = NULL;
+    slpUrl->ltime           = 0;
+    slpUrl->scopelist       = NULL;
+    slpUrl->serviceType     = NULL;
+    slpUrl->attrs           = NULL;
+    slpUrl->next            = NULL;
+    slpUrl->last            = NULL;
+    return slpUrl;
+}
+
+
+static void CleanUpSLPUrlList(SLPUrlList* slpUrlList)
+{
+    SLPUrl* slpUrl,*slpUrlNext;
+
+    slpUrl = slpUrlList->slpUrl;
+    while(slpUrl)
+    {
+	if (slpUrl->serviceURL)
+	    free(slpUrl->serviceURL);
+	if (slpUrl->scopelist)
+	    free(slpUrl->scopelist);
+	if (slpUrl->serviceType)
+	    free(slpUrl->serviceType);
+	if (slpUrl->attrs)
+	    free(slpUrl->attrs);
+	slpUrlNext = slpUrl->next;
+	free(slpUrl);
+	slpUrl = slpUrlNext;
+    }
+    slpUrlList->slpUrl = NULL;
+    if (slpUrlList->currentScope != NULL)
+	free(slpUrlList->currentScope);
+    if(slpUrlList->services != NULL)
+	free(slpUrlList->services);
+    if(slpUrlList->currentServiceType != NULL)
+	free(slpUrlList->currentServiceType);
+    free(slpUrlList);
+}
+
+static int SLPSrvTCallBack(SLPMessage message, void* cookie)
+{
+    if (message->header.functionid != SLP_FUNCT_SRVTYPERPLY)
+	return SLP_NETWORK_ERROR;
+    if (message->body.srvtyperply.errorcode != 0)
+	return message->body.srvtyperply.errorcode;
+    /* null terminate as in libslp */
+    ((char *)message->body.srvtyperply.srvtypelist)[message->body.srvtyperply.srvtypelistlen] = 0;
+    ((SLPUrlList*)cookie)->services = strdup(message->body.srvtyperply.srvtypelist);
+    return 0;
+}
+
+static int SLPSrvCallBack(SLPMessage message, void* cookie)
+{
+    SLPUrl *slpUrl = NULL;
+    char scopelist[4096];
+    int i;
+    SLPUrlEntry *srvurl;
+
+    if (message->header.functionid != SLP_FUNCT_SRVRPLY)
+	return SLP_NETWORK_ERROR;
+    if (message->body.srvrply.errorcode != 0)
+	return message->body.srvrply.errorcode;
+    for (i=0;i<message->body.srvrply.urlcount;i++)
+    {
+	srvurl = message->body.srvrply.urlarray + i;
+	/* null terminate url as in libslp, overwrites authcount */
+	((char *)srvurl->url)[srvurl->urllen] = 0;
+        for(slpUrl = ((SLPUrlList*)cookie)->slpUrl; slpUrl ; slpUrl = slpUrl->next)
+        {
+	    /* Check whether the same service URL is available as part of different scope*/
+	    if( (slpUrl->serviceURL != NULL) && ( strcasecmp( slpUrl->serviceURL,srvurl->url) == 0))
+		break;
+	}
+	if (slpUrl)
+	{
+	    snprintf(scopelist,sizeof(scopelist),"%s,%s",slpUrl->scopelist,((SLPUrlList*)cookie)->currentScope);
+	    free(slpUrl->scopelist);
+	    slpUrl->scopelist = strdup(scopelist);
+	}
+	else
+	{
+	    slpUrl                  = AllocateSLPUrl();
+	    slpUrl->serviceURL      = strdup(srvurl->url);
+	    slpUrl->ltime           = srvurl->lifetime;
+	    slpUrl->scopelist       = strdup(((SLPUrlList*)cookie)->currentScope);
+	    slpUrl->serviceType     = strdup(((SLPUrlList*)cookie)->currentServiceType);
+	    slpUrl->attrs           = NULL;
+	    slpUrl->next            = ((SLPUrlList*)cookie)->slpUrl;
+	    if(((SLPUrlList*)cookie)->slpUrl)
+		((SLPUrlList*)cookie)->slpUrl->last = slpUrl;
+	    ((SLPUrlList*)cookie)->slpUrl= slpUrl;
+        }
+    }
+    return 0;
+}
+
+static int SLPSrvAttrCallBack(SLPMessage message, void* cookie)
+{
+    SLPUrl *lslpUrl = ((SLPUrlList*)cookie)->currentSLPUrl;
+    if (message->header.functionid != SLP_FUNCT_ATTRRPLY)
+	return SLP_NETWORK_ERROR;
+    if (message->body.attrrply.errorcode != 0)
+	return message->body.attrrply.errorcode;
+
+    /* null terminate as in libslp */
+    ((char *)message->body.attrrply.attrlist)[message->body.attrrply.attrlistlen] = 0;
+    lslpUrl->attrs = strdup(message->body.attrrply.attrlist);
+    return 0;
+}
+
+static char *createreq(int *sizep, char *url, char *scope, char *predicate, char *spi)
+{
+  char *buf, *cur;
+  int urllen = url ? strlen(url) : 0;
+  int scopelen = scope ? strlen(scope) : 0;
+  int predicatelen = predicate ? strlen(predicate) : 0;
+  int spilen = spi ? strlen(spi) : 0;
+  buf = malloc(2 + urllen + 2 + scopelen + 2 + predicatelen + 2 + spilen);
+  cur = buf;
+  if (url)
+  {
+	ToUINT16(cur, urllen);
+	cur += 2;
+	memcpy(cur, url, urllen);
+	cur += urllen;
+  }
+  if (scope)
+  {
+	ToUINT16(cur, scopelen);
+	cur += 2;
+	memcpy(cur, scope, scopelen);
+	cur += scopelen;
+  }
+  if (predicate)
+  {
+	ToUINT16(cur, predicatelen);
+	cur += 2;
+	memcpy(cur, predicate, predicatelen);
+	cur += predicatelen;
+  }
+  if (spi)
+  {
+	ToUINT16(cur, spilen);
+	cur += 2;
+	memcpy(cur, spi, spilen);
+	cur += spilen;
+  }
+  *sizep = cur - buf;
+  return buf;
+}
+
+
+/*=========================================================================*/
+int getSLPServiceURLs(int sock, struct sockaddr_in *destaddr)
+/*=========================================================================*/
+{
+    char *strng, *services;
+    int gresult = 0, result;
+    SLPUrl* slpUrl;
+    char *scope = NULL, *scopelist = NULL;
+    char scopeptr[4096],serviceptr[4096];
+    SLPMessage          msg;
+    SLPBuffer           buf;
+    const char *langtag;
+    char *outbuf;
+    int bufsize;
+    char *srvtype, *srvtype_end;
+
+    SLPUrlList* slpUrlList  = (SLPUrlList*)malloc(sizeof(SLPUrlList));
+    slpUrlList->slpUrl      = NULL;
+    slpUrlList->services    = NULL;
+    slpUrlList->currentServiceType  = NULL;
+    slpUrlList->currentScope  = NULL;
+
+    langtag = SLPPropertyGet("net.slp.locale");
+
+    scopelist = strdup(G_SlpdProperty.useScopes);
+
+    for(scope = strtok_r(scopelist,",",(char**)&scopeptr); scope ; scope = strtok_r(NULL,",",(char**)&scopeptr))
+    {
+	slpUrlList->currentScope = strdup(scope);
+	outbuf = createreq(&bufsize, "", scope, NULL, NULL);
+	ToUINT16(outbuf, 0xffff); /* 0xffff indicates all service types */
+	result = SLPDUnicastRqstRply(sock, destaddr, langtag, outbuf, SLP_FUNCT_SRVTYPERQST, bufsize, SLPSrvTCallBack, slpUrlList);
+	free(outbuf);
+	if (result)
+	{
+	    gresult = result;	/* remember error with that scope */
+	    SLPDLog("Error: SLPFindSrvTypes %d\n",result);
+	    continue;
+	}
+	if(slpUrlList->services)
+	{
+	    services = strdup(slpUrlList->services);
+	    for(strng = strtok_r(services, ",",(char**)&serviceptr); strng ; strng = strtok_r(NULL, ",",(char**)&serviceptr))
+	    {
+		slpUrlList->currentServiceType = strdup(strng);
+		outbuf = createreq(&bufsize, strng, scope, "", "");
+		result = SLPDUnicastRqstRply(sock, destaddr, langtag, outbuf, SLP_FUNCT_SRVRQST, bufsize, SLPSrvCallBack, slpUrlList);
+		free(outbuf);
+		free(slpUrlList->currentServiceType);
+		slpUrlList->currentServiceType = NULL;
+		if(result != 0)
+		{
+		    SLPDLog("Error: SLPFindSrvs %d\n", result);
+		    continue;
+		}
+	    }
+	    free(services);
+	}
+	if (slpUrlList->currentScope != NULL)
+	{
+	    free(slpUrlList->currentScope);
+	    slpUrlList->currentScope = NULL;
+	}
+	if(slpUrlList->services != NULL)
+	{
+	    free(slpUrlList->services);
+	    slpUrlList->services = NULL;
+	}
+    }
+
+    /* we now have collected all services, fetch the attributes */
+
+    for(slpUrl = slpUrlList->slpUrl; slpUrl ; slpUrl = slpUrl->next)
+    {
+	slpUrl->attrs = NULL;
+	slpUrlList->currentSLPUrl = slpUrl;
+	outbuf = createreq(&bufsize, slpUrl->serviceURL, slpUrl->scopelist, "", "");
+	result = SLPDUnicastRqstRply(sock, destaddr, langtag, outbuf, SLP_FUNCT_ATTRRQST, bufsize, SLPSrvAttrCallBack, slpUrlList);
+	free(outbuf);
+	if(result != 0)
+	{
+	    SLPDLog("Error: SLPFindAttrs %d\n", result);
+	    continue;
+	}
+	srvtype = strdup(slpUrl->serviceURL);
+	srvtype_end = strstr(srvtype, "://");
+	if (srvtype_end)
+	    *srvtype_end = 0;
+	if (SLPDCreateSrvReg(SLP_REG_SOURCE_PULL_PEER_DA,
+                             strlen(slpUrl->serviceURL), slpUrl->serviceURL,
+                             strlen(langtag), (char *)langtag,
+                             strlen(srvtype), srvtype,
+                             strlen(slpUrl->scopelist), slpUrl->scopelist,
+                             slpUrl->attrs ? strlen(slpUrl->attrs) : 0, slpUrl->attrs,
+                             slpUrl->ltime, &msg, &buf) == 0)
+	{
+	    msg->peer = *destaddr;
+	    SLPDDatabaseReg(msg, buf);
+	}
+	free(srvtype);
+    }
+
+    CleanUpSLPUrlList(slpUrlList);
+    if(scopelist != NULL)
+	free(scopelist);
+    return gresult;
+}
+
--- ./slpd/slpd_initda.h.orig	2010-09-30 10:43:08.475048000 +0000
+++ ./slpd/slpd_initda.h	2010-09-30 10:43:08.476048000 +0000
@@ -0,0 +1,16 @@
+#ifndef SLPD_INITDA_H_INCLUDE
+#define SLPD_INITDA_H_INCLUDE
+
+#include "slpd.h"
+
+/*=========================================================================*/
+/* common code includes                                                    */
+/*=========================================================================*/
+#include "slpd_socket.h"
+
+
+/*=========================================================================*/
+int getSLPServiceURLs(int sock, struct sockaddr_in *destaddr);
+/*=========================================================================*/
+
+#endif
--- ./slpd/slpd_log.c.orig	2010-09-30 10:42:25.931413000 +0000
+++ ./slpd/slpd_log.c	2010-09-30 10:43:08.484053000 +0000
@@ -476,6 +476,9 @@ void SLPDLogRegistration(const char* pre
         case SLP_REG_SOURCE_STATIC:
             SLPDLog("static (slp.reg)\n");
             break;
+        case SLP_REG_SOURCE_PULL_PEER_DA:
+            SLPDLog("pulled from peer DA (%s)\n", inet_ntoa(entry->msg->peer.sin_addr));
+            break;
         }
         SLPDLogBuffer("    service-url = ",
                       entry->msg->body.srvreg.urlentry.urllen,
--- ./slpd/slpd_main.c.orig	2010-09-30 10:42:26.098408000 +0000
+++ ./slpd/slpd_main.c	2010-09-30 10:43:08.493052000 +0000
@@ -63,6 +63,7 @@
 #ifdef ENABLE_SLPv2_SECURITY
 #include "slpd_spi.h"
 #endif
+#include "slpd_initda.h"
 
 /*=========================================================================*/
 /* common code includes                                                    */
@@ -76,12 +77,34 @@ int G_SIGALRM;
 int G_SIGTERM;
 int G_SIGHUP;
 char *reg_file_dir;
+FILE *DABackupfp;
 
 #ifdef DEBUG
 int G_SIGINT;		/* Signal being used for dumping registrations */
 #endif 
 /*==========================================================================*/
 
+
+/*-------------------------------------------------------------------------*/
+static void SLPDOpenDABackupFile()
+/*-------------------------------------------------------------------------*/
+{
+    FILE *fp;
+    char filename[1024];
+    snprintf(filename, sizeof(filename), "%s/slpd/%s", reg_file_dir, "DABackup");
+
+    fp = fopen(filename, "a+");
+    if (!DABackupfp && !fp)
+	SLPDLog("Could not open DABackup file\n");
+    if (fp)
+    {
+	if (DABackupfp)
+	    fclose(DABackupfp);
+	DABackupfp = fp;
+    }
+}
+
+
 #ifdef HAVE_POLL
 
 /*-------------------------------------------------------------------------*/
@@ -239,6 +262,10 @@ void HandleSigTerm()
     SLPDLog("SLPD daemon shutting down\n");
     SLPDLog("****************************************\n");
 
+    /* write backup file if configured */
+    if (G_SlpdProperty.isDA && G_SlpdProperty.isDABackup && DABackupfp)
+	SLPDDatabaseWriteDABackup(DABackupfp);
+
     /* close all incoming sockets */
     SLPDIncomingDeinit();
 #ifdef ENABLE_MDNS_SLPD
@@ -301,6 +328,10 @@ void HandleSigHup()
     SLPDLog("SLPD daemon reset by SIGHUP\n");
     SLPDLog("****************************************\n\n");
 
+    if (G_SlpdProperty.isDA && G_SlpdProperty.isDABackup && DABackupfp)
+    {
+	SLPDDatabaseWriteDABackup(DABackupfp);
+    }
     /* unregister with all DAs */
     SLPDKnownDADeinit();
 
@@ -322,6 +353,11 @@ void HandleSigHup()
     /* Re-read the static registration file (slp.reg)*/
     SLPDDatabaseReInit();
 
+    if (G_SlpdProperty.isDA && G_SlpdProperty.isDABackup && DABackupfp)
+    {
+	SLPDDatabaseReadDABackup(DABackupfp);
+    }
+
     /* Rebuild Known DA database */
     SLPDKnownDAInit();
 
@@ -654,6 +690,9 @@ int main(int argc, char* argv[])
     SLPDLog("Agent Interfaces = %s\n",G_SlpdProperty.interfaces);
     SLPDLog("Agent URL = %s\n",G_SlpdProperty.myUrl);
 
+    if (G_SlpdProperty.isDA && G_SlpdProperty.isDABackup)
+	SLPDOpenDABackupFile();
+
     /*---------------------------*/
     /* init watcher              */
     /*---------------------------*/
@@ -675,6 +714,43 @@ int main(int argc, char* argv[])
         SLPDFatal("Error setting up signal handlers.\n");
     }
 
+    if (G_SlpdProperty.isDA && G_SlpdProperty.isDABackup && DABackupfp)
+    {
+	SLPDDatabaseReadDABackup(DABackupfp);
+    }
+
+    if((G_SlpdProperty.isDA) && (G_SlpdProperty.DASyncReg))
+    {
+	/* HACK: at that point in time all outgoing sockets are DA connections
+	 * and the incoming sockets are our interfaces */
+	SLPDLog("Pulling service list from other DAs...\n");
+	SLPDSocket* sock = (SLPDSocket*)G_OutgoingSocketList.head;
+	while (sock)
+	{
+	    SLPDSocket* isock = (SLPDSocket*)G_IncomingSocketList.head;
+
+	    /* make sure we're not connecting to ourself */
+	    while (isock)
+	    {
+		if (sock->peeraddr.sin_addr.s_addr == isock->peeraddr.sin_addr.s_addr)
+		    break;
+		isock = (SLPDSocket*)isock->listitem.next;
+	    }
+	    if (!isock)
+	    {
+		int s = SLPNetworkConnectStream(&sock->peeraddr, 0);
+		if (s >= 0)
+		{
+		    int result = getSLPServiceURLs(s, &sock->peeraddr);
+		    close(s);
+		    if (result == 0)
+			break;
+		}
+	    }
+	    sock = (SLPDSocket*)sock->listitem.next;    
+        }
+    }
+
     /*------------------------------*/
     /* Set up alarm to age database */
     /*------------------------------*/
@@ -753,6 +829,22 @@ int main(int argc, char* argv[])
 	}			
 #endif
 
+	if (G_SlpdProperty.isDA && G_SlpdProperty.isDABackup && DABackupfp)
+	{
+	    static time_t lastbck;
+	    time_t now;
+
+	    now = time(NULL);
+	    if (!lastbck)
+		lastbck = now;
+	    if (now - lastbck > G_SlpdProperty.DABackupInterval)
+	    {
+		SLPDLog("Updating registration backup file\n");
+		SLPDDatabaseWriteDABackup(DABackupfp);
+		lastbck = now;
+	    }
+	}
+
     } /* End of main loop */
 
     /* Got SIGTERM */
--- ./slpd/slpd_property.c.orig	2010-09-30 10:42:26.221408000 +0000
+++ ./slpd/slpd_property.c	2010-09-30 10:43:08.500046000 +0000
@@ -232,6 +232,11 @@ int SLPDPropertyInit(const char* conffil
     G_SlpdProperty.nextActiveDiscovery = 0;  /* ensures xmit on first call to SLPDKnownDAActiveDiscovery() */
     G_SlpdProperty.nextPassiveDAAdvert = 0;  /* ensures xmit on first call to SLPDKnownDAPassiveDiscovery()*/
 
+    G_SlpdProperty.DASyncReg = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.DASyncReg"));
+    G_SlpdProperty.DASyncReg = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.DASyncReg"));
+    G_SlpdProperty.isDABackup = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.isDABackup"));
+    G_SlpdProperty.DABackupInterval = SLPPropertyAsInteger(SLPPropertyGet("net.slp.DABackupInterval"));
+    G_SlpdProperty.DABackupLocalReg = SLPPropertyAsBoolean(SLPPropertyGet("net.slp.DABackupLocalReg"));
     return 0;
 }
 
--- ./slpd/slpd_property.h.orig	2010-09-30 10:42:26.216411000 +0000
+++ ./slpd/slpd_property.h	2010-09-30 10:43:08.507046000 +0000
@@ -96,6 +96,10 @@ typedef struct _SLPDProperty
     int             DAHeartBeat;
     int             oversizedUDP;
     int             allowDoubleEqualInPredicate;
+    int             DASyncReg;
+    int             isDABackup;
+    int             DABackupInterval;
+    int             DABackupLocalReg;
 }SLPDProperty;
 
 
--- ./slpd/slpd_regfile.c.orig	2010-09-30 10:42:25.984413000 +0000
+++ ./slpd/slpd_regfile.c	2010-09-30 10:43:08.516048000 +0000
@@ -128,19 +128,213 @@ char* RegFileReadLine(FILE* fd, char* li
     return line;
 }
 
+
 /*=========================================================================*/
-int SLPDRegFileReadSrvReg(FILE* fd,
-                          SLPMessage* msg,
-                          SLPBuffer* buf)
-/* A really big and nasty function that reads an service registration from */
-/* from a file. Don't look at this too hard or you'll be sick.  This is by */
+int SLPDCreateSrvReg(int     source,
+                     int     urllen,
+                     char*   url,
+                     int     langtaglen,
+                     char*   langtag,
+                     int     srvtypelen,
+                     char*   srvtype,
+                     int     scopelistlen,
+                     char*   scopelist,
+                     int     attrlistlen,
+                     char*   attrlist,
+                     int     lifetime,
+                     SLPMessage* msg,
+                     SLPBuffer* buf)
+/* Create a SrcReg Message from given data.                                */
+/* Don't look at this too hard or you'll be sick.  This is by far          */
 /* the most horrible code in OpenSLP.  Please volunteer to rewrite it!     */
 /*                                                                         */
 /*  "THANK GOODNESS this function is only called at startup" -- Matt       */
 /*                                                                         */
+/* Note:    Eventually the caller needs to call SLPBufferFree() and        */
+/*          SLPMessageFree() to free memory                                */
+/*=========================================================================*/
+{
+    int     result          = 0;
+    int     bufsize         = 0;
+    struct  sockaddr_in     peer;
+#ifdef ENABLE_SLPv2_SECURITY
+    unsigned char*  urlauth         = 0;
+    int             urlauthlen      = 0;
+    unsigned char*  attrauth        = 0;
+    int             attrauthlen     = 0;
+#endif
+
+#ifdef ENABLE_SLPv2_SECURITY
+    /*--------------------------------*/
+    /* Generate authentication blocks */
+    /*--------------------------------*/
+    if(G_SlpdProperty.securityEnabled)
+    {
+        
+        SLPAuthSignUrl(G_SlpdSpiHandle,
+                       0,
+                       0,
+                       urllen,
+                       url,
+                       &urlauthlen,
+                       &urlauth);
+    
+        SLPAuthSignString(G_SlpdSpiHandle,
+                          0,
+                          0,
+                          attrlistlen,
+                          attrlist,
+                          &attrauthlen,
+                          &attrauth);
+    }
+#endif
+
+
+    /*----------------------------------------*/
+    /* Allocate buffer for the SrvReg Message */
+    /*----------------------------------------*/
+    bufsize = 14 + langtaglen;  /* 14 bytes for header    */
+    bufsize += urllen + 6;      /*  1 byte for reserved   */
+                                /*  2 bytes for lifetime  */
+                                /*  2 bytes for urllen    */
+                                /*  1 byte for authcount  */
+    bufsize += srvtypelen + 2;  /*  2 bytes for len field */
+    bufsize += scopelistlen + 2;/*  2 bytes for len field */
+    bufsize += attrlistlen + 2; /*  2 bytes for len field */
+    bufsize += 1;               /*  1 byte for authcount  */
+    #ifdef ENABLE_SLPv2_SECURITY
+    bufsize += urlauthlen;
+    bufsize += attrauthlen;
+    #endif  
+    *buf = SLPBufferAlloc(bufsize);
+    if(*buf == 0)
+    {
+        result = SLP_ERROR_INTERNAL_ERROR;
+        goto CLEANUP;
+    }
+    
+    /*------------------------------*/
+    /* Now build the SrvReg Message */
+    /*------------------------------*/
+    /*version*/
+    *((*buf)->start)       = 2;
+    /*function id*/
+    *((*buf)->start + 1)   = SLP_FUNCT_SRVREG;
+    /*length*/
+    ToUINT24((*buf)->start + 2, bufsize);
+    /*flags*/
+    ToUINT16((*buf)->start + 5, 0);
+    /*ext offset*/
+    ToUINT24((*buf)->start + 7,0);
+    /*xid*/
+    ToUINT16((*buf)->start + 10, 0);
+    /*lang tag len*/
+    ToUINT16((*buf)->start + 12,langtaglen);
+    /*lang tag*/
+    memcpy((*buf)->start + 14, langtag, langtaglen);
+    (*buf)->curpos = (*buf)->start + langtaglen + 14 ;
+    /* url-entry reserved */
+    *(*buf)->curpos= 0;        
+    (*buf)->curpos = (*buf)->curpos + 1;
+    /* url-entry lifetime */
+    ToUINT16((*buf)->curpos,lifetime);
+    (*buf)->curpos = (*buf)->curpos + 2;
+    /* url-entry urllen */
+    ToUINT16((*buf)->curpos,urllen);
+    (*buf)->curpos = (*buf)->curpos + 2;
+    /* url-entry url */
+    memcpy((*buf)->curpos,url,urllen);
+    (*buf)->curpos = (*buf)->curpos + urllen;
+    /* url-entry authblock */
+#ifdef ENABLE_SLPv2_SECURITY
+    if(urlauth)
+    {
+        /* authcount */
+        *(*buf)->curpos = 1;
+        (*buf)->curpos = (*buf)->curpos + 1;
+        /* authblock */
+        memcpy((*buf)->curpos,urlauth,urlauthlen);
+        (*buf)->curpos = (*buf)->curpos + urlauthlen;
+    }
+    else
+#endif
+    {
+        /* authcount */
+        *(*buf)->curpos = 0;
+        (*buf)->curpos += 1;
+    } 
+    /* service type */
+    ToUINT16((*buf)->curpos,srvtypelen);
+    (*buf)->curpos = (*buf)->curpos + 2;
+    memcpy((*buf)->curpos,srvtype,srvtypelen);
+    (*buf)->curpos = (*buf)->curpos + srvtypelen;
+    /* scope list */
+    ToUINT16((*buf)->curpos,scopelistlen);
+    (*buf)->curpos = (*buf)->curpos + 2;
+    memcpy((*buf)->curpos,scopelist,scopelistlen);
+    (*buf)->curpos = (*buf)->curpos + scopelistlen;
+    /* attr list */
+    ToUINT16((*buf)->curpos,attrlistlen);
+    (*buf)->curpos = (*buf)->curpos + 2;
+    memcpy((*buf)->curpos,attrlist,attrlistlen);
+    (*buf)->curpos = (*buf)->curpos + attrlistlen;
+    /* attribute auth block */
+#ifdef ENABLE_SLPv2_SECURITY
+    if(attrauth)
+    {
+        /* authcount */
+        *(*buf)->curpos = 1;
+        (*buf)->curpos = (*buf)->curpos + 1;
+        /* authblock */
+        memcpy((*buf)->curpos,attrauth,attrauthlen);
+        (*buf)->curpos = (*buf)->curpos + attrauthlen;
+    }
+    else
+#endif
+    {
+        /* authcount */
+        *(*buf)->curpos = 0;
+        (*buf)->curpos = (*buf)->curpos + 1;
+    }
+
+    /*------------------------------------------------*/
+    /* Ok Now comes the really stupid (and lazy part) */
+    /*------------------------------------------------*/
+    *msg = SLPMessageAlloc();
+    if(*msg == 0)
+    {
+        SLPBufferFree(*buf);
+        *buf=0;
+        result = SLP_ERROR_INTERNAL_ERROR;
+        goto CLEANUP;
+    }
+    peer.sin_addr.s_addr = htonl(LOOPBACK_ADDRESS);
+    result = SLPMessageParseBuffer(&peer,*buf,*msg);
+    (*msg)->body.srvreg.source = source;
+    
+    
+CLEANUP:
+#ifdef ENABLE_SLPv2_SECURITY
+    if(urlauth) xfree(urlauth);
+    if(attrauth) xfree(attrauth);
+#endif
+
+    return result;
+}
+
+
+/*=========================================================================*/
+int SLPDRegFileReadSrvReg(FILE* fd,
+			  int source,
+                          SLPMessage* msg,
+                          SLPBuffer* buf)
+/* A really big and nasty function that reads an service registration from */
+/* from a file.                                                            */
 /*                                                                         */
 /* fd       (IN) file to read from                                         */
 /*                                                                         */
+/* source   (IN) registration type (SLP_REG_SOURCE_STATIC)                 */
+/*                                                                         */
 /* msg      (OUT) message describing the SrvReg in buf                     */
 /*                                                                         */
 /* buf      (OUT) buffer containing the SrvReg                             */
@@ -156,9 +350,7 @@ int SLPDRegFileReadSrvReg(FILE* fd,
     char*   p;
     char    line[4096];
     
-    struct  sockaddr_in     peer;
     int     result          = 0;
-    int     bufsize         = 0;
     int     langtaglen      = 0;
     char*   langtag         = 0;
     int     scopelistlen    = 0;
@@ -170,14 +362,9 @@ int SLPDRegFileReadSrvReg(FILE* fd,
     char*   srvtype         = 0;
     int     attrlistlen     = 0;
     char*   attrlist        = 0;
-#ifdef ENABLE_SLPv2_SECURITY
-    unsigned char*  urlauth         = 0;
-    int             urlauthlen      = 0;
-    unsigned char*  attrauth        = 0;
-    int             attrauthlen     = 0;
-#endif
-    int	    watchport = 0;
-    int	    watchflags = 0;
+    int	    watchport       = 0;
+    int	    watchflags      = 0;
+    char*   peerip          = 0;
     
     
     /*-------------------------------------------*/
@@ -217,14 +404,17 @@ int SLPDRegFileReadSrvReg(FILE* fd,
         }
 
 	/* replace "$HOSTNAME" string in url */
-	while ((p = strchr(url, '$')) && !strncmp(p, "$HOSTNAME", 9))
+	if (source == SLP_REG_SOURCE_STATIC)
 	{
-	    char *_url = (char*)malloc(strlen(url) - 9 + G_SlpdProperty.myHostnameLen + 1);
-	    strncpy(_url, url, p - url);
-	    strncpy(_url + (p - url), G_SlpdProperty.myHostname, G_SlpdProperty.myHostnameLen);
-	    strcpy(_url + (p - url) + G_SlpdProperty.myHostnameLen, url + (p - url) + 9);
-	    free(url);
-	    url = _url;
+	    while ((p = strchr(url, '$')) && !strncmp(p, "$HOSTNAME", 9))
+	    {
+		char *_url = (char*)malloc(strlen(url) - 9 + G_SlpdProperty.myHostnameLen + 1);
+		strncpy(_url, url, p - url);
+		strncpy(_url + (p - url), G_SlpdProperty.myHostname, G_SlpdProperty.myHostnameLen);
+		strcpy(_url + (p - url) + G_SlpdProperty.myHostnameLen, url + (p - url) + 9);
+		free(url);
+		url = _url;
+	    }
 	}
         urllen = strlen(url);
 
@@ -310,6 +500,7 @@ int SLPDRegFileReadSrvReg(FILE* fd,
     /*-------------------------------------------------*/
     /* Read all the attributes including the scopelist */
     /*-------------------------------------------------*/
+    
     *line=0;
     while(1)
     {
@@ -363,6 +554,15 @@ int SLPDRegFileReadSrvReg(FILE* fd,
                 }
             }
         }
+        else if(strncasecmp(slider1,"slp-source",10) == 0 && source != SLP_REG_SOURCE_STATIC)
+	{
+	    slider2 = strchr(slider1,'=');
+	    if(slider2)
+	    {
+                slider2++;
+		peerip=xstrdup(TrimWhitespace(slider2));
+	    }
+	}
         else if(strncasecmp(slider1,"tcp-port",8) == 0 || strncasecmp(slider1,"watch-port-tcp",14) == 0)
 	{
             slider2 = strchr(slider1,'=');
@@ -407,7 +607,7 @@ int SLPDRegFileReadSrvReg(FILE* fd,
 	    
 	    /* we need special case for keywords (why do we need these)   */
 	    /* they seem like a waste of code.  Why not just use booleans */
-	    if(strchr(slider1,'='))
+	    if(strchr(slider1,'=') && source == SLP_REG_SOURCE_STATIC)
 	    {
 	        /* normal attribute (with '=') */
 	        strcat(attrlist,"(");
@@ -436,157 +636,26 @@ int SLPDRegFileReadSrvReg(FILE* fd,
         scopelistlen = G_SlpdProperty.useScopesLen;
     }
 
- 
-#ifdef ENABLE_SLPv2_SECURITY
-    /*--------------------------------*/
-    /* Generate authentication blocks */
-    /*--------------------------------*/
-    if(G_SlpdProperty.securityEnabled)
-    {
-        
-        SLPAuthSignUrl(G_SlpdSpiHandle,
-                       0,
-                       0,
-                       urllen,
-                       url,
-                       &urlauthlen,
-                       &urlauth);
-    
-        SLPAuthSignString(G_SlpdSpiHandle,
-                          0,
-                          0,
-                          attrlistlen,
-                          attrlist,
-                          &attrauthlen,
-                          &attrauth);
-    }
-#endif
-
+    result = SLPDCreateSrvReg(source, urllen, url, langtaglen, langtag, srvtypelen, srvtype, scopelistlen, scopelist, attrlistlen, attrlist, lifetime, msg, buf);
+    if (result)
+	goto CLEANUP;
 
-    /*----------------------------------------*/
-    /* Allocate buffer for the SrvReg Message */
-    /*----------------------------------------*/
-    bufsize = 14 + langtaglen;  /* 14 bytes for header    */
-    bufsize += urllen + 6;      /*  1 byte for reserved   */
-                                /*  2 bytes for lifetime  */
-                                /*  2 bytes for urllen    */
-                                /*  1 byte for authcount  */
-    bufsize += srvtypelen + 2;  /*  2 bytes for len field */
-    bufsize += scopelistlen + 2;/*  2 bytes for len field */
-    bufsize += attrlistlen + 2; /*  2 bytes for len field */
-    bufsize += 1;               /*  1 byte for authcount  */
-    #ifdef ENABLE_SLPv2_SECURITY
-    bufsize += urlauthlen;
-    bufsize += attrauthlen;
-    #endif  
-    *buf = SLPBufferAlloc(bufsize);
-    if(*buf == 0)
-    {
-        result = SLP_ERROR_INTERNAL_ERROR;
-        goto CLEANUP;
-    }
-    
-    /*------------------------------*/
-    /* Now build the SrvReg Message */
-    /*------------------------------*/
-    /*version*/
-    *((*buf)->start)       = 2;
-    /*function id*/
-    *((*buf)->start + 1)   = SLP_FUNCT_SRVREG;
-    /*length*/
-    ToUINT24((*buf)->start + 2, bufsize);
-    /*flags*/
-    ToUINT16((*buf)->start + 5, 0);
-    /*ext offset*/
-    ToUINT24((*buf)->start + 7,0);
-    /*xid*/
-    ToUINT16((*buf)->start + 10, 0);
-    /*lang tag len*/
-    ToUINT16((*buf)->start + 12,langtaglen);
-    /*lang tag*/
-    memcpy((*buf)->start + 14, langtag, langtaglen);
-    (*buf)->curpos = (*buf)->start + langtaglen + 14 ;
-    /* url-entry reserved */
-    *(*buf)->curpos= 0;        
-    (*buf)->curpos = (*buf)->curpos + 1;
-    /* url-entry lifetime */
-    ToUINT16((*buf)->curpos,lifetime);
-    (*buf)->curpos = (*buf)->curpos + 2;
-    /* url-entry urllen */
-    ToUINT16((*buf)->curpos,urllen);
-    (*buf)->curpos = (*buf)->curpos + 2;
-    /* url-entry url */
-    memcpy((*buf)->curpos,url,urllen);
-    (*buf)->curpos = (*buf)->curpos + urllen;
-    /* url-entry authblock */
-#ifdef ENABLE_SLPv2_SECURITY
-    if(urlauth)
-    {
-        /* authcount */
-        *(*buf)->curpos = 1;
-        (*buf)->curpos = (*buf)->curpos + 1;
-        /* authblock */
-        memcpy((*buf)->curpos,urlauth,urlauthlen);
-        (*buf)->curpos = (*buf)->curpos + urlauthlen;
-    }
-    else
-#endif
-    {
-        /* authcount */
-        *(*buf)->curpos = 0;
-        (*buf)->curpos += 1;
-    } 
-    /* service type */
-    ToUINT16((*buf)->curpos,srvtypelen);
-    (*buf)->curpos = (*buf)->curpos + 2;
-    memcpy((*buf)->curpos,srvtype,srvtypelen);
-    (*buf)->curpos = (*buf)->curpos + srvtypelen;
-    /* scope list */
-    ToUINT16((*buf)->curpos,scopelistlen);
-    (*buf)->curpos = (*buf)->curpos + 2;
-    memcpy((*buf)->curpos,scopelist,scopelistlen);
-    (*buf)->curpos = (*buf)->curpos + scopelistlen;
-    /* attr list */
-    ToUINT16((*buf)->curpos,attrlistlen);
-    (*buf)->curpos = (*buf)->curpos + 2;
-    memcpy((*buf)->curpos,attrlist,attrlistlen);
-    (*buf)->curpos = (*buf)->curpos + attrlistlen;
-    /* attribute auth block */
-#ifdef ENABLE_SLPv2_SECURITY
-    if(attrauth)
-    {
-        /* authcount */
-        *(*buf)->curpos = 1;
-        (*buf)->curpos = (*buf)->curpos + 1;
-        /* authblock */
-        memcpy((*buf)->curpos,attrauth,attrauthlen);
-        (*buf)->curpos = (*buf)->curpos + attrauthlen;
-    }
-    else
-#endif
+    if (source == SLP_REG_SOURCE_STATIC)
     {
-        /* authcount */
-        *(*buf)->curpos = 0;
-        (*buf)->curpos = (*buf)->curpos + 1;
+	(*msg)->body.srvreg.watchflags = watchflags ? (watchflags | SLP_REG_WATCH_DEAD) : 0;
+	(*msg)->body.srvreg.watchport = watchport;
     }
-
-    /*------------------------------------------------*/
-    /* Ok Now comes the really stupid (and lazy part) */
-    /*------------------------------------------------*/
-    *msg = SLPMessageAlloc();
-    if(*msg == 0)
+    if (peerip && source != SLP_REG_SOURCE_STATIC)
     {
-        SLPBufferFree(*buf);
-        *buf=0;
-        result = SLP_ERROR_INTERNAL_ERROR;
-        goto CLEANUP;
+	if (!strncmp(peerip, "pulled-from-da-", 15)) {
+	    inet_aton(peerip + 15, &(*msg)->peer.sin_addr);
+	    (*msg)->body.srvreg.source = SLP_REG_SOURCE_PULL_PEER_DA;
+	} else if (!strcmp(peerip, "local")) {
+	    (*msg)->body.srvreg.source = SLP_REG_SOURCE_LOCAL;
+	} else {
+	    inet_aton(peerip, &(*msg)->peer.sin_addr);
+	}
     }
-    peer.sin_addr.s_addr = htonl(LOOPBACK_ADDRESS);
-    result = SLPMessageParseBuffer(&peer,*buf,*msg);
-    (*msg)->body.srvreg.source = SLP_REG_SOURCE_STATIC;
-    (*msg)->body.srvreg.watchflags = watchflags ? (watchflags | SLP_REG_WATCH_DEAD) : 0;
-    (*msg)->body.srvreg.watchport = watchport;
-    
     
 CLEANUP:
     
@@ -612,11 +681,39 @@ CLEANUP:
     if(scopelist) xfree(scopelist);
     if(url) xfree(url);
     if(srvtype) xfree(srvtype);
-    if(attrlist)xfree(attrlist);
-#ifdef ENABLE_SLPv2_SECURITY
-    if(urlauth) xfree(urlauth);
-    if(attrauth) xfree(attrauth);
-#endif
+    if(attrlist) xfree(attrlist);
+    if(peerip) xfree(peerip);
 
     return result;
 }
+
+/*=========================================================================*/
+int SLPDRegFileWriteSrvReg(FILE* fd,
+                           SLPMessage msg)
+/* Write a service registration to a file                                  */
+/*                                                                         */
+/* fd       (IN) file to write to                                          */
+/*                                                                         */
+/* msg      (in) message describing the SrvReg                             */
+/*                                                                         */
+/*=========================================================================*/
+{
+    int result = 0;
+    if (fd)
+    {
+	fprintf(fd, "%s,%s,%d\n", msg->body.srvreg.urlentry.url, msg->header.langtag, msg->body.srvreg.urlentry.lifetime);
+	if (msg->body.srvreg.source == SLP_REG_SOURCE_PULL_PEER_DA)
+	    fprintf(fd, "slp-source=pulled-from-da-%s\n", inet_ntoa(msg->peer.sin_addr));
+	else if (msg->body.srvreg.source == SLP_REG_SOURCE_LOCAL)
+	    fprintf(fd, "slp-source=local\n");
+	else
+	    fprintf(fd, "slp-source=%s\n", inet_ntoa(msg->peer.sin_addr));
+	if (msg->body.srvreg.scopelistlen)
+	    fprintf(fd, "scopes=%.*s\n", msg->body.srvreg.scopelistlen, msg->body.srvreg.scopelist);
+	if(msg->body.srvreg.attrlistlen)
+	    fprintf(fd, "%.*s\n", msg->body.srvreg.attrlistlen, msg->body.srvreg.attrlist);
+	fprintf(fd, "\n");
+    }
+    return result;
+}
+
--- ./slpd/slpd_regfile.h.orig	2001-05-10 15:04:19.000000000 +0000
+++ ./slpd/slpd_regfile.h	2010-09-30 10:43:08.522049000 +0000
@@ -61,18 +61,42 @@
 
 
 /*=========================================================================*/
-int SLPDRegFileReadSrvReg(FILE* fd,
-                          SLPMessage* msg,
-                          SLPBuffer* buf);
-/* A really big and nasty function that reads an service registration from */
-/* from a file. Don't look at this too hard or you'll be sick.  This is by */
+int SLPDCreateSrvReg(int     source,
+                     int     urllen,
+                     char*   url,
+                     int     langtaglen,
+                     char*   langtag,
+                     int     srvtypelen,
+                     char*   srvtype,
+                     int     scopelistlen,
+                     char*   scopelist,
+                     int     attrlistlen,
+                     char*   attrlist,
+                     int     lifetime,
+                     SLPMessage* msg,
+                     SLPBuffer* buf);
+/* Create a SrcReg Message from given data.                                */
+/* Don't look at this too hard or you'll be sick.  This is by far          */
 /* the most horrible code in OpenSLP.  Please volunteer to rewrite it!     */
 /*                                                                         */
 /*  "THANK GOODNESS this function is only called at startup" -- Matt       */
 /*                                                                         */
+/* Note:    Eventually the caller needs to call SLPBufferFree() and        */
+/*          SLPMessageFree() to free memory                                */
+/*=========================================================================*/
+
+/*=========================================================================*/
+int SLPDRegFileReadSrvReg(FILE* fd,
+                          int source,
+                          SLPMessage* msg,
+                          SLPBuffer* buf);
+/* A really big and nasty function that reads an service registration from */
+/* from a file.                                                            */
 /*                                                                         */
 /* fd       (IN) file to read from                                         */
 /*                                                                         */
+/* source   (IN) registration type (SLP_REG_SOURCE_STATIC)                 */
+/*                                                                         */
 /* msg      (OUT) message describing the SrvReg in buf                     */
 /*                                                                         */
 /* buf      (OUT) buffer containing the SrvReg                             */
@@ -83,5 +107,16 @@ int SLPDRegFileReadSrvReg(FILE* fd,
 /*          SLPMessageFree() to free memory                                */
 /*=========================================================================*/
 
+/*=========================================================================*/
+int SLPDRegFileWriteSrvReg(FILE* fd, 
+                           SLPMessage msg);
+/* Write a service registration to a file                                  */
+/*                                                                         */
+/* fd       (IN) file to write to                                          */
+/*                                                                         */
+/* msg      (in) message describing the SrvReg                             */
+/*                                                                         */
+/*=========================================================================*/
+
 
 #endif