1 /*-------------------------------------------------------------------------
2  * Copyright (C) 2000 Caldera Systems, Inc
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *    Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *    Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  *    Neither the name of Caldera Systems nor the names of its
17  *    contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA
24  * SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *-------------------------------------------------------------------------*/
32 
33 /** Keeps track of known DA's.
34  *
35  * @file       slpd_knownda.c
36  * @author     Matthew Peterson, John Calcote (jcalcote@novell.com)
37  * @attention  Please submit patches to http://www.openslp.org
38  * @ingroup    SlpdCode
39  */
40 
41 #include "slpd_knownda.h"
42 #include "slpd_property.h"
43 #include "slpd_database.h"
44 #include "slpd_socket.h"
45 #include "slpd_outgoing.h"
46 #include "slpd_log.h"
47 #include "slpd.h"
48 #include "slpd_incoming.h"  /*For the global incoming socket map.  Instead of creating a new
49                               socket for every multicast and broadcast, we'll simply send
50                               on the existing sockets, using their network interfaces*/
51 
52 #ifdef ENABLE_SLPv2_SECURITY
53 # include "slpd_spi.h"
54 #endif
55 
56 #include "slp_xmalloc.h"
57 #include "slp_v1message.h"
58 #include "slp_utf8.h"
59 #include "slp_compare.h"
60 #include "slp_xid.h"
61 #include "slp_dhcp.h"
62 #include "slp_parse.h"
63 #include "slp_net.h"
64 
65 #ifdef ENABLE_SLPv2_SECURITY
66 # include "slp_auth.h"
67 # include "slp_spi.h"
68 #endif
69 
70 /*=========================================================================*/
71 SLPDatabase G_SlpdKnownDAs;
72 /* The database of DAAdverts from DAs known to slpd.                       */
73 /*=========================================================================*/
74 
75 /*=========================================================================*/
76 int G_KnownDATimeSinceLastRefresh = 0;
77 /*=========================================================================*/
78 
79 /*=========================================================================*/
80 char* G_ifaceurls = 0;
81 size_t G_ifaceurlsLen = 0;
82 /* Used to filter out our own DA urls */
83 /*=========================================================================*/
84 
85 /*-------------------------------------------------------------------------*/
MakeActiveDiscoveryRqst(int ismcast,SLPBuffer * buffer)86 int MakeActiveDiscoveryRqst(int ismcast, SLPBuffer * buffer)
87 /* Pack a buffer with service:directory-agent SrvRqst                      *
88  *                                                                         *
89  * Caller must free buffer                                                 *
90  *-------------------------------------------------------------------------*/
91 {
92    size_t size;
93    void * eh;
94    SLPMessage * msg;
95    char * prlist = 0;
96    size_t prlistlen = 0;
97    int errorcode = 0;
98    SLPBuffer tmp = 0;
99    SLPBuffer result = *buffer;
100    char addr_str[INET6_ADDRSTRLEN];
101 
102    /*-------------------------------------------------*/
103    /* Generate a DA service request buffer to be sent */
104    /*-------------------------------------------------*/
105    /* determine the size of the fixed portion of the SRVRQST     */
106    size = 47; /* 14 bytes for the header                        */
107    /*  2 bytes for the prlistlen                     */
108    /*  2 bytes for the srvtype length                */
109    /* 23 bytes for "service:directory-agent" srvtype */
110    /*  2 bytes for scopelistlen                      */
111    /*  2 bytes for predicatelen                      */
112    /*  2 bytes for sprstrlen                         */
113 
114    /* figure out what our Prlist will be by going through our list of  */
115    /* known DAs                                                        */
116    prlistlen = 0;
117    prlist = xmalloc(G_SlpdProperty.MTU - size);
118    if (prlist == 0)
119    {
120       /* out of memory */
121       errorcode = SLP_ERROR_INTERNAL_ERROR;
122       goto FINISHED;
123    }
124 
125    *prlist = 0;
126    /* Don't send active discoveries to DAs we already know about */
127    eh = SLPDKnownDAEnumStart();
128    if (eh)
129    {
130       while (1)
131       {
132          size_t addrstrlen;
133 
134          if (SLPDKnownDAEnum(eh, &msg, &tmp) == 0)
135             break;
136          /*Make sure we have room for the potential pr addr*/
137          if(G_SlpdProperty.MTU - size < prlistlen + sizeof(addr_str) + 1) /*1 for the comma*/
138             break;
139 
140          *addr_str = 0;
141          SLPNetSockAddrStorageToString(&(msg->peer), addr_str,
142                      sizeof(addr_str));
143          addrstrlen = strlen(addr_str);
144          if (addrstrlen > 0 && SLPContainsStringList(prlistlen,
145                      prlist, addrstrlen, addr_str) == 0)
146          {
147             if (prlistlen != 0)
148                strcat(prlist, ",");
149             strcat(prlist, addr_str);
150             prlistlen = strlen(prlist);
151          }
152       }
153 
154       SLPDKnownDAEnumEnd(eh);
155    }
156 
157    /* Allocate the send buffer */
158    size += G_SlpdProperty.localeLen + prlistlen;
159    result = SLPBufferRealloc(result, size);
160    if (result == 0)
161    {
162       /* out of memory */
163       errorcode = SLP_ERROR_INTERNAL_ERROR;
164       goto FINISHED;
165    }
166 
167    /*------------------------------------------------------------*/
168    /* Build a buffer containing the fixed portion of the SRVRQST */
169    /*------------------------------------------------------------*/
170 
171    /* version */
172    *result->curpos++ = 2;
173 
174    /* function id */
175    *result->curpos++ = SLP_FUNCT_SRVRQST;
176 
177    /* length */
178    PutUINT24(&result->curpos, size);
179 
180    /* flags */
181    PutUINT16(&result->curpos, (ismcast ? SLP_FLAG_MCAST : 0));
182 
183    /* ext offset */
184    PutUINT24(&result->curpos, 0);
185 
186    /* xid */
187    PutUINT16(&result->curpos, SLPXidGenerate());
188 
189    /* lang tag len */
190    PutUINT16(&result->curpos, G_SlpdProperty.localeLen);
191 
192    /* lang tag */
193    memcpy(result->curpos, G_SlpdProperty.locale, G_SlpdProperty.localeLen);
194    result->curpos += G_SlpdProperty.localeLen;
195 
196    /* Prlist */
197    PutUINT16(&result->curpos, prlistlen);
198    memcpy(result->curpos, prlist, prlistlen);
199    result->curpos += prlistlen;
200 
201    /* service type */
202    PutUINT16(&result->curpos, 23);
203 
204    /* 23 is the length of SLP_DA_SERVICE_TYPE */
205    memcpy(result->curpos, SLP_DA_SERVICE_TYPE, 23);
206    result->curpos += 23;
207 
208    /* scope list zero length */
209    PutUINT16(&result->curpos, 0);
210 
211    /* predicate zero length */
212    PutUINT16(&result->curpos, 0);
213 
214    /* spi list zero length */
215    PutUINT16(&result->curpos, 0);
216 
217    *buffer = result;
218 
219 FINISHED:
220 
221    if (prlist)
222       xfree(prlist);
223 
224    /** TODO: incorporate errorcode into return value. */
225    (void)errorcode;
226 
227    return 0;
228 }
229 
230 
231 /*-------------------------------------------------------------------------*/
SLPDKnownDARegisterAll(SLPMessage * daadvert,int immortalonly)232 void SLPDKnownDARegisterAll(SLPMessage * daadvert, int immortalonly)
233 /* registers all services with specified DA                                */
234 /*-------------------------------------------------------------------------*/
235 {
236    SLPBuffer buf;
237    SLPMessage * msg;
238    SLPSrvReg * srvreg;
239    SLPDSocket * sock;
240    SLPBuffer sendbuf = 0;
241    void * handle = 0;
242 
243    /*---------------------------------------------------------------*/
244    /* Check to see if the database is empty and open an enumeration */
245    /* handle if it is not empty                                     */
246    /*---------------------------------------------------------------*/
247    if (SLPDDatabaseIsEmpty())
248       return;
249 
250    /*--------------------------------------*/
251    /* Never do a Register All to ourselves */
252    /*--------------------------------------*/
253    if(SLPIntersectStringList(G_ifaceurlsLen, G_ifaceurls, daadvert->body.daadvert.urllen,
254                              daadvert->body.daadvert.url) > 0)
255       return;
256 
257    handle = SLPDDatabaseEnumStart();
258    if (handle == 0)
259       return;
260 
261    /*----------------------------------------------*/
262    /* Establish a new connection with the known DA */
263    /*----------------------------------------------*/
264    sock = SLPDOutgoingConnect(0, &(daadvert->peer));
265    if (sock)
266       while (1)
267       {
268          msg = SLPDDatabaseEnum(handle, &msg, &buf);
269          if (msg == NULL)
270             break;
271          srvreg = &(msg->body.srvreg);
272 
273          /*-----------------------------------------------*/
274          /* If so instructed, skip mortal registrations   */
275          /*-----------------------------------------------*/
276          if (immortalonly && srvreg->urlentry.lifetime < SLP_LIFETIME_MAXIMUM)
277             continue;
278 
279          /*---------------------------------------------------------*/
280          /* Only register local (or static) registrations of scopes */
281          /* supported by peer DA                                    */
282          /*---------------------------------------------------------*/
283          if ((srvreg->source == SLP_REG_SOURCE_LOCAL
284                || srvreg->source == SLP_REG_SOURCE_STATIC)
285                && SLPIntersectStringList(srvreg->scopelistlen,
286                                          srvreg->scopelist,
287                                          daadvert->body.daadvert.scopelistlen,
288                                          daadvert->body.daadvert.scopelist))
289          {
290             sendbuf = SLPBufferDup(buf);
291             if (sendbuf)
292             {
293                /*--------------------------------------------------------------*/
294                /* link newly constructed buffer to socket resendlist, and send */
295                /*--------------------------------------------------------------*/
296                SLPListLinkTail(&(sock->sendlist), (SLPListItem *) sendbuf);
297                SLPDOutgoingDatagramWrite(sock, sendbuf);
298             }
299          }
300       }
301 
302    SLPDDatabaseEnumEnd(handle);
303 }
304 
305 
306 /*-------------------------------------------------------------------------*/
307 /* Pack a buffer with a SrvDereg message using information from an existing
308  * SrvReg message
309  *
310  * Caller must free outbuf
311  *-------------------------------------------------------------------------*/
MakeSrvderegFromSrvReg(SLPMessage * msg,SLPBuffer inbuf,SLPBuffer * outbuf)312 int MakeSrvderegFromSrvReg(SLPMessage * msg, SLPBuffer inbuf, SLPBuffer * outbuf)
313 {
314    size_t size;
315    SLPBuffer sendbuf;
316    SLPSrvReg * srvreg;
317 
318    (void)inbuf;
319 
320    srvreg = &(msg->body.srvreg);
321 
322    /*-------------------------------------------------------------*/
323    /* ensure the buffer is big enough to handle the whole srvdereg*/
324    /*-------------------------------------------------------------*/
325    size = msg->header.langtaglen + 18; /* 14 bytes for header     */
326    /*  2 bytes for scopelen */
327    /*  see below for URLEntry */
328    /*  2 bytes for taglist len */
329    if (srvreg->urlentry.opaque)
330       size += srvreg->urlentry.opaquelen;
331    else
332    {
333       size += 6; /* +6 for the static portion of the url-entry */
334       size += srvreg->urlentry.urllen;
335    }
336    size += srvreg->scopelistlen;
337    /* taglistlen is always 0 */
338 
339    *outbuf = sendbuf = SLPBufferAlloc(size);
340    if (*outbuf == NULL)
341       return SLP_ERROR_INTERNAL_ERROR;
342 
343    /*----------------------*/
344    /* Construct a SrvDereg */
345    /*----------------------*/
346 
347    /* version */
348    *sendbuf->curpos++ = 2;
349 
350    /* function id */
351    *sendbuf->curpos++ = SLP_FUNCT_SRVDEREG;
352 
353    /* length */
354    PutUINT24(&sendbuf->curpos, size);
355 
356    /* flags */
357    PutUINT16(&sendbuf->curpos, (size > (size_t)G_SlpdProperty.MTU?
358          SLP_FLAG_OVERFLOW: 0));
359 
360    /* ext offset */
361    PutUINT24(&sendbuf->curpos, 0);
362 
363    /* xid */
364    PutUINT16(&sendbuf->curpos, SLPXidGenerate());
365 
366    /* lang tag len */
367    PutUINT16(&sendbuf->curpos, msg->header.langtaglen);
368 
369    /* lang tag */
370    memcpy(sendbuf->curpos, msg->header.langtag, msg->header.langtaglen);
371    sendbuf->curpos += msg->header.langtaglen;
372 
373    /* scope list */
374    PutUINT16(&sendbuf->curpos, srvreg->scopelistlen);
375    memcpy(sendbuf->curpos, srvreg->scopelist, srvreg->scopelistlen);
376    sendbuf->curpos += srvreg->scopelistlen;
377 
378    /* the URL entry */
379 #ifdef ENABLE_SLPv1
380    if (srvreg->urlentry.opaque == 0)
381    {
382       /* url-entry reserved */
383       *sendbuf->curpos++ = 0;
384 
385       /* url-entry lifetime */
386       PutUINT16(&sendbuf->curpos, srvreg->urlentry.lifetime);
387 
388       /* url-entry urllen */
389       PutUINT16(&sendbuf->curpos, srvreg->urlentry.urllen);
390 
391       /* url-entry url */
392       memcpy(sendbuf->curpos, srvreg->urlentry.url, srvreg->urlentry.urllen);
393       sendbuf->curpos += srvreg->urlentry.urllen;
394 
395       /* url-entry authcount */
396       *sendbuf->curpos++ = 0;
397    }
398    else
399 #endif /* ENABLE_SLPv1 */
400    {
401       memcpy(sendbuf->curpos, srvreg->urlentry.opaque,
402             srvreg->urlentry.opaquelen);
403       sendbuf->curpos += srvreg->urlentry.opaquelen;
404    }
405 
406    /* taglist (always 0) */
407    PutUINT16(&sendbuf->curpos, 0);
408 
409    return 0;
410 }
411 
412 
413 /*-------------------------------------------------------------------------*/
SLPDKnownDADeregisterAll(SLPMessage * daadvert)414 void SLPDKnownDADeregisterAll(SLPMessage * daadvert)
415 /* de-registers all services with specified DA                             */
416 /*-------------------------------------------------------------------------*/
417 {
418    SLPBuffer buf;
419    SLPMessage * msg;
420    SLPSrvReg * srvreg;
421    SLPDSocket * sock;
422    SLPBuffer sendbuf = 0;
423    void * handle = 0;
424 
425    /*---------------------------------------------------------------*/
426    /* Check to see if the database is empty and open an enumeration */
427    /* handle if it is not empty                                     */
428    /*---------------------------------------------------------------*/
429    if (SLPDDatabaseIsEmpty())
430       return;
431    handle = SLPDDatabaseEnumStart();
432    if (handle == 0)
433       return;
434 
435    /* Establish a new connection with the known DA */
436    sock = SLPDOutgoingConnect(0, &(daadvert->peer));
437    if (sock)
438       while (1)
439       {
440          msg = SLPDDatabaseEnum(handle, &msg, &buf);
441          if (msg == NULL)
442             break;
443          srvreg = &(msg->body.srvreg);
444 
445         /*-----------------------------------------------------------*/
446         /* Only Deregister local (or static) registrations of scopes */
447         /* supported by peer DA                                      */
448         /*-----------------------------------------------------------*/
449         if ( ( srvreg->source == SLP_REG_SOURCE_LOCAL ||
450                srvreg->source == SLP_REG_SOURCE_STATIC ) &&
451             SLPIntersectStringList(srvreg->scopelistlen,
452                                    srvreg->scopelist,
453                                    daadvert->body.daadvert.scopelistlen,
454                                    daadvert->body.daadvert.scopelist) )
455          {
456             if (MakeSrvderegFromSrvReg(msg, buf, &sendbuf) == 0)
457             {
458                /*--------------------------------------------------------------*/
459                /* link newly constructed buffer to socket resendlist, and send */
460                /*--------------------------------------------------------------*/
461                SLPListLinkTail(&(sock->sendlist), (SLPListItem *) sendbuf);
462                SLPDOutgoingDatagramWrite(sock, sendbuf);
463             }
464          }
465       }
466 
467    SLPDDatabaseEnumEnd(handle);
468 }
469 
470 
471 /*=========================================================================*/
SLPDKnownDAFromDHCP()472 int SLPDKnownDAFromDHCP()
473 /* Queries DHCP for configured DA's.  IPv4 is the only supported address   */
474 /* family presently.                                                       */
475 /* returns  zero on success, Non-zero on failure                           */
476 /*=========================================================================*/
477 {
478    SLPBuffer buf;
479    DHCPContext ctx;
480    SLPDSocket * sock;
481    struct sockaddr_storage daaddr;
482    unsigned char * alp;
483    unsigned char             dhcpOpts[] =
484    {
485       TAG_SLP_SCOPE, TAG_SLP_DA
486    };
487 
488    *ctx.scopelist = 0;
489    ctx.addrlistlen = 0;
490 
491    DHCPGetOptionInfo(dhcpOpts, sizeof(dhcpOpts), DHCPParseSLPTags, &ctx);
492 
493    alp = ctx.addrlist;
494    while (ctx.addrlistlen >= 4)
495    {
496       memset(&daaddr, 0, sizeof(struct sockaddr_in)); /*Some platforms require sin_zero be 0*/
497       daaddr.ss_family = AF_INET;
498       memcpy(&(((struct sockaddr_in *) &daaddr)->sin_addr.s_addr), alp, 4);
499       if (&(((struct sockaddr_in *) &daaddr)->sin_addr.s_addr))
500       {
501          /*--------------------------------------------------------
502                Get an outgoing socket to the DA and set it up to make
503                the service:directoryagent request
504               --------------------------------------------------------*/
505          sock = SLPDOutgoingConnect(0, &daaddr);
506          if (sock)
507          {
508             buf = 0;
509             if (MakeActiveDiscoveryRqst(0, &buf) == 0)
510             {
511                SLPListLinkTail(&(sock->sendlist), (SLPListItem *) buf);
512                SLPDOutgoingDatagramWrite(sock, buf);
513             }
514          }
515       }
516       ctx.addrlistlen -= 4;
517       alp += 4;
518    }
519    return 0;
520 }
521 
522 /*=========================================================================*/
SLPKnownDAFromProperties()523 int SLPKnownDAFromProperties()
524 /* Queries static configuration for DA's.                                  */
525 /*                                                                         */
526 /* returns  zero on success, Non-zero on failure                           */
527 /*=========================================================================*/
528 {
529    char * temp;
530    char * tempend;
531    char * slider1;
532    char * slider2;
533    struct addrinfo * ai;
534    struct addrinfo * ai_ref;
535    struct sockaddr_storage daaddr;
536    int daaddr_isset;
537    SLPDSocket * sock;
538    SLPBuffer buf;
539 
540    if (G_SlpdProperty.DAAddresses && *G_SlpdProperty.DAAddresses)
541    {
542       temp = slider1 = xstrdup(G_SlpdProperty.DAAddresses);
543       if (temp)
544       {
545          tempend = temp + strlen(temp);
546          while (slider1 < tempend)
547          {
548             while (*slider1 && *slider1 == ' ')
549                slider1++;
550             slider2 = slider1;
551             while (*slider2 && *slider2 != ',')
552                slider2++;
553             *slider2++ = 0;
554 
555             daaddr_isset = 0;
556             if (inet_pton(AF_INET6, slider1,
557                      &((struct sockaddr_in6 *) &daaddr)->sin6_addr) > 0)
558             {
559                daaddr.ss_family = AF_INET6;
560                ((struct sockaddr_in6 *) &daaddr)->sin6_family = AF_INET6;
561                daaddr_isset = 1;
562             }
563             else if (inet_pton(AF_INET, slider1,
564                            &((struct sockaddr_in *) &daaddr)->sin_addr) > 0)
565             {
566                daaddr.ss_family = AF_INET;
567                ((struct sockaddr_in *) &daaddr)->sin_family = AF_INET;
568                daaddr_isset = 1;
569             }
570             else if (getaddrinfo(slider1, NULL, NULL, &ai) == 0)
571             {
572                ai_ref = ai;
573                while (ai_ref != NULL)
574                {
575                   if (SLPNetIsIPV6() && ai_ref->ai_addr->sa_family == AF_INET6)
576                   {
577                      memcpy(&daaddr, &ai_ref->ai_addr,
578                            sizeof(struct sockaddr_in6));
579                      daaddr_isset = 1;
580                      break;
581                      /* we prefer IPv6 when configured, so we'll take the first IPv6 address and break */
582                   }
583                   else if (SLPNetIsIPV4()
584                         && !daaddr_isset
585                         && ai_ref->ai_addr->sa_family == AF_INET)
586                   {
587                      memcpy(&daaddr, &ai_ref->ai_addr,
588                            sizeof(struct sockaddr_in));
589                      daaddr_isset = 1;
590                      /* we'll continue searching for an IPv6 address, but we'll use the first IPv4 address if none are found */
591                   }
592                   ai_ref = ai_ref->ai_next;
593                }
594 
595                freeaddrinfo(ai);
596             }
597 
598             if (daaddr_isset)
599             {
600                /*--------------------------------------------------------*/
601                /* Get an outgoing socket to the DA and set it up to make */
602                /* the service:directoryagent request                     */
603                /*--------------------------------------------------------*/
604                sock = SLPDOutgoingConnect(0, &daaddr);
605                if (sock)
606                {
607                   buf = 0;
608                   if (MakeActiveDiscoveryRqst(0, &buf) == 0)
609                   {
610                      SLPListLinkTail(&(sock->sendlist), (SLPListItem *) buf);
611                      SLPDOutgoingDatagramWrite(sock, buf);
612                   }
613                }
614             }
615             slider1 = slider2;
616          }
617          xfree(temp);
618       }
619    }
620    return 0;
621 }
622 
623 /*=========================================================================*/
SLPDKnownDAGenerateIfaceURLs()624 void SLPDKnownDAGenerateIfaceURLs()
625 /* Initializes G_ifaceurls and G_ifaceurlsLen from GSlpdProperties.ifaceInfo */
626 /* Much of this is pulled from SLPDKnownDAGenerateMyDAAdvert               */
627 /*=========================================================================*/
628 {
629    int i;
630    char localaddr_str[INET6_ADDRSTRLEN + 2];
631    struct sockaddr_storage* localaddr;
632    size_t strmax = G_SlpdProperty.ifaceInfo.iface_count * (G_SlpdProperty.urlPrefixLen + INET6_ADDRSTRLEN + 2 + 1);  /*The +1 is for the ','*/
633 
634    if(strmax)
635    {
636       ++strmax;  /*For the terminating NULL*/
637       G_ifaceurls = xmalloc(strmax);
638       if(G_ifaceurls)
639       {
640          G_ifaceurls[0] = '\0';
641          for(i = 0; i < G_SlpdProperty.ifaceInfo.iface_count; ++i)
642          {
643             /*build the ipaddr string*/
644             localaddr_str[0] = '\0';
645             localaddr = G_SlpdProperty.ifaceInfo.iface_addr + i;
646             if (localaddr->ss_family == AF_INET)
647                inet_ntop(localaddr->ss_family,
648                      &((struct sockaddr_in *) localaddr)->sin_addr, localaddr_str,
649                      sizeof(localaddr_str));
650             else if (localaddr->ss_family == AF_INET6)
651             {
652                strcpy(localaddr_str, "[");
653                inet_ntop(localaddr->ss_family,
654                      &((struct sockaddr_in6 *) localaddr)->sin6_addr,
655                      &localaddr_str[1], sizeof(localaddr_str) - 1);
656                strcat(localaddr_str, "]");
657             }
658 
659             /*Add the url to G_ifaceurls*/
660             strncat(G_ifaceurls, G_SlpdProperty.urlPrefix, G_SlpdProperty.urlPrefixLen);
661             strcat(G_ifaceurls, localaddr_str);
662             strcat(G_ifaceurls, ",");
663          }
664          G_ifaceurlsLen = strlen(G_ifaceurls);
665       }
666    }
667 }
668 
669 /*=========================================================================*/
SLPDKnownDAInit()670 int SLPDKnownDAInit()
671 /* Initializes the KnownDA list.  Removes all entries and adds entries     */
672 /* that are statically configured.  Adds entries configured through DHCP.  */
673 /*                                                                         */
674 /* returns  zero on success, Non-zero on failure                           */
675 /*=========================================================================*/
676 {
677    /*--------------------------------------*/
678    /* Set initialize the DAAdvert database */
679    /*--------------------------------------*/
680    SLPDatabaseInit(&G_SlpdKnownDAs);
681 
682    /*-----------------------------------------------------------------*/
683    /* Added statically configured DAs to the Known DA List by sending */
684    /* active DA discovery requests directly to them                   */
685    /*-----------------------------------------------------------------*/
686    SLPKnownDAFromProperties();
687 
688    /*-----------------------------------------------------------------*/
689    /* Discover DHCP DA's and add them to the active discovery list.    */
690    /*-----------------------------------------------------------------*/
691    if (G_SlpdProperty.useDHCP)
692       SLPDKnownDAFromDHCP();
693 
694    /*------------------------------------------------------------------*/
695    /* Generate the list of our URLs                                    */
696    /*------------------------------------------------------------------*/
697    SLPDKnownDAGenerateIfaceURLs();
698 
699    /*----------------------------------------*/
700    /* Lastly, Perform first active discovery */
701    /*----------------------------------------*/
702    SLPDKnownDAActiveDiscovery(0);
703 
704    return 0;
705 }
706 
707 
708 /*=========================================================================*/
SLPDKnownDADeinit()709 int SLPDKnownDADeinit()
710 /* Deinitializes the KnownDA list.  Removes all entries and deregisters    */
711 /* all services.                                                           */
712 /*                                                                         */
713 /* returns  zero on success, Non-zero on failure                           */
714 /*=========================================================================*/
715 {
716    SLPDatabaseHandle dh;
717    SLPDatabaseEntry * entry;
718    dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
719    if (dh)
720    {
721       /*------------------------------------*/
722       /* Unregister all local registrations */
723       /*------------------------------------*/
724       while (1)
725       {
726          entry = SLPDatabaseEnum(dh);
727          if (entry == NULL)
728             break;
729 
730          SLPDKnownDADeregisterAll(entry->msg);
731       }
732       SLPDatabaseClose(dh);
733    }
734 
735    SLPDatabaseDeinit(&G_SlpdKnownDAs);
736 
737    if(G_ifaceurls)
738       xfree(G_ifaceurls);
739 
740    return 0;
741 }
742 
743 
744 /*=========================================================================*/
SLPDKnownDAAdd(SLPMessage * msg,SLPBuffer buf)745 int SLPDKnownDAAdd(SLPMessage * msg, SLPBuffer buf)
746 /* Adds a DA to the known DA list if it is new, removes it if DA is going  */
747 /* down or adjusts entry if DA changed.                                    */
748 /*                                                                         */
749 /* msg     (IN) DAAdvert Message descriptor                                */
750 /*                                                                         */
751 /* buf     (IN) The DAAdvert message buffer                                */
752 /*                                                                         */
753 /* returns  Zero on success, Non-zero on error                             */
754 /*=========================================================================*/
755 {
756    SLPDatabaseEntry * entry;
757    SLPDAAdvert * entrydaadvert;
758    SLPDAAdvert * daadvert;
759    struct sockaddr_storage daaddr;
760    SLPParsedSrvUrl * parsedurl = NULL;
761    int result = 0;
762    SLPDatabaseHandle dh = NULL;
763    uint32_t saved_scope = 0;
764 
765    dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
766    if (dh == NULL)
767    {
768       result = SLP_ERROR_INTERNAL_ERROR;
769       goto CLEANUP;
770    }
771 
772    /* daadvert is the DAAdvert message being added */
773    daadvert = &(msg->body.daadvert);
774 
775 
776    /* --------------------------------------------------------
777     * Make sure that the peer address in the DAAdvert matches
778     * the host in the DA service URL.
779     *---------------------------------------------------------
780     */
781 
782    if(SLPNetIsIPV6())
783    {
784       /*We need to save the scope of the address, since a multi-nic machine
785         with multiple link-local addresses has no other way of differentiating route*/
786       saved_scope = ((struct sockaddr_in6*)&msg->peer)->sin6_scope_id;
787    }
788 
789    if (SLPParseSrvUrl(daadvert->urllen, daadvert->url, &parsedurl))
790    {
791       /* could not parse the DA service url */
792       result = SLP_ERROR_PARSE_ERROR;
793       goto CLEANUP;
794    }
795    if (SLPNetResolveHostToAddr(parsedurl->host, &daaddr))
796    {
797       /* Unable to resolve the host in the DA advert to an address */
798       xfree(parsedurl);
799       result = SLP_ERROR_PARSE_ERROR;
800       goto CLEANUP;
801    }
802    /* free the parsed url created in call to SLPParseSrvUrl() */
803    xfree(parsedurl);
804    /* set the peer address in the DAAdvert message so that it matches
805     * the address the DA service URL resolves to
806     */
807    msg->peer = daaddr;
808 
809    if(SLPNetIsIPV6())
810    {
811       /*reset the scope*/
812       ((struct sockaddr_in6*)&msg->peer)->sin6_scope_id = saved_scope;
813    }
814 
815 
816 
817    /*-----------------------------------------------------*/
818    /* Check to see if there is already an identical entry */
819    /*-----------------------------------------------------*/
820    while (1)
821    {
822       entry = SLPDatabaseEnum(dh);
823       if (entry == NULL)
824          break;
825 
826       /* entrydaadvert is the DAAdvert message from the database */
827       entrydaadvert = &(entry->msg->body.daadvert);
828 
829       /* Assume DAs are identical if their URLs match */
830       if (SLPCompareString(entrydaadvert->urllen, entrydaadvert->url,
831                daadvert->urllen, daadvert->url) == 0)
832       {
833 #ifdef ENABLE_SLPv2_SECURITY
834          if (G_SlpdProperty.checkSourceAddr)
835          {
836             if ((entry->msg->peer.ss_family == AF_INET
837                   && msg->peer.ss_family == AF_INET
838                   && memcmp(&(((struct sockaddr_in *)&entry->msg->peer)->sin_addr),
839                            &(((struct sockaddr_in *)&msg->peer)->sin_addr),
840                            sizeof(struct in_addr)))
841                   || (entry->msg->peer.ss_family == AF_INET6
842                   && msg->peer.ss_family == AF_INET6
843                   && memcmp(&(((struct sockaddr_in6 *)&entry->msg->peer)->sin6_addr),
844                            &(((struct sockaddr_in6 *)&msg->peer)->sin6_addr),
845                            sizeof(struct in6_addr))))
846             {
847                SLPDatabaseClose(dh);
848                result = SLP_ERROR_AUTHENTICATION_FAILED;
849                goto CLEANUP;
850             }
851          }
852 
853          /* make sure an unauthenticated DAAdvert can't replace */
854          /* an authenticated one                                */
855          if (entrydaadvert->authcount
856                && entrydaadvert->authcount != daadvert->authcount)
857          {
858             SLPDatabaseClose(dh);
859             result = SLP_ERROR_AUTHENTICATION_FAILED;
860             goto CLEANUP;
861          }
862 #endif
863          if (daadvert->bootstamp != 0
864                && daadvert->bootstamp != entrydaadvert->bootstamp)
865          {
866             /* Advertising DA must have went down then came back up */
867             SLPDLogDAAdvertisement("Replacement", entry);
868             SLPDKnownDARegisterAll(msg, 0);
869          }
870 
871          if ( daadvert->bootstamp == 0 )
872          {
873             /* Dying DA was found in our KnownDA database. Log that it
874              * was removed.
875              */
876             SLPDLogDAAdvertisement("Removal", entry);
877          }
878 
879          /* Remove the entry that is the same as the advertised entry */
880          /* so that we can put the new advertised entry back in       */
881          SLPDatabaseRemove(dh, entry);
882          break;
883       }
884    }
885 
886    /* Make sure the DA is not dying */
887    if (daadvert->bootstamp != 0)
888    {
889       if (entry == 0)
890       {
891          /* create a new database entry using the DAAdvert message */
892          entry = SLPDatabaseEntryCreate(msg, buf);
893          if (entry)
894          {
895             /* reset the "time to stale" count to indicate the DA is active (not stale) */
896             entry->entryvalue = G_SlpdProperty.staleDACheckPeriod / SLPD_AGE_INTERVAL;
897 
898             SLPDatabaseAdd(dh, entry);
899 
900             /* register all the services we know about with this new DA */
901             SLPDKnownDARegisterAll(msg, 0);
902 
903             /* log the addition of a new DA */
904             SLPDLogDAAdvertisement("Addition", entry);
905          }
906          else
907          {
908             /* Could not create a new entry */
909             result = SLP_ERROR_INTERNAL_ERROR;
910             goto CLEANUP;
911          }
912       }
913       else
914       {
915          /* The advertising DA is not new to us, but the old entry   */
916          /* has been deleted from our database so that the new entry */
917          /* with its up to date time stamp can be put back in.       */
918          /* create a new database entry using the DAAdvert message */
919          entry = SLPDatabaseEntryCreate(msg, buf);
920          if (entry)
921          {
922             /* reset the "time to stale" count to indicate the DA is active (not stale) */
923             entry->entryvalue = G_SlpdProperty.staleDACheckPeriod / SLPD_AGE_INTERVAL;
924 
925             SLPDatabaseAdd(dh, entry);
926          }
927          else
928          {
929             /* Could not create a new entry */
930             result = SLP_ERROR_INTERNAL_ERROR;
931             goto CLEANUP;
932          }
933       }
934    } else {
935       /* If we are here, we need to cleanup the message descriptor and the  */
936       /* message buffer because they were not added to the database and not */
937       /* cleaning them up would result in a memory leak. This is because we */
938       /* return zero, so the caller thinks it must not do the cleanup.      */
939       SLPMessageFree(msg);
940       SLPBufferFree(buf);
941    }
942 
943    CLEANUP:
944    if (dh)
945       SLPDatabaseClose(dh);
946 
947    return result;
948 }
949 
950 /*=========================================================================*/
SLPDKnownDARemove(struct sockaddr_storage * addr)951 void SLPDKnownDARemove(struct sockaddr_storage * addr)
952 /* Removes known DAs that sent DAAdverts from the specified in_addr        */
953 /*=========================================================================*/
954 {
955    SLPDatabaseHandle dh;
956    SLPDatabaseEntry * entry;
957 
958    dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
959    if (dh)
960    {
961       /*-----------------------------------------------------*/
962       /* Check to see if there is already an identical entry */
963       /*-----------------------------------------------------*/
964       while (1)
965       {
966          entry = SLPDatabaseEnum(dh);
967          if (entry == NULL)
968             break;
969 
970          /* Assume DAs are identical if their peer match */
971          if ((entry->msg->peer.ss_family == AF_INET
972               && addr->ss_family == AF_INET
973               && (0 == memcmp(&(((struct sockaddr_in *) &(entry->msg->peer))->sin_addr),
974                               &(((struct sockaddr_in *) addr)->sin_addr),
975                               sizeof(struct in_addr))))
976              || (entry->msg->peer.ss_family == AF_INET6
977                  && addr->ss_family == AF_INET6
978                  && (0 == memcmp(&(((struct sockaddr_in6 *) &(entry->msg->peer))->sin6_addr),
979                                  &(((struct sockaddr_in6 *) addr)->sin6_addr),
980                                  sizeof(struct in6_addr)))))
981          {
982             SLPDLogDAAdvertisement("Removal", entry);
983             SLPDatabaseRemove(dh, entry);
984             break;
985          }
986       }
987 
988       SLPDatabaseClose(dh);
989    }
990 }
991 
992 
993 /*=========================================================================*/
SLPDKnownDAEnumStart()994 void * SLPDKnownDAEnumStart()
995 /* Start an enumeration of all Known DAs                                   */
996 /*                                                                         */
997 /* Returns: An enumeration handle that is passed to subsequent calls to    */
998 /*          SLPDKnownDAEnum().  Returns NULL on failure.  Returned         */
999 /*          enumeration handle (if not NULL) must be passed to             */
1000 /*          SLPDKnownDAEnumEnd() when you are done with it.                */
1001 /*=========================================================================*/
1002 {
1003    return SLPDatabaseOpen(&G_SlpdKnownDAs);
1004 }
1005 
1006 
1007 /*=========================================================================*/
SLPDKnownDAEnum(void * eh,SLPMessage ** msg,SLPBuffer * buf)1008 SLPMessage * SLPDKnownDAEnum(void * eh, SLPMessage ** msg, SLPBuffer * buf)
1009 /* Enumerate through all Known DAs                                         */
1010 /*                                                                         */
1011 /* eh (IN) pointer to opaque data that is used to maintain                 */
1012 /*         enumerate entries.  Pass in a pointer to NULL to start          */
1013 /*         enumeration.                                                    */
1014 /*                                                                         */
1015 /* msg (OUT) pointer to the DAAdvert message descriptor                    */
1016 /*                                                                         */
1017 /* buf (OUT) pointer to the DAAdvert message buffer                        */
1018 /*                                                                         */
1019 /* returns: Pointer to enumerated entry or NULL if end of enumeration      */
1020 /*=========================================================================*/
1021 {
1022    SLPDatabaseEntry * entry;
1023    entry = SLPDatabaseEnum((SLPDatabaseHandle) eh);
1024    if (entry)
1025    {
1026       *msg = entry->msg;
1027       *buf = entry->buf;
1028    }
1029    else
1030    {
1031       *msg = 0;
1032       *buf = 0;
1033    }
1034 
1035    return *msg;
1036 }
1037 
1038 /*=========================================================================*/
SLPDKnownDAEnumEnd(void * eh)1039 void SLPDKnownDAEnumEnd(void * eh)
1040 /* End an enumeration started by SLPDKnownDAEnumStart()                    */
1041 /*                                                                         */
1042 /* Parameters:  eh (IN) The enumeration handle returned by                 */
1043 /*              SLPDKnownDAEnumStart()                                     */
1044 /*=========================================================================*/
1045 {
1046    if (eh)
1047       SLPDatabaseClose((SLPDatabaseHandle) eh);
1048 }
1049 
1050 /*=========================================================================*/
SLPDKnownDAGenerateMyDAAdvert(struct sockaddr_storage * localaddr,int errorcode,int deadda,int ismcast,int xid,SLPBuffer * sendbuf)1051 int SLPDKnownDAGenerateMyDAAdvert(struct sockaddr_storage * localaddr,
1052       int errorcode, int deadda, int ismcast, int xid, SLPBuffer * sendbuf)
1053 /* Pack a buffer with a DAAdvert using information from a SLPDAentry       */
1054 /*                                                                         */
1055 /* localaddr (IN) the address of the DA to advertise                       */
1056 /*                                                                         */
1057 /* errorcode (IN) the errorcode for the DAAdvert                           */
1058 /*                                                                         */
1059 /* deadda (IN) whether the DAAdvert should indicate the DA is shut down    */
1060 /*                                                                         */
1061 /* ismcast (IN) whether the mcast flag should be set for the DAAdvert      */
1062 /*                                                                         */
1063 /* xid (IN) the xid to for the DAAdvert                                    */
1064 /*                                                                         */
1065 /* daentry (IN) pointer to the daentry that contains the rest of the info  */
1066 /*              to make the DAAdvert                                       */
1067 /*                                                                         */
1068 /* sendbuf (OUT) pointer to the SLPBuffer that will be packed with a       */
1069 /*               DAAdvert                                                  */
1070 /*                                                                         */
1071 /* returns: zero on success, non-zero on error                             */
1072 /*=========================================================================*/
1073 {
1074    char localaddr_str[INET6_ADDRSTRLEN + 2];
1075    size_t size;
1076    SLPBuffer result = *sendbuf;
1077 
1078 #ifdef ENABLE_SLPv2_SECURITY
1079    int daadvertauthlen = 0;
1080    unsigned char * daadvertauth = 0;
1081    size_t spistrlen = 0;
1082    char * spistr = 0;
1083 
1084    /** @todo Use correct delay value - 1000 is just an arbitrary choice. */
1085    uint32_t expires = (uint32_t)time(0) + 1000;
1086 
1087    if (G_SlpdProperty.securityEnabled)
1088    {
1089       SLPSpiGetDefaultSPI(G_SlpdSpiHandle, SLPSPI_KEY_TYPE_PRIVATE,
1090             &spistrlen, &spistr);
1091 
1092       SLPAuthSignDAAdvert(G_SlpdSpiHandle, spistrlen, spistr,
1093             expires, G_SlpdProperty.urlPrefixLen,
1094             G_SlpdProperty.urlPrefix, 0, 0, G_SlpdProperty.useScopesLen,
1095             G_SlpdProperty.useScopes, spistrlen, spistr, &daadvertauthlen,
1096             &daadvertauth);
1097    }
1098 #endif
1099 
1100    /*-------------------------------------------------------------*/
1101    /* ensure the buffer is big enough to handle the whole srvrply */
1102    /*-------------------------------------------------------------*/
1103    size = G_SlpdProperty.localeLen + 29; /* 14 bytes for header     */
1104    /*  2 errorcode  */
1105    /*  4 bytes for timestamp */
1106    /*  2 bytes for url len */
1107    /*  2 bytes for scope list len */
1108    /*  2 bytes for attr list len */
1109    /*  2 bytes for spi str len */
1110    /*  1 byte for authblock count */
1111    size += G_SlpdProperty.urlPrefixLen;
1112    localaddr_str[0] = '\0';
1113    if (localaddr->ss_family == AF_INET)
1114       inet_ntop(localaddr->ss_family,
1115             &((struct sockaddr_in *) localaddr)->sin_addr, localaddr_str,
1116             sizeof(localaddr_str));
1117    else if (localaddr->ss_family == AF_INET6)
1118    {
1119       strcpy(localaddr_str, "[");
1120       inet_ntop(localaddr->ss_family,
1121             &((struct sockaddr_in6 *) localaddr)->sin6_addr,
1122             &localaddr_str[1], sizeof(localaddr_str) - 1);
1123       strcat(localaddr_str, "]");
1124    }
1125    size += strlen(localaddr_str);
1126    size += G_SlpdProperty.useScopesLen;
1127 #ifdef ENABLE_SLPv2_SECURITY
1128    size += spistrlen;
1129    size += daadvertauthlen;
1130 #endif
1131 
1132    result = SLPBufferRealloc(result, size);
1133    if (result == 0)
1134    {
1135       /* Out of memory, what should we do here! */
1136       errorcode = SLP_ERROR_INTERNAL_ERROR;
1137       goto FINISHED;
1138    }
1139 
1140    /*----------------*/
1141    /* Add the header */
1142    /*----------------*/
1143 
1144    /* version */
1145    *result->curpos++ = 2;
1146 
1147    /* function id */
1148    *result->curpos++ = SLP_FUNCT_DAADVERT;
1149 
1150    /* length */
1151    PutUINT24(&result->curpos, size);
1152 
1153    /* flags */
1154    PutUINT16(&result->curpos,
1155              (size > (size_t)G_SlpdProperty.MTU ? SLP_FLAG_OVERFLOW : 0) |
1156              (ismcast ? SLP_FLAG_MCAST : 0));
1157 
1158    /* ext offset */
1159    PutUINT24(&result->curpos, 0);
1160 
1161    /* xid */
1162    PutUINT16(&result->curpos, xid);
1163 
1164    /* lang tag len */
1165    PutUINT16(&result->curpos, G_SlpdProperty.localeLen);
1166 
1167    /* lang tag */
1168    memcpy(result->curpos, G_SlpdProperty.locale, G_SlpdProperty.localeLen);
1169    result->curpos += G_SlpdProperty.localeLen;
1170 
1171    /*--------------------------*/
1172    /* Add rest of the DAAdvert */
1173    /*--------------------------*/
1174 
1175    /* error code */
1176    PutUINT16(&result->curpos, errorcode);
1177    if (errorcode == 0)
1178    {
1179       /* timestamp */
1180       if (deadda)
1181          PutUINT32(&result->curpos, 0);
1182       else
1183          PutUINT32(&result->curpos, G_SlpdProperty.DATimestamp);
1184 
1185       /* url len */
1186       PutUINT16(&result->curpos, G_SlpdProperty.urlPrefixLen
1187             + strlen(localaddr_str));
1188 
1189       /* url */
1190       memcpy(result->curpos, G_SlpdProperty.urlPrefix,
1191             G_SlpdProperty.urlPrefixLen);
1192       result->curpos += G_SlpdProperty.urlPrefixLen;
1193       memcpy(result->curpos, localaddr_str, strlen(localaddr_str));
1194       result->curpos += strlen(localaddr_str);
1195 
1196       /* scope list len */
1197       PutUINT16(&result->curpos, G_SlpdProperty.useScopesLen);
1198 
1199       /* scope list */
1200       memcpy(result->curpos, G_SlpdProperty.useScopes,
1201             G_SlpdProperty.useScopesLen);
1202       result->curpos += G_SlpdProperty.useScopesLen;
1203 
1204       /* attr list len */
1205       PutUINT16(&result->curpos, 0);
1206 
1207       /* attr list */
1208       /* memcpy(result->start, ???, 0);                          */
1209       /* result->curpos = result->curpos + daentry->attrlistlen; */
1210       /* SPI List */
1211 #ifdef ENABLE_SLPv2_SECURITY
1212       PutUINT16(&result->curpos, spistrlen);
1213       memcpy(result->curpos, spistr, spistrlen);
1214       result->curpos += spistrlen;
1215 #else
1216       PutUINT16(&result->curpos, 0);
1217 #endif
1218 
1219       /* authblock count */
1220 #ifdef ENABLE_SLPv2_SECURITY
1221       if (daadvertauth)
1222       {
1223          /* authcount */
1224          *result->curpos++ = 1;
1225 
1226          /* authblock */
1227          memcpy(result->curpos, daadvertauth, daadvertauthlen);
1228          result->curpos += daadvertauthlen;
1229       }
1230       else
1231 #endif
1232          *result->curpos++ = 0;
1233    }
1234 
1235 FINISHED:
1236 
1237 #ifdef ENABLE_SLPv2_SECURITY
1238    if (daadvertauth)
1239       xfree(daadvertauth);
1240    if (spistr)
1241       xfree(spistr);
1242 #endif
1243    *sendbuf = result;
1244 
1245    return errorcode;
1246 }
1247 
1248 #if defined(ENABLE_SLPv1)
1249 /*=========================================================================*/
SLPDKnownDAGenerateMyV1DAAdvert(struct sockaddr_storage * localaddr,int errorcode,int encoding,unsigned int xid,SLPBuffer * sendbuf)1250 int SLPDKnownDAGenerateMyV1DAAdvert(struct sockaddr_storage * localaddr,
1251       int errorcode, int encoding, unsigned int xid, SLPBuffer * sendbuf)
1252 /* Pack a buffer with a v1 DAAdvert using information from a SLPDAentry    */
1253 /*                                                                         */
1254 /* localaddr (IN) the address of the DA to advertise                       */
1255 /*                                                                         */
1256 /* errorcode (IN) the errorcode for the DAAdvert                           */
1257 /*                                                                         */
1258 /* encoding (IN) the SLPv1 language encoding for the DAAdvert              */
1259 /*                                                                         */
1260 /* xid (IN) the xid to for the DAAdvert                                    */
1261 /*                                                                         */
1262 /* sendbuf (OUT) pointer to the SLPBuffer that will be packed with a       */
1263 /*               DAAdvert                                                  */
1264 /*                                                                         */
1265 /* returns: zero on success, non-zero on error                             */
1266 /*=========================================================================*/
1267 {
1268    size_t size = 0;
1269    size_t urllen = INT_MAX;
1270    size_t scopelistlen = INT_MAX;
1271    SLPBuffer result = *sendbuf;
1272    char localaddr_str[INET6_ADDRSTRLEN + 2];
1273    char da_url[INET6_ADDRSTRLEN + 29];
1274 
1275    /*-------------------------------------------------------------*/
1276    /* ensure the buffer is big enough to handle the whole srvrply */
1277    /*-------------------------------------------------------------*/
1278    size = 18; /* 12 bytes for header     */
1279    /*  2 errorcode  */
1280    /*  2 bytes for url len */
1281    /*  2 bytes for scope list len */
1282 
1283    /* Create the local address in string form */
1284    localaddr_str[0] = '\0';
1285    if (localaddr->ss_family == AF_INET)
1286       inet_ntop(localaddr->ss_family,
1287             &((struct sockaddr_in *) localaddr)->sin_addr, localaddr_str,
1288             sizeof(localaddr_str));
1289    else if (localaddr->ss_family == AF_INET6)
1290    {
1291       strcpy(localaddr_str, "[");
1292       inet_ntop(localaddr->ss_family,
1293             &((struct sockaddr_in6 *) localaddr)->sin6_addr,
1294             &localaddr_str[1], sizeof(localaddr_str) - 1);
1295       strcat(localaddr_str, "]");
1296    }
1297 
1298    /* Create the DA URL */
1299    da_url[0] = '\0';
1300    strcpy(da_url, G_SlpdProperty.urlPrefix);
1301    strcat(da_url, localaddr_str);
1302 
1303    if (!errorcode)
1304    {
1305       errorcode = SLPv1ToEncoding(0, &urllen, encoding, da_url, strlen(da_url));
1306       if (!errorcode)
1307       {
1308          size += urllen;
1309 #ifndef FAKE_UNSCOPED_DA
1310          errorcode = SLPv1ToEncoding(0, &scopelistlen, encoding,
1311                            G_SlpdProperty.useScopes,
1312                            G_SlpdProperty.useScopesLen);
1313 #else
1314          scopelistlen = 0;   /* pretend that we're unscoped */
1315 #endif
1316          if (!errorcode)
1317             size += scopelistlen;
1318       }
1319    }
1320    else
1321    {
1322       /* don't add these */
1323       urllen = scopelistlen = 0;
1324    }
1325 
1326    result = SLPBufferRealloc(result, size);
1327    if (result == 0)
1328    {
1329       /* TODO: out of memory, what should we do here! */
1330       errorcode = SLP_ERROR_INTERNAL_ERROR;
1331       goto FINISHED;
1332    }
1333 
1334    /*----------------*/
1335    /* Add the header */
1336    /*----------------*/
1337 
1338    /* version */
1339    *result->curpos++ = 1;
1340 
1341    /* function id */
1342    *result->curpos++ = SLP_FUNCT_DAADVERT;
1343 
1344    /* length */
1345    PutUINT16(&result->curpos, size);
1346 
1347    /* flags */
1348    /** @todo We have to handle monoling and all that stuff. */
1349    *result->curpos++ = (size > (size_t)G_SlpdProperty.MTU?
1350          SLPv1_FLAG_OVERFLOW: 0);
1351 
1352    /* dialect */
1353    *result->curpos++ = 0;
1354 
1355    /* language code */
1356    if (G_SlpdProperty.locale)
1357    {
1358       memcpy(result->curpos, G_SlpdProperty.locale, 2);
1359       result->curpos += 2;
1360    }
1361    PutUINT16(&result->curpos, encoding);
1362 
1363    /* xid */
1364    PutUINT16(&result->curpos, xid);
1365 
1366    /*--------------------------*/
1367    /* Add rest of the DAAdvert */
1368    /*--------------------------*/
1369 
1370    /* error code */
1371    PutUINT16(&result->curpos, errorcode);
1372 
1373    /* url len */
1374    PutUINT16(&result->curpos, urllen);
1375 
1376    /* url */
1377    SLPv1ToEncoding((char *)result->curpos, &urllen, encoding, da_url, strlen(da_url));
1378    result->curpos += urllen;
1379 
1380    /* scope list len */
1381    PutUINT16(&result->curpos, scopelistlen);
1382 
1383    /* scope list */
1384 #ifndef FAKE_UNSCOPED_DA
1385    SLPv1ToEncoding((char *)result->curpos, &scopelistlen, encoding,
1386          G_SlpdProperty.useScopes, G_SlpdProperty.useScopesLen);
1387 #endif
1388 
1389    result->curpos += scopelistlen;
1390 
1391 FINISHED:
1392 
1393    *sendbuf = result;
1394 
1395    return errorcode;
1396 }
1397 #endif
1398 
1399 /*=========================================================================*/
SLPDKnownDAEcho(SLPMessage * msg,SLPBuffer buf)1400 void SLPDKnownDAEcho(SLPMessage * msg, SLPBuffer buf)
1401 /* Echo a srvreg message to a known DA                                     */
1402 /*                                                                */
1403 /* msg (IN) the SrvReg message descriptor                                  */
1404 /*                                                                         */
1405 /* buf (IN) the SrvReg message buffer to echo                              */
1406 /*                                                                         */
1407 /* Returns:  none                                                          */
1408 /*=========================================================================*/
1409 {
1410    SLPBuffer dup;
1411    SLPDatabaseHandle dh;
1412    SLPDatabaseEntry * entry;
1413    SLPDAAdvert * entrydaadvert;
1414    SLPDSocket * sock;
1415    const char * msgscope;
1416    size_t msgscopelen;
1417 
1418    /* Do not echo registrations if we are a DA unless they were made  */
1419    /* local through the API!                                          */
1420    if (G_SlpdProperty.isDA && !SLPNetIsLocal(&(msg->peer)))
1421       return;
1422 
1423    if (msg->header.functionid == SLP_FUNCT_SRVREG)
1424    {
1425       msgscope = msg->body.srvreg.scopelist;
1426       msgscopelen = msg->body.srvreg.scopelistlen;
1427    }
1428    else if (msg->header.functionid == SLP_FUNCT_SRVDEREG)
1429    {
1430       msgscope = msg->body.srvdereg.scopelist;
1431       msgscopelen = msg->body.srvdereg.scopelistlen;
1432    }
1433    else
1434    {
1435       /* We only echo SRVREG and SRVDEREG */
1436       return;
1437    }
1438 
1439    dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
1440    if (dh)
1441    {
1442       /*-----------------------------------------------------*/
1443       /* Check to see if there is already an identical entry */
1444       /*-----------------------------------------------------*/
1445       while (1)
1446       {
1447          entry = SLPDatabaseEnum(dh);
1448          if (entry == NULL)
1449             break;
1450 
1451          /* entrydaadvert is the DAAdvert message from the database */
1452          entrydaadvert = &(entry->msg->body.daadvert);
1453 
1454          /* Send to all DAs that have matching scope */
1455          if (SLPIntersectStringList(msgscopelen, msgscope,
1456                   entrydaadvert->scopelistlen, entrydaadvert->scopelist))
1457          {
1458             /* Do not echo to ourselves if we are a DA*/
1459             if (G_SlpdProperty.isDA
1460                     && (SLPIntersectStringList(G_ifaceurlsLen,
1461                                                G_ifaceurls,
1462                                                entrydaadvert->urllen,
1463                                                entrydaadvert->url) > 0))
1464             {
1465                /* don't do anything because it makes no sense to echo */
1466                /* to myself                                           */
1467             }
1468             else
1469             {
1470                /*------------------------------------------*/
1471                /* Load the socket with the message to send */
1472                /*------------------------------------------*/
1473                sock = SLPDOutgoingConnect(0, &(entry->msg->peer));
1474                if (sock)
1475                {
1476                   dup = SLPBufferDup(buf);
1477                   if (dup)
1478                   {
1479                      SLPListLinkTail(&(sock->sendlist), (SLPListItem *) dup);
1480                      SLPDOutgoingDatagramWrite(sock, buf);
1481                   }
1482                   else
1483                      sock->state = SOCKET_CLOSE;
1484                }
1485             }
1486          }
1487       }
1488       SLPDatabaseClose(dh);
1489    }
1490 }
1491 
1492 /*=========================================================================*/
SLPDKnownDAActiveDiscovery(int seconds)1493 void SLPDKnownDAActiveDiscovery(int seconds)
1494 /* Add a socket to the outgoing list to do active DA discovery SrvRqst     */
1495 /*                                                                */
1496 /* seconds (IN) number of seconds that expired since last call             */
1497 /*                                                                         */
1498 /* Returns:  none                                                          */
1499 /*=========================================================================*/
1500 {
1501    SLPDSocket * sock;
1502 
1503    /* Check to see if we should perform active DA detection */
1504    if (G_SlpdProperty.DAActiveDiscoveryInterval == 0)
1505       return;
1506    /* When activeDiscoveryXmits is < 0 then we should not xmit any more */
1507    if (G_SlpdProperty.activeDiscoveryXmits < 0)
1508       return ;
1509 
1510    if (G_SlpdProperty.nextActiveDiscovery <= 0)
1511    {
1512       if (G_SlpdProperty.activeDiscoveryXmits == 0)
1513       {
1514          if (G_SlpdProperty.DAActiveDiscoveryInterval == 1)
1515          {
1516             /* ensures xmit on first call */
1517             /* don't xmit any more */
1518             G_SlpdProperty.activeDiscoveryXmits = -1;
1519          }
1520          else
1521          {
1522             G_SlpdProperty.nextActiveDiscovery = G_SlpdProperty.DAActiveDiscoveryInterval;
1523             G_SlpdProperty.activeDiscoveryXmits = 3;
1524          }
1525       }
1526 
1527       G_SlpdProperty.activeDiscoveryXmits --;
1528 
1529       /*Send the datagram, either broadcast or multicast*/
1530       if((G_SlpdProperty.isBroadcastOnly == 1) && SLPNetIsIPV4())
1531       {
1532          /* Use sockaddr_storage consistently for SLPDSocketCreateDatagram */
1533          struct sockaddr_storage peeraddr;
1534          struct sockaddr_in * p_peeraddr = (struct sockaddr_in *)&peeraddr;
1535                                             /* Use sockaddr_in cast for ipv4 only */
1536          memset(&peeraddr, 0, sizeof(struct sockaddr_storage));  /*Some platforms require sin_zero be 0*/
1537          p_peeraddr->sin_family = AF_INET;
1538          p_peeraddr->sin_addr.s_addr = htonl(SLP_BCAST_ADDRESS);
1539          sock = SLPDSocketCreateDatagram(&peeraddr, DATAGRAM_BROADCAST);
1540          if (sock)
1541          {
1542             MakeActiveDiscoveryRqst(1, &(sock->sendbuf));
1543             SLPDOutgoingDatagramWrite(sock, sock->sendbuf);
1544             SLPDSocketFree(sock);
1545          }
1546       }
1547       else
1548       {
1549          /* For each incoming socket, find the sockets that can send multicast
1550             and send the appropriate datagram.  The incoming list is used because
1551             it already has ready-to-use multicast sending sockets allocated for every interface.*/
1552          sock = (SLPDSocket *)G_IncomingSocketList.head;
1553          while (sock)
1554          {
1555             if(sock->can_send_mcast)
1556             {
1557                struct sockaddr_storage mcastaddr;
1558 
1559                if(SLPNetIsIPV6() && (sock->localaddr.ss_family == AF_INET6))
1560                {
1561                   MakeActiveDiscoveryRqst(1, &(sock->sendbuf));
1562 
1563                   SLPNetSetAddr(&mcastaddr, AF_INET6, G_SlpdProperty.port, &in6addr_srvlocda_node);
1564                   SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1565                   SLPNetSetAddr(&mcastaddr, AF_INET6, G_SlpdProperty.port, &in6addr_srvlocda_link);
1566                   SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1567                   if (!IN6_IS_ADDR_LINKLOCAL(&(((struct sockaddr_in6 *) &sock->localaddr)->sin6_addr)))
1568                   {
1569                      SLPNetSetAddr(&mcastaddr, AF_INET6, G_SlpdProperty.port, &in6addr_srvlocda_site);
1570                      SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1571                   }
1572                }
1573                else if((sock->localaddr.ss_family == AF_INET) && SLPNetIsIPV4())
1574                {
1575                   int tmpaddr = SLP_MCAST_ADDRESS;
1576                   MakeActiveDiscoveryRqst(1, &(sock->sendbuf));
1577 
1578                   SLPNetSetAddr(&mcastaddr, AF_INET, G_SlpdProperty.port, &tmpaddr);
1579                   SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1580                }
1581             }
1582 
1583             sock = (SLPDSocket *) sock->listitem.next;
1584          }
1585       }
1586    }
1587    else
1588       G_SlpdProperty.nextActiveDiscovery =
1589             G_SlpdProperty.nextActiveDiscovery - seconds;
1590 }
1591 
1592 /*=========================================================================*/
SLPDKnownDAStaleDACheck(int seconds)1593 void SLPDKnownDAStaleDACheck(int seconds)
1594 /* Check for stale DAs if properly configured                              */
1595 /*                                                                         */
1596 /* seconds (IN) number seconds that elapsed since the last call to this    */
1597 /*              function                                                   */
1598 /*                                                                         */
1599 /* Returns:  none                                                          */
1600 /*=========================================================================*/
1601 {
1602    /* Check to see if we should perform stale DA detection */
1603    if (G_SlpdProperty.staleDACheckPeriod == 0)
1604       return;
1605 
1606    {
1607       SLPDatabaseHandle dh;
1608       SLPDatabaseEntry * entry;
1609       SLPDatabaseEntry * nextEntry;
1610 
1611       (void) seconds;  /*unused parameter warning*/
1612 
1613       dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
1614       if (dh)
1615       {
1616          nextEntry = SLPDatabaseEnum(dh);
1617          while (1)
1618          {
1619             entry = nextEntry;
1620             if (entry == NULL)
1621                break;
1622             nextEntry = SLPDatabaseEnum(dh);
1623             if (!entry->entryvalue)
1624             {
1625                /* No DAAdvert received for this DA within the check period */
1626                SLPDLogDAAdvertisement("Removed - stale", entry);
1627                SLPDatabaseRemove(dh, entry);
1628             }
1629             else
1630                entry->entryvalue--;   /* Decrement the "time to stale" count */
1631          }
1632       }
1633       SLPDatabaseClose(dh);
1634    }
1635 }
1636 
1637 /*=========================================================================*/
SLPDKnownDAPassiveDAAdvert(int seconds,int dadead)1638 void SLPDKnownDAPassiveDAAdvert(int seconds, int dadead)
1639 /* Send passive daadvert messages if properly configured and running as    */
1640 /* a DA                                                                    */
1641 /*                                                                        */
1642 /* seconds (IN) number seconds that elapsed since the last call to this    */
1643 /*              function                                                   */
1644 /*                                                                         */
1645 /* dadead  (IN) nonzero if the DA is dead and a bootstamp of 0 should be   */
1646 /*              sent                                                       */
1647 /*                                                                         */
1648 /* Returns:  none                                                          */
1649 /*=========================================================================*/
1650 {
1651    SLPDSocket * sock;
1652 
1653    /* SAs don't send passive DAAdverts */
1654    if (G_SlpdProperty.isDA == 0)
1655       return;
1656 
1657    /* Check to see if we should perform passive DA detection */
1658    if ((G_SlpdProperty.passiveDADetection == 0) &&
1659        (G_SlpdProperty.staleDACheckPeriod == 0))
1660       return;
1661 
1662    G_SlpdProperty.nextPassiveDAAdvert = G_SlpdProperty.nextPassiveDAAdvert - seconds;
1663    if (G_SlpdProperty.nextPassiveDAAdvert <= 0 || dadead)
1664    {
1665       G_SlpdProperty.nextPassiveDAAdvert += G_SlpdProperty.DAHeartBeat;
1666 
1667       /*Send the datagram, either broadcast or multicast*/
1668       if ((G_SlpdProperty.isBroadcastOnly == 1) && SLPNetIsIPV4())
1669       {
1670          /* Use sockaddr_storage consistently for SLPDSocketCreateDatagram */
1671          struct sockaddr_storage peeraddr;
1672          struct sockaddr_in *p_peeraddr = (struct sockaddr_in *)&peeraddr;
1673                                            /* Use sockaddr_in cast for ipv4 only */
1674          memset(&peeraddr, 0, sizeof(struct sockaddr_storage));  /*Some platforms require sin_zero be 0*/
1675          p_peeraddr->sin_family = AF_INET;
1676          p_peeraddr->sin_addr.s_addr = htonl(SLP_BCAST_ADDRESS);
1677          sock = SLPDSocketCreateDatagram(&peeraddr, DATAGRAM_BROADCAST);
1678          if(sock)
1679          {
1680             /* @todo sock doesn't have a localaddr, and some platforms send broadcasts on all
1681             network interfaces, so I'm not sure what to send -- I'll just pick a non-loopback
1682             interface for now, and perhaps later cycle through the list and send as all local
1683             addrs.  Note that the original broadcasting code had the same problem, so this
1684             probably wasn't used much.*/
1685             if(G_IncomingSocketList.tail)
1686             {
1687                struct sockaddr_storage* myaddr = &((SLPDSocket *)G_IncomingSocketList.tail)->localaddr;
1688                if (SLPDKnownDAGenerateMyDAAdvert(myaddr, 0, dadead, 1, 0, &(sock->sendbuf)) == 0)
1689                   SLPDOutgoingDatagramWrite(sock, sock->sendbuf);
1690 #ifdef ENABLE_SLPv1
1691                if (SLPDKnownDAGenerateMyV1DAAdvert(myaddr, 0, SLP_CHAR_UTF8, 0, &(sock->sendbuf)) == 0)
1692                   SLPDOutgoingDatagramWrite(sock, sock->sendbuf);
1693 #endif
1694             }
1695             SLPDSocketFree(sock);
1696          }
1697       }
1698       else
1699       {
1700          /*   For each incoming socket, find the sockets that can send multicast
1701             and send the appropriate datagram. */
1702          sock = (SLPDSocket *)G_IncomingSocketList.head;
1703          while (sock)
1704          {
1705             if(sock->can_send_mcast)
1706             {
1707                struct sockaddr_storage mcastaddr;
1708 
1709                if(SLPNetIsIPV6() && (sock->localaddr.ss_family == AF_INET6))
1710                {
1711                   if (SLPDKnownDAGenerateMyDAAdvert(&sock->localaddr, 0, dadead, 1, 0, &(sock->sendbuf)) == 0)
1712                   {
1713                      SLPNetSetAddr(&mcastaddr, AF_INET6, G_SlpdProperty.port, &in6addr_srvlocda_node);
1714                      SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1715                      SLPNetSetAddr(&mcastaddr, AF_INET6, G_SlpdProperty.port, &in6addr_srvlocda_link);
1716                      SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1717                      if (!IN6_IS_ADDR_LINKLOCAL(&(((struct sockaddr_in6 *) &sock->localaddr)->sin6_addr)))
1718                      {
1719                         SLPNetSetAddr(&mcastaddr, AF_INET6, G_SlpdProperty.port, &in6addr_srvlocda_site);
1720                         SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1721                      }
1722                   }
1723                }
1724                else if((sock->localaddr.ss_family == AF_INET) && SLPNetIsIPV4())
1725                {
1726                   int tmpaddr = SLP_MCAST_ADDRESS;
1727 
1728                   if (SLPDKnownDAGenerateMyDAAdvert(&sock->localaddr, 0, dadead, 1, 0, &(sock->sendbuf)) == 0)
1729                   {
1730                         SLPNetSetAddr(&mcastaddr, AF_INET, G_SlpdProperty.port, &tmpaddr);
1731                         SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1732                   }
1733 #ifdef ENABLE_SLPv1
1734                   if (SLPDKnownDAGenerateMyV1DAAdvert(&sock->localaddr, 0,
1735                                     SLP_CHAR_UTF8, 0, &(sock->sendbuf)) == 0)
1736                   {
1737                         tmpaddr = SLPv1_DA_MCAST_ADDRESS;
1738                         SLPNetSetAddr(&mcastaddr, AF_INET, G_SlpdProperty.port, &tmpaddr);
1739                         SLPDOutgoingDatagramMcastWrite(sock, &mcastaddr, sock->sendbuf);
1740                   }
1741 #endif
1742                }
1743             }
1744 
1745             sock = (SLPDSocket *) sock->listitem.next;
1746          }
1747       }
1748    }
1749 }
1750 
1751 
1752 /*=========================================================================*/
SLPDKnownDAImmortalRefresh(int seconds)1753 void SLPDKnownDAImmortalRefresh(int seconds)
1754 /* Refresh all SLP_LIFETIME_MAXIMUM services                               */
1755 /*                                                          */
1756 /* seconds (IN) time in seconds since last call                            */
1757 /*=========================================================================*/
1758 {
1759    SLPDatabaseHandle dh;
1760    SLPDatabaseEntry * entry;
1761    SLPDAAdvert * entrydaadvert;
1762 
1763    G_KnownDATimeSinceLastRefresh += seconds;
1764 
1765    if (G_KnownDATimeSinceLastRefresh >= SLP_LIFETIME_MAXIMUM - seconds)
1766    {
1767       /* Refresh all SLP_LIFETIME_MAXIMUM registrations */
1768       dh = SLPDatabaseOpen(&G_SlpdKnownDAs);
1769       if (dh)
1770       {
1771          /*-----------------------------------------------------*/
1772          /* Check to see if there is already an identical entry */
1773          /*-----------------------------------------------------*/
1774          while (1)
1775          {
1776             entry = SLPDatabaseEnum(dh);
1777             if (entry == NULL)
1778                break;
1779 
1780             /* entrydaadvert is the DAAdvert message from the database */
1781             entrydaadvert = &(entry->msg->body.daadvert);
1782 
1783             /* Skip ourself, which we detect by matching the entry's url     */
1784             /* (ip address) against the list of our own interface addresses. */
1785             /* If there's no match, then we can go ahead                     */
1786             if(SLPIntersectStringList(G_ifaceurlsLen, G_ifaceurls, entrydaadvert->urllen, entrydaadvert->url) == 0)
1787                SLPDKnownDARegisterAll(entry->msg, 1);
1788          }
1789 
1790          SLPDatabaseClose(dh);
1791       }
1792 
1793       G_KnownDATimeSinceLastRefresh = 0;
1794    }
1795 }
1796 
1797 /*=========================================================================*/
SLPDKnownDADeRegisterWithAllDas(SLPMessage * msg,SLPBuffer buf)1798 void SLPDKnownDADeRegisterWithAllDas(SLPMessage * msg, SLPBuffer buf)
1799 /* Deregister the registration described by the specified message          */
1800 /*                                                                         */
1801 /* msg (IN) A message descriptor for a SrvReg or SrvDereg message to       */
1802 /*          deregister                                                     */
1803 /*                                                                         */
1804 /* buf (IN) Message buffer associated with msg                             */
1805 /*                                                                         */
1806 /* Returns: None                                                           */
1807 /*=========================================================================*/
1808 {
1809    SLPBuffer sendbuf;
1810 
1811    if (msg->header.functionid == SLP_FUNCT_SRVREG)
1812    {
1813       if (MakeSrvderegFromSrvReg(msg, buf, &sendbuf) == 0)
1814       {
1815          SLPDKnownDAEcho(msg, sendbuf);
1816          SLPBufferFree(sendbuf);
1817       }
1818    }
1819    else if (msg->header.functionid == SLP_FUNCT_SRVDEREG)
1820    {
1821       /* Simply echo the message through as is */
1822       SLPDKnownDAEcho(msg, buf);
1823    }
1824 }
1825 
1826 /*=========================================================================*/
SLPDKnownDARegisterWithAllDas(SLPMessage * msg,SLPBuffer buf)1827 void SLPDKnownDARegisterWithAllDas(SLPMessage * msg, SLPBuffer buf)
1828 /* Register the registration described by the specified message with all   */
1829 /* known DAs                                                               */
1830 /*                                                                         */
1831 /* msg (IN) A message descriptor for a SrvReg or SrvDereg message to       */
1832 /*          deregister                                                     */
1833 /*                                                                         */
1834 /* buf (IN) Message buffer associated with msg                             */
1835 /*                                                                         */
1836 /* Returns: None                                                           */
1837 /*=========================================================================*/
1838 {
1839    if (msg->header.functionid == SLP_FUNCT_SRVDEREG)
1840    {
1841       /* Simply echo the message through as is */
1842       SLPDKnownDAEcho(msg, buf);
1843    }
1844 }
1845 
1846 #ifdef DEBUG
1847 /*=========================================================================*/
SLPDKnownDADump(void)1848 void SLPDKnownDADump(void)
1849 /*=========================================================================*/
1850 {
1851    SLPMessage * msg;
1852    SLPBuffer buf;
1853    void * eh;
1854 
1855    eh = SLPDKnownDAEnumStart();
1856    if (eh)
1857    {
1858       SLPDLog("========================================================================\n");
1859       SLPDLog("Dumping KnownDAs \n");
1860       SLPDLog("========================================================================\n");
1861       while (SLPDKnownDAEnum(eh, &msg, &buf))
1862       {
1863          SLPDLogMessageInternals(msg);
1864          SLPDLog("\n");
1865       }
1866 
1867       SLPDKnownDAEnumEnd(eh);
1868    }
1869 }
1870 #endif
1871 
1872 /*=========================================================================*/
1873