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 /** Processes incoming SLPv1 messages
34  *
35  * @file       slpd_v1process.c
36  * @author     Matthew Peterson, Ganesan Rajagopal,
37  *             John Calcote (jcalcote@novell.com)
38  * @attention  Please submit patches to http://www.openslp.org
39  * @ingroup    SlpdCode
40  */
41 
42 #include "slpd_process.h"
43 #include "slpd_property.h"
44 #include "slpd_database.h"
45 #include "slpd_knownda.h"
46 #include "slpd_log.h"
47 
48 #include "slp_xmalloc.h"
49 #include "slp_message.h"
50 #include "slp_v1message.h"
51 #include "slp_utf8.h"
52 #include "slp_compare.h"
53 #include "slp_net.h"
54 
55 /** Process an SLPv1 DA Service Request.
56  *
57  * @param[in] peeraddr - The address of the remote client.
58  * @param[in] localaddr - The locally bound address for this message.
59  * @param[in] message - The SRV request message.
60  * @param[out] sendbuf - The response buffer to be sent back to the client.
61  * @param[in] errorcode - The error code from the client request.
62  *
63  * @return Zero on success, or a non-zero value on failure.
64  *
65  * @internal
66  */
v1ProcessDASrvRqst(struct sockaddr_storage * peeraddr,struct sockaddr_storage * localaddr,SLPMessage * message,SLPBuffer * sendbuf,int errorcode)67 static int v1ProcessDASrvRqst(struct sockaddr_storage * peeraddr,
68       struct sockaddr_storage * localaddr, SLPMessage * message,
69       SLPBuffer * sendbuf, int errorcode)
70 {
71    if (G_SlpdProperty.isDA)
72    {
73       if (message->body.srvrqst.scopelistlen == 0
74             || SLPIntersectStringList(message->body.srvrqst.scopelistlen,
75                   message->body.srvrqst.scopelist,G_SlpdProperty.useScopesLen,
76                   G_SlpdProperty.useScopes))
77          errorcode = SLPDKnownDAGenerateMyV1DAAdvert(localaddr, errorcode,
78                message->header.encoding, message->header.xid, sendbuf);
79       else
80          errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
81    }
82    else
83       errorcode = SLP_ERROR_MESSAGE_NOT_SUPPORTED;
84 
85    /* don't return errorcodes to multicast messages */
86    if ((errorcode != 0 && (message->header.flags & SLP_FLAG_MCAST) != 0)
87          || SLPNetIsMCast(peeraddr))
88    {
89       (*sendbuf)->end = (*sendbuf)->start;
90       return errorcode;
91    }
92    return errorcode;
93 }
94 
95 /** Process an SLPv1 general Service Request.
96  *
97  * @internal
98  */
v1ProcessSrvRqst(struct sockaddr_storage * peeraddr,struct sockaddr_storage * localaddr,SLPMessage * message,SLPBuffer * sendbuf,int errorcode)99 static int v1ProcessSrvRqst(struct sockaddr_storage * peeraddr,
100       struct sockaddr_storage * localaddr, SLPMessage * message,
101       SLPBuffer * sendbuf, int errorcode)
102 {
103    int i;
104    size_t urllen;
105    size_t size = 0;
106    SLPDDatabaseSrvRqstResult * db = 0;
107    SLPBuffer result = *sendbuf;
108 
109    /* If errorcode is set, we can not be sure that message is good
110       Go directly to send response code */
111    if (errorcode)
112       goto RESPOND;
113 
114    /* check for one of our IP addresses in the prlist */
115    if (SLPIntersectStringList(message->body.srvrqst.prlistlen,
116          message->body.srvrqst.prlist, G_SlpdProperty.interfacesLen,
117          G_SlpdProperty.interfaces))
118    {
119       result->end = result->start;
120       goto FINISHED;
121    }
122 
123    /* check to to see if a this is a special SrvRqst */
124    if (SLPCompareString(message->body.srvrqst.srvtypelen,
125          message->body.srvrqst.srvtype, 15, "directory-agent") == 0)
126    {
127       errorcode = v1ProcessDASrvRqst(peeraddr, localaddr, message,
128             sendbuf, errorcode);
129       return errorcode;
130    }
131 
132    /* make sure that we handle the scope */
133    if (SLPIntersectStringList(message->body.srvrqst.scopelistlen,
134          message->body.srvrqst.scopelist, G_SlpdProperty.useScopesLen,
135          G_SlpdProperty.useScopes) != 0) /* find services in the database */
136       errorcode = SLPDDatabaseSrvRqstStart(message, &db);
137    else
138       errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
139 
140 RESPOND:
141 
142    /* do not send error codes or empty replies to multicast requests */
143    if (message->header.flags & SLP_FLAG_MCAST)
144       if (!db || errorcode != 0 || db->urlcount == 0)
145       {
146          result->end = result->start;
147          goto FINISHED;
148       }
149 
150    /* ensure the buffer is big enough to handle the whole srvrply */
151    size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes for url count */
152    if (db && errorcode == 0)
153    {
154       for (i = 0; i < db->urlcount; i++)
155       {
156          urllen = INT_MAX;
157          errorcode = SLPv1ToEncoding(0, &urllen, message->header.encoding,
158                db->urlarray[i]->url, db->urlarray[i]->urllen);
159          if (errorcode)
160             break;
161          size += urllen + 4; /* 2 bytes for lifetime, 2 bytes for urllen */
162       }
163       result = SLPBufferRealloc(result, size);
164       if (result == 0)
165          errorcode = SLP_ERROR_INTERNAL_ERROR;
166    }
167 
168    if (db && result)
169    {
170       /* add the header */
171 
172       /* version */
173       *result->curpos++ = 1;
174 
175       /* function id */
176       *result->curpos++ = SLP_FUNCT_SRVRPLY;
177 
178       /* length */
179       PutUINT16(&result->curpos, size);
180 
181       /* flags */
182       /** @todo Set the flags correctly. */
183       *result->curpos++ = (uint8_t)(message->header.flags
184             | (size > (size_t)G_SlpdProperty.MTU? SLPv1_FLAG_OVERFLOW: 0));
185 
186       /* dialect */
187       *result->curpos++ = 0;
188 
189       /* language code */
190       memcpy(result->curpos, message->header.langtag, 2);
191       result->curpos += 2;
192       PutUINT16(&result->curpos, message->header.encoding);
193 
194       /* xid */
195       PutUINT16(&result->curpos, message->header.xid);
196 
197       /* add rest of the SrvRply */
198 
199       /* error code*/
200       PutUINT16(&result->curpos, errorcode);
201       if (errorcode == 0)
202       {
203          /* urlentry count */
204          PutUINT16(&result->curpos, db->urlcount);
205          for (i = 0; i < db->urlcount; i++)
206          {
207             /* url-entry lifetime */
208             PutUINT16(&result->curpos, db->urlarray[i]->lifetime);
209 
210             /* url-entry url and urllen */
211             urllen = size;
212             errorcode = SLPv1ToEncoding((char *)(result->curpos + 2),
213                   &urllen, message->header.encoding, db->urlarray[i]->url,
214                   db->urlarray[i]->urllen);
215             PutUINT16(&result->curpos, urllen);
216             result->curpos += urllen;
217          }
218       }
219       else  /* urlentry count */
220          PutUINT16(&result->curpos, 0);
221    }
222 
223 FINISHED:
224 
225    SLPDDatabaseSrvRqstEnd(db);
226    *sendbuf = result;
227    return errorcode;
228 }
229 
230 /** Process an SLPv1 general Service Registration.
231  *
232  * @param[in] peeraddr - The remote address of the client.
233  * @param[in] message - The client message object.
234  * @param[in] recvbuf - The client message receive buffer.
235  * @param[in] sendbuf - The server response send buffer.
236  * @param[in] errorcode - The error code from the client message.
237  *
238  * @return Non-zero if message should be silently dropped.
239  *
240  * @internal
241  */
v1ProcessSrvReg(struct sockaddr_storage * peeraddr,SLPMessage * message,SLPBuffer recvbuf,SLPBuffer * sendbuf,int errorcode)242 static int v1ProcessSrvReg(struct sockaddr_storage * peeraddr,
243       SLPMessage * message, SLPBuffer recvbuf, SLPBuffer * sendbuf,
244       int errorcode)
245 {
246    SLPBuffer result = *sendbuf;
247 
248    (void)peeraddr;
249 
250    /* If errorcode is set, we can not be sure that message is good
251       Go directly to send response code  also do not process mcast
252       srvreg or srvdereg messages */
253 
254    if (errorcode || message->header.flags & SLP_FLAG_MCAST)
255       goto RESPOND;
256 
257    /* make sure that we handle the scope */
258    if (SLPIntersectStringList(message->body.srvreg.scopelistlen,
259          message->body.srvreg.scopelist, G_SlpdProperty.useScopesLen,
260          G_SlpdProperty.useScopes))
261    {
262       /* put the service in the database */
263       if (SLPNetIsLocal(&message->peer))
264          message->body.srvreg.source= SLP_REG_SOURCE_LOCAL;
265       else
266          message->body.srvreg.source = SLP_REG_SOURCE_REMOTE;
267 
268       errorcode = SLPDDatabaseReg(message,recvbuf);
269    }
270    else
271       errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
272 
273 RESPOND:
274 
275    /* don't send back reply anything multicast SrvReg (set result empty) */
276    if (message->header.flags & SLP_FLAG_MCAST)
277    {
278       result->end = result->start;
279       goto FINISHED;
280    }
281 
282    /* ensure the buffer is big enough to handle the whole srvack */
283    result = SLPBufferRealloc(result, 14);
284    if (result == 0)
285    {
286       errorcode = SLP_ERROR_INTERNAL_ERROR;
287       goto FINISHED;
288    }
289 
290    /* add the header */
291 
292    /* version */
293    *result->curpos++ = 1;
294 
295    /* function id */
296    *result->curpos++   = SLP_FUNCT_SRVACK;
297 
298    /* length */
299    PutUINT16(&result->curpos, 14);
300 
301    /* flags */
302    /** @todo Set the flags correctly. */
303    *result->curpos++ = 0;
304 
305    /* dialect */
306    *result->curpos++ = 0;
307 
308    /* language code */
309    memcpy(result->curpos, message->header.langtag, 2);
310    result->curpos += 2;
311    PutUINT16(&result->curpos, message->header.encoding);
312 
313    /* xid */
314    PutUINT16(&result->curpos, message->header.xid);
315 
316    /* add the errorcode */
317    PutUINT16(&result->curpos, errorcode);
318 
319 FINISHED:
320 
321    *sendbuf = result;
322    return errorcode;
323 }
324 
325 /** Process an SLPv1 general Service Deregistration.
326  *
327  * @param[in] peeraddr - The remote client's address.
328  * @param[in] message - The inbound SrvDereg message.
329  * @param[out] sendbuf - The outbound reply buffer.
330  * @param[in] errorcode - The inbound request error code.
331  *
332  * @return Non-zero if message should be silently dropped.
333  */
v1ProcessSrvDeReg(struct sockaddr_storage * peeraddr,SLPMessage * message,SLPBuffer * sendbuf,int errorcode)334 static int v1ProcessSrvDeReg(struct sockaddr_storage * peeraddr,
335       SLPMessage * message, SLPBuffer * sendbuf, int errorcode)
336 {
337    SLPBuffer result = *sendbuf;
338 
339    (void)peeraddr;
340 
341    /* If errorcode is set, we can not be sure that message is good
342       Go directly to send response code  also do not process mcast
343       srvreg or srvdereg messages */
344 
345    if (errorcode || message->header.flags & SLP_FLAG_MCAST)
346       goto RESPOND;
347 
348    /* make sure that we handle the scope */
349    if (SLPIntersectStringList(message->body.srvdereg.scopelistlen,
350          message->body.srvdereg.scopelist, G_SlpdProperty.useScopesLen,
351          G_SlpdProperty.useScopes))
352       errorcode = SLPDDatabaseDeReg(message);
353    else
354       errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
355 
356 RESPOND:
357 
358    /* don't do anything multicast SrvDeReg (set result empty) */
359    if (message->header.flags & SLP_FLAG_MCAST)
360    {
361       result->end = result->start;
362       goto FINISHED;
363    }
364 
365    /* ensure the buffer is big enough to handle the whole srvack */
366    result = SLPBufferRealloc(result, 14);
367    if (result == 0)
368    {
369       errorcode = SLP_ERROR_INTERNAL_ERROR;
370       goto FINISHED;
371    }
372 
373    /* add the header */
374 
375    /* version */
376    *result->curpos++ = 1;
377 
378    /* function id */
379    *result->curpos++ = SLP_FUNCT_SRVACK;
380 
381    /* length */
382    PutUINT16(&result->curpos, 14);
383 
384    /* flags */
385    /** @todo Set the flags correctly. */
386    *result->curpos++ = 0;
387 
388    /* dialect */
389    *result->curpos++ = 0;
390 
391    /* language code */
392    memcpy(result->curpos, message->header.langtag, 2);
393    result->curpos += 2;
394    PutUINT16(&result->curpos, message->header.encoding);
395 
396    /*xid*/
397    PutUINT16(&result->curpos, message->header.xid);
398 
399    /* add the errorcode */
400    PutUINT16(&result->curpos, errorcode);
401 
402 FINISHED:
403 
404    *sendbuf = result;
405    return errorcode;
406 }
407 
408 /** Process an SLPv1 Attribute Request message.
409  *
410  * @param[in] peeraddr - The remote client's address.
411  * @param[in] message - The inbound request message.
412  * @param[out] sendbuf - The outbound response buffer.
413  * @param[in] errorcode - The inbound request error code.
414  *
415  * @return Zero on success, or a non-zero value on failure.
416  */
v1ProcessAttrRqst(struct sockaddr_storage * peeraddr,SLPMessage * message,SLPBuffer * sendbuf,int errorcode)417 static int v1ProcessAttrRqst(struct sockaddr_storage * peeraddr,
418       SLPMessage * message, SLPBuffer * sendbuf, int errorcode)
419 {
420    SLPDDatabaseAttrRqstResult * db = 0;
421    size_t attrlen = 0;
422    size_t size = 0;
423    SLPBuffer result = *sendbuf;
424 
425    (void)peeraddr;
426 
427    /* If errorcode is set, we can not be sure that message is good
428       Go directly to send response code */
429    if (errorcode)
430       goto RESPOND;
431 
432    /* check for one of our IP addresses in the prlist */
433    if (SLPIntersectStringList(message->body.attrrqst.prlistlen,
434          message->body.attrrqst.prlist, G_SlpdProperty.interfacesLen,
435          G_SlpdProperty.interfaces))
436    {
437       result->end = result->start;
438       goto FINISHED;
439    }
440 
441    /* make sure that we handle the scope */
442    if (SLPIntersectStringList(message->body.attrrqst.scopelistlen,
443          message->body.attrrqst.scopelist, G_SlpdProperty.useScopesLen,
444          G_SlpdProperty.useScopes))
445       errorcode = SLPDDatabaseAttrRqstStart(message,&db);
446    else
447       errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
448 
449 RESPOND:
450 
451    /* do not send error codes or empty replies to multicast requests */
452    if (message->header.flags & SLP_FLAG_MCAST)
453       if (errorcode != 0 || db->attrlistlen == 0)
454       {
455          result->end = result->start;
456          goto FINISHED;
457       }
458 
459    /* ensure the buffer is big enough to handle the whole attrrply */
460    size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes
461    for attr-list len */
462    if (errorcode == 0)
463    {
464       attrlen = INT_MAX;
465       errorcode = SLPv1ToEncoding(0, &attrlen, message->header.encoding,
466             db->attrlist, db->attrlistlen);
467       size += attrlen;
468    }
469 
470    /* alloc the buffer */
471    result = SLPBufferRealloc(result, size);
472    if (result == 0)
473    {
474       errorcode = SLP_ERROR_INTERNAL_ERROR;
475       goto FINISHED;
476    }
477 
478    /* Add the header */
479 
480    /* version */
481    *result->curpos++ = 1;
482 
483    /* function id */
484    *result->curpos++ = SLP_FUNCT_ATTRRPLY;
485 
486    /* length */
487    PutUINT16(&result->curpos, size);
488 
489    /* flags */
490    /** @todo Set the flags correctly. */
491    *result->curpos++ = (uint8_t)(message->header.flags
492          | (size > (size_t)G_SlpdProperty.MTU?
493                SLPv1_FLAG_OVERFLOW: 0));
494 
495    /* dialect */
496    *result->curpos++ = 0;
497 
498    /* language code */
499    memcpy(result->curpos, message->header.langtag, 2);
500    result->curpos += 2;
501    PutUINT16(&result->curpos, message->header.encoding);
502 
503    /* xid */
504    PutUINT16(&result->curpos, message->header.xid);
505 
506    /* add rest of the AttrRply */
507 
508    /* error code */
509 
510    PutUINT16(&result->curpos, errorcode);
511    if (errorcode == 0)
512    {
513       /* attr-list len */
514       PutUINT16(&result->curpos, attrlen);
515       attrlen = size;
516       SLPv1ToEncoding((char *)result->curpos, &attrlen,
517             message->header.encoding, db->attrlist, db->attrlistlen);
518       result->curpos += attrlen;
519    }
520 
521 FINISHED:
522 
523    *sendbuf = result;
524    if (db)
525       SLPDDatabaseAttrRqstEnd(db);
526    return errorcode;
527 }
528 
529 /** Process an SLPv1 Service Type request message.
530  *
531  * @param[in] peeraddr - The remote client's address.
532  * @param[in] message - The inbound request message.
533  * @param[out] sendbuf - The outbound response buffer.
534  * @param[in] errorcode - The inbound request error code.
535  *
536  * @return Zero on success, or a non-zero value on failure.
537  */
v1ProcessSrvTypeRqst(struct sockaddr_storage * peeraddr,SLPMessage * message,SLPBuffer * sendbuf,int errorcode)538 static int v1ProcessSrvTypeRqst(struct sockaddr_storage * peeraddr,
539       SLPMessage * message, SLPBuffer * sendbuf, int errorcode)
540 {
541    char * type;
542    char * end;
543    char * slider;
544    int i;
545    size_t typelen;
546    size_t size = 0;
547    int numsrvtypes = 0;
548    SLPDDatabaseSrvTypeRqstResult * db = 0;
549    SLPBuffer result = *sendbuf;
550 
551    (void)peeraddr;
552 
553    /* check for one of our IP addresses in the prlist */
554    if (SLPIntersectStringList(message->body.srvtyperqst.prlistlen,
555          message->body.srvtyperqst.prlist, G_SlpdProperty.interfacesLen,
556          G_SlpdProperty.interfaces))
557    {
558       result->end = result->start;
559       goto FINISHED;
560    }
561 
562    /* make sure that we handle the scope */
563    if (SLPIntersectStringList(message->body.srvtyperqst.scopelistlen,
564          message->body.srvtyperqst.scopelist, G_SlpdProperty.useScopesLen,
565          G_SlpdProperty.useScopes) != 0)
566       errorcode = SLPDDatabaseSrvTypeRqstStart(message, &db);
567    else
568       errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
569 
570    /* do not send error codes or empty replies to multicast requests */
571    if (message->header.flags & SLP_FLAG_MCAST)
572       if (errorcode != 0 || db->srvtypelistlen == 0)
573       {
574          result->end = result->start;
575          goto FINISHED;
576       }
577 
578    /* ensure the buffer is big enough to handle the whole srvtyperply */
579    size = 16;  /* 12 bytes for header, 2 bytes for error code, 2 bytes
580                   for num of service types */
581    if (errorcode == 0)
582    {
583       if (db->srvtypelistlen)
584       {
585          /* there has to be at least one service type*/
586          numsrvtypes = 1;
587 
588          /* count the rest of the service types */
589          type = db->srvtypelist;
590          for (i = 0; i < (int)db->srvtypelistlen; i++)
591             if (type[i] == ',')
592                numsrvtypes += 1;
593 
594          /* figure out how much memory is required for srvtype strings */
595          typelen = INT_MAX;
596          errorcode = SLPv1ToEncoding(0, &typelen, message->header.encoding,
597                db->srvtypelist, db->srvtypelistlen);
598 
599          /* TRICKY: We add in the numofsrvtypes + 1 to make room for the
600           * type length.  We can do this because the ',' of the comma
601           * delimited list is one byte.
602           */
603          size = size + typelen + numsrvtypes + 1;
604       }
605       else
606          numsrvtypes = 0;
607    }
608 
609    /* allocate memory */
610    result = SLPBufferRealloc(result,size);
611    if (result == 0)
612    {
613       errorcode = SLP_ERROR_INTERNAL_ERROR;
614       goto FINISHED;
615    }
616 
617    /* Add the header */
618 
619    /* version */
620    *result->curpos++ = 1;
621 
622    /* function id */
623    *result->curpos++ = SLP_FUNCT_SRVTYPERPLY;
624 
625    /* length */
626    PutUINT16(&result->curpos, size);
627 
628    /* flags */
629    /** @todo Set the flags correctly. */
630    *result->curpos++ = (uint8_t)(message->header.flags
631          | (size > (size_t)G_SlpdProperty.MTU?
632                SLPv1_FLAG_OVERFLOW: 0));
633 
634    /* dialect */
635    *result->curpos++ = 0;
636 
637    /* language code */
638    memcpy(result->curpos, message->header.langtag, 2);
639    result->curpos += 2;
640 
641    PutUINT16(&result->curpos, message->header.encoding);
642 
643    /* xid */
644    PutUINT16(&result->curpos, message->header.xid);
645 
646    /* Add rest of the SrvTypeRply */
647 
648    /* error code */
649    PutUINT16(&result->curpos, errorcode);
650    if (errorcode == 0)
651    {
652       /* num of service types */
653       PutUINT16(&result->curpos, numsrvtypes);
654 
655       /* service type strings */
656       type = db->srvtypelist;
657       slider = db->srvtypelist;
658       end = &type[db->srvtypelistlen];
659       for (i = 0; i < numsrvtypes; i++)
660       {
661          while (slider < end && *slider != ',')
662             slider++;
663 
664          /* put in the encoded service type */
665          typelen = size;
666          SLPv1ToEncoding((char *)(result->curpos + 2), &typelen,
667                message->header.encoding, type, slider - type);
668 
669          /* slip in the typelen */
670          PutUINT16(&result->curpos, typelen);
671          result->curpos += typelen;
672 
673          slider++; /* skip comma */
674          type = slider;
675       }
676       /** @todo Make sure we don't return generic types */
677    }
678 
679 FINISHED:
680 
681    if (db)
682       SLPDDatabaseSrvTypeRqstEnd(db);
683 
684    *sendbuf = result;
685 
686    return errorcode;
687 }
688 
689 /** Process an SLPv1 message.
690  *
691  * Process an SLPv1 message, and place the results in an outbound
692  * buffer object.
693  *
694  * @param[in] peeraddr - The remote client's address.
695  * @param[in] recvbuf  - The inbound message to process.
696  * @param[out] sendbuf - The outbound response buffer.
697  *
698  * @return Zero on success, or SLP_ERROR_PARSE_ERROR on general failure,
699  *    or SLP_ERROR_INTERNAL_ERROR under out-of-memory conditions.
700  */
SLPDv1ProcessMessage(struct sockaddr_storage * peeraddr,SLPBuffer recvbuf,SLPBuffer * sendbuf)701 int SLPDv1ProcessMessage(struct sockaddr_storage * peeraddr,
702       SLPBuffer recvbuf, SLPBuffer * sendbuf)
703 {
704    SLPHeader header;
705    SLPMessage * message;
706    int errorcode = 0;
707 
708    /* SLPv1 messages are handled only by DAs */
709    if (!G_SlpdProperty.isDA)
710       return SLP_ERROR_VER_NOT_SUPPORTED;
711 
712    /* Parse just the message header the reset the buffer "curpos" pointer */
713    recvbuf->curpos = recvbuf->start;
714    if ((errorcode = SLPv1MessageParseHeader(recvbuf, &header)) != 0)
715       return errorcode;
716 
717    /* Reset the buffer "curpos" pointer so that full message can be
718       parsed later
719     */
720    recvbuf->curpos = recvbuf->start;
721 
722 
723    /* TRICKY: Duplicate SRVREG recvbufs *before* parsing them it because we
724     * are going to keep them in the
725     */
726    if (header.functionid == SLP_FUNCT_SRVREG)
727    {
728       recvbuf = SLPBufferDup(recvbuf);
729       if (recvbuf == 0)
730          return SLP_ERROR_INTERNAL_ERROR;
731    }
732 
733    /* Allocate the message descriptor */
734    message = SLPMessageAlloc();
735    if (message)
736    {
737       /* Copy in the remote address */
738       memcpy(&message->peer, peeraddr, sizeof(message->peer));
739 
740       /* Parse the message and fill out the message descriptor */
741       errorcode = SLPv1MessageParseBuffer(recvbuf, message);
742       if (errorcode == 0)
743       {
744          /* Process messages based on type */
745          switch (message->header.functionid)
746          {
747             case SLP_FUNCT_SRVRQST:
748                errorcode = v1ProcessSrvRqst(peeraddr, peeraddr, message,
749                      sendbuf, errorcode);
750                break;
751 
752             case SLP_FUNCT_SRVREG:
753                errorcode = v1ProcessSrvReg(peeraddr, message, recvbuf,
754                      sendbuf, errorcode);
755                if (errorcode == 0)
756                   SLPDKnownDAEcho(message, recvbuf);
757                break;
758 
759             case SLP_FUNCT_SRVDEREG:
760                errorcode = v1ProcessSrvDeReg(peeraddr, message,
761                      sendbuf, errorcode);
762                if (errorcode == 0)
763                   SLPDKnownDAEcho(message, recvbuf);
764                break;
765 
766             case SLP_FUNCT_ATTRRQST:
767                errorcode = v1ProcessAttrRqst(peeraddr, message,
768                      sendbuf, errorcode);
769                break;
770 
771             case SLP_FUNCT_SRVTYPERQST:
772                errorcode = v1ProcessSrvTypeRqst(peeraddr, message,
773                      sendbuf, errorcode);
774                break;
775 
776             case SLP_FUNCT_DAADVERT:
777                /* we are a SLPv2 DA, ignore other v1 DAs */
778                (*sendbuf)->end = (*sendbuf)->start;
779                break;
780 
781             default:
782                /* Should never happen... but we're paranoid */
783                errorcode = SLP_ERROR_PARSE_ERROR;
784                break;
785          }
786       }
787 
788       if (header.functionid == SLP_FUNCT_SRVREG)
789       {
790          /* TRICKY: Do not free the message descriptor for SRVREGs because we
791           * are keeping them in the database unless there is an error then we
792           * free memory.
793           */
794          if (errorcode)
795          {
796             SLPMessageFree(message);
797             SLPBufferFree(recvbuf);
798          }
799       }
800       else
801          SLPMessageFree(message);
802    }
803    else
804       errorcode = SLP_ERROR_INTERNAL_ERROR;
805 
806    return errorcode;
807 }
808 
809 /*=========================================================================*/
810