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