1 mday 1.1 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2001 The Open Group, BMC Software, IBM
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a
6 // copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the
10 // Software is furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 mday 1.1 // DEALINGS IN THE SOFTWARE.
23 //
24 //==============================================================================
25 //
26 // Author: Mike Day (mdday@us.ibm.com)
27 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
30
31 #include "slp.h"
32
33 PEGASUS_USING_STD;
34
35 PEGASUS_NAMESPACE_BEGIN
36
|
37 mday 1.2 PEGASUS_EXPORT String slp_get_host_name(void)
|
38 mday 1.1 {
|
39 mday 1.2
40 String s = String();
41 Sint8 *buf = new Sint8[255];
42 if( 0 == gethostname(buf, 254) )
43 s += buf;
44 delete buf;
45 return(s);
|
46 mday 1.1 }
47
48
49 #ifdef _WIN32
50 PEGASUS_EXPORT int gethostbyname_r(const char *name,
51 struct hostent *resultbuf,
52 char *buf,
53 size_t bufsize,
54 struct hostent **result,
55 int *errnop)
56 {
57 name = name;
58 resultbuf = resultbuf;
59 buf = buf;
60 bufsize = bufsize;
61
62 if(NULL == (*result = gethostbyname(name))) {
63 *errnop = WSAGetLastError();
64 return(-1);
65 }
66 return(0);
67 mday 1.1 }
68
69 #endif
70
|
71 karl 1.3 #ifdef PEGASUS_OS_HPUX
72
73 PEGASUS_EXPORT int gethostbyname_r(const char *name,
74 struct hostent *resultbuf,
75 char *buf,
76 size_t bufsize,
77 struct hostent **result,
78 int *errnop)
79 {
80 name = name;
81 resultbuf = resultbuf;
82 buf = buf;
83 bufsize = bufsize;
84
85 if(NULL == (*result = gethostbyname(name))) {
86 *errnop = h_errno;
87 return(-1);
88 }
89 return(0);
90 }
91 #endif
92 karl 1.3
|
93 mday 1.2 PEGASUS_EXPORT String slp_get_addr_string_from_url(const String & url)
|
94 mday 1.1 {
|
95 mday 1.2 String s = String();
|
96 mday 1.1 struct sockaddr_in addr;
97 if( get_addr_from_url( url, &addr) ) {
|
98 mday 1.2 Sint8 *name = new Sint8[255];
|
99 mday 1.1 #ifdef _WIN32
|
100 mday 1.2 _snprintf(name, 254, "%s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port) );
|
101 mday 1.1 #else
|
102 mday 1.2 snprintf(name, 254, "%s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port) );
|
103 mday 1.1 #endif
|
104 mday 1.2 s += name;
105 delete [] name;
|
106 mday 1.1 }
|
107 mday 1.2 return(s);
|
108 mday 1.1 }
109
|
110 mday 1.2 PEGASUS_EXPORT Boolean get_addr_from_url(const String & url, struct sockaddr_in *addr )
|
111 mday 1.1 {
112 Sint8 *bptr, *url_dup;
113 Boolean ccode = false;
114
115 // isolate the host field
|
116 mday 1.2 bptr = (url_dup = url.allocateCString());
|
117 mday 1.1 if(bptr == NULL)
118 return(false );
119
120 while( (*bptr != '/') && (*bptr != 0x00) )
121 bptr++;
122
123 if(*bptr == '/' && *(bptr + 1) == '/') {
124 Sint8 *endptr, *portptr;
125 endptr = bptr + 2;
126 while (*endptr != 0x00 && *endptr != '/' && *endptr != ';')
127 endptr++;
128 *endptr = 0x00;
129 portptr = (endptr - 1) ;
130
131 while( ( portptr > ( bptr + 2 ) ) && ( *portptr != ':' ) )
132 portptr--;
133
134 if( *portptr == ':') {
135 *portptr = 0x00;
136 portptr++;
137 } else { portptr = NULL; }
138 mday 1.1
139 // bptr points to the host name or address
140 // portptr points to the port or is null
141
142 if (portptr != NULL)
143 addr->sin_port = htons( (Sint16)strtoul(portptr, NULL, 0) );
144 else
145 addr->sin_port = 0x0000;
146 addr->sin_family = AF_INET;
147
148 bptr += 2;
149 addr->sin_addr.s_addr = inet_addr(bptr);
150 if(addr->sin_addr.s_addr == INADDR_NONE) {
151 struct hostent *host;
152 struct hostent hostbuf;
153 Uint8 *temp ;
154 Uint32 result, err;
155 size_t hostbuflen = 256;
156
157 // hopefully a hostname because dotted decimal notation was invalid
158 // look for the user@hostname production
159 mday 1.1 Sint8 *userptr;
160 userptr = bptr;
161 while( (*userptr != 0x00 ) && (*userptr != '@' ) )
162 userptr++;
163 if( *userptr == '@' )
164 bptr = userptr + 1;
165
166 temp = (Uint8 *)malloc(hostbuflen);
167 if(temp != NULL) {
168 host = NULL;
169 while(temp != NULL && (result = gethostbyname_r(bptr, &hostbuf, (char *)temp, hostbuflen,
170 &host, (int *)&err)) == ERANGE){
171 hostbuflen *= 2;
172 temp = (Uint8 *)realloc(temp, hostbuflen);
173 }
174 if(host != NULL) {
175 struct in_addr *ptr;
176 if (((ptr = (struct in_addr *)*(host->h_addr_list)) != NULL ) ) {
177 addr->sin_addr.s_addr = ptr->s_addr;
178 ccode = true;
179 }
180 mday 1.1 }
181 free(temp);
182 } /* we allocated the temp buffer for gethostbyname */
183 } else { ccode = true; } /* host field is not in a valid dotted decimal form */
184 } /* isolated the host field in the url */
185 return(ccode);
186 }
187
188
|
189 mday 1.2 static Boolean slp_join_multicast(SOCKET sock, struct in_addr *addr)
190 {
191
192 // don't join on the loopback interface
193 if (addr->s_addr == inet_addr("127.0.0.1") )
194 return(false);
195
196 struct ip_mreq mreq;
197 mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.253");
198 mreq.imr_interface.s_addr = addr->s_addr;
199
200 if(SOCKET_ERROR == setsockopt(sock,IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq)))
201 return(false);
202 return(true);
203 }
204
205
206
207 static int slp_join_multicast_all(SOCKET sock)
208 {
209
210 mday 1.2
211 int num_interfaces = 0;
212
213 String host_name = slp_get_host_name();
214
215 if( 0 < host_name.size() ) {
216 struct hostent hostbuf;
217 struct hostent *host ;
218
219 int result = 0, err;
220 size_t hostbuf_len = 512;
221 Sint8 *hn = host_name.allocateCString( );
222 Sint8 *buf = (Sint8 *)malloc(hostbuf_len) ;
223 while( buf != NULL && ( result = gethostbyname_r( hn,
224 &hostbuf,
225 buf,
226 hostbuf_len,
227 &host,
228 &err) ) == ERANGE ) {
229 hostbuf_len *= 2;
230 buf = (Sint8 *)realloc(buf, hostbuf_len);
231 mday 1.2 } // realloc buffer loop
232
233 if((host != NULL) && (result == 0)) {
234 struct in_addr *ptr;
235 while ( ( ptr = (struct in_addr *) *(host->h_addr_list)++ ) != NULL ) {
236 if(true == slp_join_multicast(sock, ptr) )
237 num_interfaces++ ;
238 } // traversing address list
239 if(buf != NULL)
240 free(buf);
241 } // gethostnume succeeded
242 delete[] hn;
243 } // if allocated host buffer
244 return(num_interfaces);
245 }
246
247
248 static SOCKET slp_open_listen_sock( void )
249 {
250
251 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0) ;
252 mday 1.2 int err = 1;
253 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err));
254 struct sockaddr_in local;
255 local.sin_family = AF_INET;
256 local.sin_port = htons(427);
257 local.sin_addr.s_addr = INADDR_ANY;
258 bind(sock, (struct sockaddr *)&local, sizeof(local));
259 slp_join_multicast_all(sock);
260 return(sock);
261 }
262
|
263 mday 1.1
264 // static class members (windows only )
265 #ifdef _WIN32
266 int slp_client::_winsock_count = 0;
267 WSADATA slp_client::_wsa_data ;
268 #endif
269
|
270 mday 1.2
271 // insert new node at the back of the list
272 template<class L> void slp2_list<L>::insert(L *element)
|
273 mday 1.1 {
274 slp2_list *ins = new slp2_list(false);
275 ins->_rep = element;
|
276 mday 1.2 ins->_next = this;
277 ins->_prev = this->_prev;
278 this->_prev->_next = ins;
279 this->_prev = ins;
|
280 mday 1.1 _count++;
281 return;
282 }
283
284
285 template<class L> inline L *slp2_list<L>::next(L * init)
286 {
287 if( init == NULL )
288 _cur = _next;
289 else {
290 assert( init = _cur->_rep );
291 _cur = _cur->_next;
292 }
293 return(_cur->_rep);
294 }
295
296 template<class L> inline L *slp2_list<L>::prev( L * init )
297 {
298 if( init == NULL )
299 _cur = _next;
300 else {
301 mday 1.1 assert( init = _cur->rep ) ;
302 _cur = _cur->_prev;
303 }
304 return(_cur->_rep);
305 }
306
307 template<class L> inline int slp2_list<L>::count(void) { return(_count) ; }
308
309 template<class L> void slp2_list<L>::empty_list(void)
310 {
311 while( _count > 0 ) {
312 slp2_list *temp = _next;
313 temp->unlink();
314 if(temp->_rep != NULL)
315 delete temp->_rep;
316 delete temp;
317 _count--;
318 }
319 assert(_count == 0);
320 return;
321 }
322 mday 1.1
323
324 template<class L> L *slp2_list<L>::remove( void )
325 {
326 L *ret = NULL;
327 if( _count > 0 ) {
328 slp2_list *temp = _next;
329 temp->unlink();
330 ret = temp->_rep;
331 // unhinge ret from temp so it doesn't get destroyed
332 temp->_rep = NULL ;
333 delete temp;
334 _count--;
335 }
336 return(ret);
337 }
338
|
339 mday 1.2
340 template<class L> L *slp2_list<L>::remove(Sint8 *key)
341 {
342 L *ret = NULL;
343 if( _count > 0 ) {
344 slp2_list *temp = _next;
345 while ( temp->_isHead == false ) {
346 if( temp->_rep->operator==( key )) {
347 temp->unlink();
348 ret = temp->_rep;
349 temp->_rep = NULL;
350 delete temp;
351 _count--;
352 break;
353 }
354 temp = temp->_next;
355 }
356 }
357 return(ret);
358 }
359
360 mday 1.2
361 template<class L> Boolean slp2_list<L>::exists(Sint8 *key)
362 {
363 if( _count > 0) {
364 slp2_list *temp = _next;
365 while(temp->_isHead == false ) {
366 if( temp->_rep->operator==( key ))
367 return(true);
368 temp = temp->_next;
369 }
370 }
371 return(false);
372 }
373
374
|
375 mday 1.1 da_list::~da_list()
376 {
377 // unlink();
|
378 mday 1.2 delete[] url;
379 delete[] scope;
380 delete[] attr;
381 delete[] spi;
382 delete[] auth;
|
383 mday 1.1 }
384
385
|
386 mday 1.2 Boolean da_list::operator ==(const Sint8 *key) const
387 {
388 if( ! strcasecmp(url, key) )
389 return(true);
390 return(false);
391 }
|
392 mday 1.1
393 rply_list::~rply_list()
394 {
395 // unlink();
|
396 mday 1.2 delete[] url;
397 delete[] auth;
398 }
399
400
401 Boolean rply_list::operator ==(const Sint8 *key ) const
402 {
403 if (! strcasecmp(url, key) )
404 return(true);
405 return(false);
406 }
407
408
409 reg_list::~reg_list()
410 {
411 delete[] url;
412 delete[] attributes;
413 delete[] service_type;
414 delete[] scopes;
415 }
416
417 mday 1.2
418 Boolean reg_list::operator ==(const Sint8 *key ) const
419 {
420 if( ! strcasecmp(url, key) )
421 return(true);
422 return(false);
|
423 mday 1.1 }
424
425
426 void slp_client::set_target_addr(const Sint8 *addr)
427 {
428 if(addr == NULL)
429 _target_addr = inet_addr("239.255.255.253") ;
430 else
431 _target_addr = inet_addr(addr);
432 }
433
434 void slp_client::set_local_interface(const Sint8 *iface)
435 {
436
437 if(iface == NULL)
438 _local_addr = INADDR_ANY;
439 else
440 _local_addr = inet_addr(iface);
441 }
442
443 void slp_client::set_spi(const Sint8 *spi)
444 mday 1.1 {
445 if(_spi != NULL)
446 free(_spi);
447 if(spi != NULL)
448 _spi = strdup(spi);
449 else
450 _spi = NULL;
451 return ;
452 }
453
454 slp_client::slp_client(const Sint8 *target_addr,
455 const Sint8 *local_addr,
456 Uint16 target_port,
457 const Sint8 *spi )
458
|
459 mday 1.2 : _pr_buf_len(0), _buf_len (LSLP_MTU), _version((Uint8)1),
460 _xid(1), _target_port(target_port), _spi(NULL), _use_das(false),
461 _last_da_cycle(0), _retries(3), _ttl(255), _convergence(1),
462 _crypto_context(NULL), das( ), replies( ), regs( )
|
463 mday 1.1
464 {
465 set_target_addr(target_addr);
466 set_local_interface(local_addr);
467 set_spi(spi);
|
468 mday 1.2 _pr_buf = new Sint8[LSLP_MTU];
469 _msg_buf = new Sint8[LSLP_MTU] ;
470 _rcv_buf = new Sint8[LSLP_MTU] ;
|
471 mday 1.1 _tv.tv_sec = 1;
472 _tv.tv_usec = 0;
473 #ifdef _WIN32
474 if(_winsock_count == 0)
475 WSAStartup(0x0002, &_wsa_data);
476 _winsock_count++;
477 #endif
|
478 mday 1.2
479 // initialize the recieve socket
480 _rcv_sock = slp_open_listen_sock( );
|
481 mday 1.1 }
482
483
484 slp_client::~slp_client()
485 {
|
486 mday 1.2 // close the receive socket
487
488
489 #ifdef _WIN32
490 _winsock_count--;
491 if(_winsock_count == 0)
492 WSACleanup();
493 #endif
494
495 delete _pr_buf;;
496 delete _msg_buf;
497 delete _rcv_buf;
|
498 mday 1.1 if(_spi != NULL)
499 free(_spi);
500 if(_crypto_context != NULL)
501 free(_crypto_context);
502 das.empty_list();
503 replies.empty_list();
|
504 mday 1.2
|
505 mday 1.1 }
506
507
508 void slp_client::prepare_pr_buf(const Sint8 *a)
509 {
510 if(a == NULL)
511 return;;
512 if(_pr_buf_len > 0)
513 *(_pr_buf + _pr_buf_len - 1) = ',' ;
514 do {
515 *(_pr_buf + _pr_buf_len) = *a;
516 a++;
517 _pr_buf_len++;
518 }while((*a != 0x00) && (_pr_buf_len < LSLP_MTU - 1));
519 _pr_buf_len++;
520 }
521
522 Boolean slp_client::prepare_query( Uint16 xid,
523 const Sint8 *service_type,
524 const Sint8 *scopes,
525 const Sint8 *predicate )
526 mday 1.1 {
527 Sint16 len, total_len;
528 Sint8 *bptr;
529 if(_msg_buf == NULL || _pr_buf == NULL)
530 return(false);
531 if(xid != _xid) {
532 /* this is a new request */
533 memset(_pr_buf, 0x00, LSLP_MTU);
534 _pr_buf_len = 0;
535 _xid = xid;
536 }
537 memset(_msg_buf, 0x00, LSLP_MTU);
538 bptr = _msg_buf;
539 _LSLP_SETVERSION(bptr, LSLP_PROTO_VER);
540 _LSLP_SETFUNCTION(bptr, LSLP_SRVRQST);
541 /* we don't know the length yet */
542 _LSLP_SETFLAGS(bptr, LSLP_FLAGS_MCAST);
543 _LSLP_SETXID(bptr, xid);
544 _LSLP_SETLAN(bptr, LSLP_EN_US);
545 bptr += ( total_len = _LSLP_HDRLEN(bptr) ) ;
546
547 mday 1.1 if(_pr_buf_len + total_len < LSLP_MTU) {
548 /* set the pr list length */
549 _LSLP_SETSHORT(bptr, (len = _pr_buf_len), 0);
550 if(len)
551 memcpy(bptr + 2, _pr_buf, len);
552 total_len += ( 2 + len );
553 bptr += (2 + len);
554
555 if(service_type == NULL)
556 len = DA_SRVTYPELEN;
557 else
558 len = strlen(service_type) + 1;
559 if(total_len + 2 + len < LSLP_MTU) {
560 /* set the service type string length */
561 _LSLP_SETSHORT(bptr, len, 0);
562 if(service_type != NULL)
563 memcpy(bptr + 2, service_type, len);
564 else
565 memcpy(bptr + 2, DA_SRVTYPE, len);
566
567 total_len += (2 + len);
568 mday 1.1 bptr += (2 + len);
569
570 /* set the scope len and scope type, advance the buffer */
571
572 if(scopes == NULL)
573 len = DA_SCOPELEN;
574 else
575 len = strlen(scopes) + 1;
576 if( total_len + 2 + len < LSLP_MTU) {
577 _LSLP_SETSHORT(bptr, len, 0);
578 if(scopes != NULL)
579 memcpy(bptr + 2, scopes, len);
580 else
581 memcpy(bptr + 2, DA_SCOPE, DA_SCOPELEN);
582
583 total_len += ( 2 + len);
584 bptr += (2 + len);
585
586 /* stuff the predicate if there is one */
587 if(predicate == NULL)
588 len = 0;
589 mday 1.1 else
590 len = strlen(predicate) + 1;
591 if( total_len + 2 + len < LSLP_MTU) {
592 _LSLP_SETSHORT(bptr, len, 0);
593 if(predicate != NULL)
594 memcpy(bptr + 2, predicate, len);
595
596 total_len += (2 + len);
597 bptr += (2 + len);
598
599 /* stuff the spi */
600
601 /* set the spi len and spi string */
602 if(_spi == NULL)
603 len = 0;
604 else
605 len = strlen(_spi) + 1;
606
607 if(total_len + 2 + len < LSLP_MTU) {
608 _LSLP_SETSHORT(bptr, len, 0);
609
610 mday 1.1 if(_spi != NULL)
611 memcpy(bptr + 2, _spi, len);
612
613 total_len += ( 2 + len);
614 bptr += (2 + len);
615 assert(total_len == bptr - _msg_buf);
616 /* now go back and set the length for the entire message */
617 _LSLP_SETLENGTH(_msg_buf, total_len );
618 return(true);
619 } /* room for the spi */
620 } /* room for predicate */
621 } /* room for the scope */
622 } /* room for the service type */
623 } /* room for the pr list */
624 return(false);
625 }
626
627
628 rply_list *slp_client::get_response( void )
629 {
630
631 mday 1.1 rply_list *ret = replies.remove();
632 return(ret);
633 }
634
635
636 int slp_client::find_das(const Sint8 *predicate,
637 const Sint8 *scopes)
638 {
639 converge_srv_req(NULL, predicate, scopes);
|
640 mday 1.2 time(&_last_da_cycle);
641 if(0 < das.count() )
642 _use_das = true;
643 else
644 _use_das = false;
|
645 mday 1.1 return( das.count( ) );
646 }
647
648 int slp_client::converge_srv_req( const Sint8 *type,
649 const Sint8 *predicate,
650 const Sint8 *scopes)
651 {
652
653 Uint32 old_addr = _target_addr;
654 set_target_addr( "239.255.255.253" ) ;
655 srv_req( type, predicate, scopes ) ;
656 _target_addr = old_addr;
657
658 return( replies.count( ) );
659 }
660
661
662 void slp_client::srv_req( const Sint8 *type,
663 const Sint8 *predicate,
664 const Sint8 *scopes)
665 {
666 mday 1.1 if ((true == prepare_query( _xid + 1, type, scopes, predicate ))) {
667 replies.empty_list();
668 Uint16 convergence = _convergence;
669 if(convergence-- > 0) { _LSLP_SETFLAGS( _msg_buf, LSLP_FLAGS_MCAST) ; }
670 send_rcv_udp( ) ;
671 while(convergence-- > 0) {
672 _LSLP_SLEEP( _tv.tv_usec / 1000 ) ;
673 if(prepare_query( _xid, type, scopes, predicate)) {
674 _LSLP_SETFLAGS(_msg_buf, LSLP_FLAGS_MCAST) ;
675 send_rcv_udp( );
676 }
677 }
678 /* if this was a multicast request try it on the local machine too */
679 if(_convergence) {
680 /* save current settings */
681 Sint8 convergence_save = _convergence;
682 Uint32 target_save = _target_addr;
683 _convergence = 0;
684 _target_addr = inet_addr("127.0.0.1" ) ;
685 if ((true == prepare_query( _xid + 1, type, scopes, predicate ))) {
686 _LSLP_SETFLAGS( _msg_buf, 0 );
687 mday 1.1 send_rcv_udp( );
688 }
689 /* restore current settings */
690 _convergence = convergence_save;
691 _target_addr = target_save;
692 } /* if we need to do the query on the local machine */
693 } /* prepared query */
694 memset( _msg_buf, 0x00, LSLP_MTU);
695 return ;
696 }
697
698 void slp_client::decode_reply( struct sockaddr_in *remote )
699 {
700
|
701 mday 1.2 if( _xid == _LSLP_GETXID( _rcv_buf ))
702 prepare_pr_buf( inet_ntoa(remote->sin_addr) );
703
704 Sint8 function = _LSLP_GETFUNCTION( _rcv_buf );
705 switch(function) {
706 case LSLP_DAADVERT:
707 decode_daadvert( remote );
708 return;
709 case LSLP_SRVRPLY:
710 decode_srvrply( remote );
711 return;
712 case LSLP_SRVACK:
713 default:
714 break;
715 }
|
716 mday 1.1 return;
717 }
718
719
720 void slp_client::decode_srvrply( struct sockaddr_in *remote )
721 {
722 Sint8 *bptr;
723 Sint16 str_len, err, count;
724 Sint32 total_len, purported_len;
725
|
726 mday 1.2 bptr = _rcv_buf;
|
727 mday 1.1 purported_len = _LSLP_GETLENGTH(bptr);
728 bptr += (total_len = _LSLP_HDRLEN(bptr));
729 if(total_len < purported_len) {
730 rply_list *reply = new rply_list();
731 if(reply == NULL) abort();
732 err = _LSLP_GETSHORT(bptr, 0);
733 count = _LSLP_GETSHORT(bptr, 2);
734 bptr += 4;
735 total_len += 4;
736 /* loop on the url entries */
737 while( ( total_len <= purported_len ) && ( count > 0 ) && reply != NULL ) {
738 reply->function = LSLP_SRVRPLY;
739 reply->err = err;
740 reply->lifetime = _LSLP_GETSHORT(bptr, 1);
741 total_len += (5 + (str_len = _LSLP_GETSHORT(bptr, 3)));
742 if(total_len <= purported_len) {
743 Sint8 num_auths;
744 if(str_len > 0) {
|
745 mday 1.2 reply->url = new Sint8[str_len + 1];
746 memcpy(reply->url, bptr + 5, str_len);
747 *((reply->url) + str_len) = 0x00;
|
748 mday 1.1 bptr += (5 + str_len);
749 reply->auth_blocks = (num_auths = _LSLP_GETBYTE(bptr, 0));
750 total_len += 1;
751 bptr += 1;
752 while(num_auths && (total_len <= purported_len )) {
753 /* iterate past the authenticators for now */
754 /* need extra code here to authenticate url entries */
755 total_len += (str_len = _LSLP_GETSHORT(bptr, 2));
756 bptr += str_len;
757 num_auths--;
758 }
|
759 mday 1.2 // handling duplicate responses is really inefficient, and we're
760 // not helping things out by checking for dupes this late in the game
761 // however, in order to get to any further urls that may be in the
762 // reply buffer we need to unstuff it anyway. So we are optimizing
763 // for the case where there are no dupes.
764 if( false == replies.exists(reply->url) ) {
765 strcpy(&(reply->remote[0]), inet_ntoa( remote->sin_addr )) ;
766 replies.insert(reply);
767 } else { delete reply ; }
|
768 mday 1.1 count--;
769 if((total_len <= purported_len) && (count > 0) )
770 reply = new rply_list( );
771 else
772 reply = NULL;
773 } else { delete reply; reply = NULL ; } /* bad packet */
774 } else { delete reply; reply = NULL ; } /* bad packet */
775 } // while unwrapping multi-response message
776 } /* if the hdr length field is consistent with reality */
777 return;
778 }
779
780
781 void slp_client::decode_daadvert(struct sockaddr_in *remote)
782 {
783 Sint8 *bptr;
784 Sint16 str_len;
785 Sint32 total_len, purported_len;
786
|
787 mday 1.2 bptr = _rcv_buf;
|
788 mday 1.1 purported_len = _LSLP_GETLENGTH(bptr);
789 bptr += (total_len = _LSLP_HDRLEN(bptr));
790 if(total_len < purported_len) {
791 da_list *adv = new da_list( );
792 if(adv == NULL) abort();
793
794 adv->function = LSLP_DAADVERT;
795 adv->err = _LSLP_GETSHORT(bptr, 0);
796 adv->stateless_boot = _LSLP_GETLONG(bptr, 2);
797 total_len += (8 + (str_len = _LSLP_GETSHORT(bptr, 6)));
798 if(total_len < purported_len) {
799 /* decode and capture the url - note: this is a string, not a url-entry structure */
|
800 mday 1.2 adv->url = new Sint8[str_len + 1] ;
801 memcpy(adv->url, bptr + 8, str_len);
802 *((adv->url) + str_len) = 0x00;
803 /* advance the pointer past the url string */
804 bptr += (str_len + 8);
805 total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
806 if(total_len < purported_len) {
807 if(str_len > 0) {
808 adv->scope = new Sint8[str_len + 1] ;
809 memcpy(adv->scope, bptr + 2, str_len);
810 *((adv->scope) + str_len) = 0x00;
811 }
812 /* advance the pointer past the scope string */
813 bptr += (str_len + 2);
|
814 mday 1.1 total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
815 if(total_len < purported_len) {
816 if(str_len > 0) {
|
817 mday 1.2 adv->attr = new Sint8[str_len + 1] ;
818 memcpy(adv->attr, bptr + 2, str_len);
819 *((adv->attr) + str_len) = 0x00;
|
820 mday 1.1 }
|
821 mday 1.2 /* advance the pointer past the attr string */
|
822 mday 1.1 bptr += (str_len + 2);
823 total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
824 if(total_len < purported_len) {
|
825 mday 1.2 if(str_len > 0 ) {
826 adv->spi = new Sint8[str_len + 1];
827 memcpy(adv->spi, bptr + 2, str_len);
828 *((adv->spi) + str_len) = 0x00;
829 } /* if there is an spi */
830
831 /* advance the pointer past the spi string */
|
832 mday 1.1 bptr += (str_len + 2);
|
833 mday 1.2 adv->auth_blocks = _LSLP_GETBYTE(bptr, 0);
834
835 // if we already know about this da, remove the existing
836 // entry from our cache and insert this new entry
837 // maybe the stateless boot field changed or the da
838 // supports new scopes, etc.
839 da_list * exists = das.remove(adv->url);
840 delete exists;
841
842 /* need code here to handle authenticated urls */
843 strcpy(&(adv->remote[0]), inet_ntoa(remote->sin_addr)) ;
844 das.insert(adv);
845 return;
846 } /* spi length field is consistent with hdr */
847 } /* attr length field is consistent with hdr */
848 } /* scope length field is consistent with hdr */
|
849 mday 1.1 }
850 }
851 return;
852 }
853
854
855 Boolean slp_client::srv_reg(Sint8 *url,
856 Sint8 *attributes,
857 Sint8 *service_type,
858 Sint8 *scopes,
859 Sint16 lifetime)
860 {
861 Sint32 len;
862 Sint16 str_len;
863 Sint8 *bptr;
864
865
866 /* this is always a new request */
867 memset( _pr_buf, 0x00, LSLP_MTU);
868 _pr_buf_len = 0;
869 _xid++ ;
870 mday 1.1
871 memset(_msg_buf, 0x00, LSLP_MTU);
872 bptr = _msg_buf;
873 _LSLP_SETVERSION(bptr, LSLP_PROTO_VER);
874 _LSLP_SETFUNCTION(bptr, LSLP_SRVREG);
875 /* we don't know the length yet */
876 _LSLP_SETXID(bptr, _xid);
877 _LSLP_SETLAN(bptr, LSLP_EN_US);
878 bptr += (len = _LSLP_HDRLEN(bptr) ) ;
879
880 /* construct a url-entry */
881
882 _LSLP_SETSHORT(bptr, lifetime, 1);
883 _LSLP_SETSHORT(bptr, (str_len = (strlen(url) + 1)), 3);
884 len += (5 + str_len );
885 if(len + 1 < LSLP_MTU ) {
886 memcpy(bptr + 5, url, str_len);
887 bptr += (5 + str_len);
888 /* no auth blocks for now */
889 _LSLP_SETBYTE(bptr, 0x00, 0);
890 bptr++;
891 mday 1.1 len++;
892 /* stuff the service type */
893 str_len = strlen(service_type) + 1;
894 if(len + 2 + str_len < LSLP_MTU) {
895 _LSLP_SETSHORT(bptr, str_len, 0);
896 memcpy(bptr + 2, service_type, str_len);
897 bptr += (2 + str_len);
898 len += (2 + str_len);
899 /* stuff the scope list if there is one */
900 if(scopes == NULL)
901 str_len = 0;
902 else
903 str_len = strlen(scopes) + 1;
904 if(str_len == 1)
905 str_len = 0;
906 if(len + 2 + str_len < LSLP_MTU) {
907 _LSLP_SETSHORT(bptr, str_len, 0);
908 if(str_len)
909 memcpy(bptr + 2, scopes, str_len);
910
911 len += (2 + str_len);
912 mday 1.1 bptr += (2 + str_len);
913 /* stuff the attribute string if there is one */
914 if(attributes == NULL)
915 str_len = 0;
916 else
917 str_len = strlen(attributes) + 1;
918 if(str_len == 1)
919 str_len = 0;
920 if(len + 2 + str_len < LSLP_MTU) {
921 _LSLP_SETSHORT(bptr, str_len, 0);
922 if(str_len)
923 memcpy(bptr + 2, attributes, str_len);
924
925 len += ( 2 + str_len);
926 bptr += (2 + str_len);
927
928 /* no attribute auths for now */
929 if(len + 1 < LSLP_MTU) {
930 _LSLP_SETBYTE(bptr, 0x00, 0);
931 }
932 len += 1;
933 mday 1.1 /* set the length field in the header */
934 _LSLP_SETLENGTH( _msg_buf, len );
935 if(true == send_rcv_udp( )) {
|
936 mday 1.2 if(LSLP_SRVACK == _LSLP_GETFUNCTION( _rcv_buf )) {
937 if(0x0000 == _LSLP_GETSHORT( _rcv_buf, (_LSLP_HDRLEN( _rcv_buf )))) {
|
938 mday 1.1 memset(_msg_buf, 0x00, LSLP_MTU);
939 return(true);
940 }
941 }
942 }
943 } /* attribute string fits into buffer */
944 } /* scope string fits into buffer */
945 } /* service type fits into buffer */
946 } /* url fits into buffer */
947 memset( _msg_buf, 0x00, LSLP_MTU);
948 return(false);
949 }
950
951
952
953 Boolean slp_client::send_rcv_udp( void )
954 {
955 SOCKET sock;
956 struct sockaddr_in target, local;
957 Boolean ccode = false;
958 if(INVALID_SOCKET != (sock = socket(AF_INET, SOCK_DGRAM, 0))) {
959 mday 1.1 int err = 1;
960 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err) );
961
962 local.sin_family = AF_INET;
963 local.sin_port = 0;
964 local.sin_addr.s_addr = _local_addr;
965 if(SOCKET_ERROR != bind(sock, (struct sockaddr *)&local, sizeof(local))) {
966 int bcast = ( (_LSLP_GETFLAGS(_msg_buf)) & LSLP_FLAGS_MCAST) ? 1 : 0 ;
967 if(bcast) {
968 if( (SOCKET_ERROR == _LSLP_SET_TTL(sock, _ttl) ) ||
969 (SOCKET_ERROR == setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const Sint8 *)&bcast, sizeof(bcast)))) {
970 _LSLP_CLOSESOCKET(sock);
971 return(false);
972 }
973 if(_local_addr != INADDR_ANY ) {
974 struct sockaddr_in ma;
975 memset(&ma, 0x00, sizeof(ma));
976 ma.sin_addr.s_addr = _local_addr;
977 if( (SOCKET_ERROR == setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&ma, sizeof(struct sockaddr_in))) ) {
978 _LSLP_CLOSESOCKET(sock);
979 return(false);
980 mday 1.1 }
981 }
982 }
983 target.sin_family = AF_INET;
984 target.sin_port = htons(_target_port);
985 target.sin_addr.s_addr = _target_addr;
986 if(SOCKET_ERROR == (err = sendto(sock,
987 _msg_buf,
988 _LSLP_GETLENGTH(_msg_buf),
989 0,
990 (struct sockaddr *)&target, sizeof(target) ))) {
991 _LSLP_CLOSESOCKET(sock);
992 return(false);
993 } /* oops - error sending data */
|
994 mday 1.2 if(bcast)
995 service_listener_wait(_convergence, sock, false) ;
996 else
997 service_listener_wait(_convergence, sock, true);
998 } // bound the socket
|
999 mday 1.1 _LSLP_CLOSESOCKET(sock);
1000 } /* got the socket */
1001 return(ccode);
1002 }
1003
|
1004 mday 1.2 // must be called regularly to process responses
1005
1006 Sint32 slp_client::service_listener(void)
1007 {
1008 return service_listener((SOCKET) 0);
1009 }
1010
1011
1012 Sint32 slp_client::service_listener_wait(time_t wait, SOCKET extra_sock, Boolean one_only)
1013 {
1014 Sint32 rcv = 0;
1015 time_t now;
1016 time_t start = time(NULL);
1017
1018 while( time(&now) && ((now - wait ) <= start ) ) {
1019 rcv += service_listener(extra_sock);
1020 if(rcv > 0)
1021 if(one_only == true)
1022 return(rcv);
1023 _LSLP_SLEEP(10);
1024 }
1025 mday 1.2 rcv += service_listener(extra_sock);
1026 return(rcv);
1027 }
1028
1029 Sint32 slp_client::service_listener(SOCKET extra_sock )
1030 {
1031
1032 fd_set fds;
1033 struct timeval tv = {0, 10};
1034 FD_ZERO(&fds);
1035 FD_SET(_rcv_sock, &fds);
1036 if(extra_sock)
1037 FD_SET( extra_sock, &fds);
1038 Sint32 err;
1039 do {
1040 err = select(_rcv_sock > extra_sock ? _rcv_sock + 1: extra_sock + 1, &fds, NULL, NULL, &tv);
1041 } while ( (err < 0 )&& (errno == EINTR)) ;
1042 if( 0 < err ) {
1043 struct sockaddr_in remote;
1044 int size = sizeof(remote);
1045 if(extra_sock && FD_ISSET(extra_sock, &fds) ) {
|
1046 karl 1.3 #ifdef PEGASUS_OS_HPUX
1047 err = recvfrom(extra_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, &size);
1048 #else
|
1049 mday 1.2 err = recvfrom(extra_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, (socklen_t *)&size);
|
1050 karl 1.3 #endif
|
1051 mday 1.2 if(err && err != SOCKET_ERROR)
1052 decode_reply( &remote );
1053 }
1054 if(FD_ISSET(_rcv_sock, &fds)) {
|
1055 karl 1.3 #ifdef PEGASUS_OS_HPUX
1056 err = recvfrom(_rcv_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, &size);
1057 #else
|
1058 mday 1.2 err = recvfrom(_rcv_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, (socklen_t *)&size);
|
1059 karl 1.3 #endif
|
1060 mday 1.2 if(err && err != SOCKET_ERROR)
1061 decode_reply( &remote );
1062 }
1063 }
1064 return(err);
1065 }
1066
|
1067 mday 1.1 int slp_client::srv_reg_all( Sint8 *url,
1068 Sint8 *attributes,
1069 Sint8 *service_type,
1070 Sint8 *scopes,
1071 Sint16 lifetime)
1072 {
1073
1074 assert(url != NULL && attributes != NULL && service_type != NULL && scopes != NULL);
1075 if(url == NULL || attributes == NULL || service_type == NULL || scopes == NULL )
1076 return(0);
1077
1078 // see if we have built a cache of directory agents
1079 if( 0 == das.count() ) {
1080 // we don't know of any directory agents - see if we can find some
1081 if( 0 == find_das(NULL, scopes) )
1082 return(0);
1083 }
1084
1085 // unicast a srvreg to each da
1086 int registrations = 0;
1087 Uint32 target_addr_save = _target_addr;
1088 mday 1.1 int convergence_save = _convergence;
1089 _convergence = 0;
1090
1091 da_list *da = das.next(NULL);
1092 while( da != NULL ) {
1093 set_target_addr(da->remote);
1094 if( true == srv_reg( url, attributes, service_type, scopes, lifetime) )
1095 registrations++;
1096 da = das.next(da);;
1097 }
1098
1099 /* now try to register with the local host */
1100 set_target_addr("127.0.0.1");
1101 if(true == srv_reg( url, attributes, service_type, scopes, lifetime) )
1102 registrations++;
1103
1104 _convergence = convergence_save;
1105 _target_addr = target_addr_save;
1106
1107 return(registrations);
1108 }
1109 mday 1.1
1110
1111 PEGASUS_NAMESPACE_END
|