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 mike 1.5 #include "slp.h"
31
32 #ifdef PEGASUS_OS_TRU64
33 # include <unistd.h>
34 extern "C" void usleep(unsigned int);
35 #endif
|
36 mday 1.1
37
38 PEGASUS_USING_STD;
39
40 PEGASUS_NAMESPACE_BEGIN
41
|
42 mday 1.2 PEGASUS_EXPORT String slp_get_host_name(void)
|
43 mday 1.1 {
|
44 mday 1.2
45 String s = String();
46 Sint8 *buf = new Sint8[255];
47 if( 0 == gethostname(buf, 254) )
48 s += buf;
49 delete buf;
50 return(s);
|
51 mday 1.1 }
52
53
54 #ifdef _WIN32
55 PEGASUS_EXPORT int gethostbyname_r(const char *name,
56 struct hostent *resultbuf,
57 char *buf,
58 size_t bufsize,
59 struct hostent **result,
60 int *errnop)
61 {
62 name = name;
63 resultbuf = resultbuf;
64 buf = buf;
65 bufsize = bufsize;
66
67 if(NULL == (*result = gethostbyname(name))) {
68 *errnop = WSAGetLastError();
69 return(-1);
70 }
71 return(0);
72 mday 1.1 }
73
74 #endif
75
|
76 mike 1.5 #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_TRU64)
|
77 karl 1.3
78 PEGASUS_EXPORT int gethostbyname_r(const char *name,
79 struct hostent *resultbuf,
80 char *buf,
81 size_t bufsize,
82 struct hostent **result,
83 int *errnop)
84 {
85 name = name;
86 resultbuf = resultbuf;
87 buf = buf;
88 bufsize = bufsize;
89
90 if(NULL == (*result = gethostbyname(name))) {
91 *errnop = h_errno;
92 return(-1);
93 }
94 return(0);
95 }
|
96 mike 1.5
|
97 karl 1.3 #endif
98
|
99 mday 1.4 PEGASUS_EXPORT void slp_get_addr_string_from_url(const Sint8 *url, String &addr)
|
100 mday 1.1 {
|
101 mday 1.4 Sint8 *name = NULL;
102 struct sockaddr_in a;
103 if( get_addr_from_url( url, &a, NULL) ) {
104 name = new Sint8 [ 255 ] ;
|
105 mday 1.1 #ifdef _WIN32
|
106 mday 1.4 _snprintf(name, 254, "%s:%d", inet_ntoa(a.sin_addr), ntohs(a.sin_port) );
|
107 mday 1.1 #else
|
108 mike 1.5
109 // ATTN: Mike Brasher: Hack to get built of TRU64:
110 #ifdef PEGASUS_OS_TRU64
111 sprintf(name, "%s:%d", inet_ntoa(a.sin_addr), ntohs(a.sin_port) );
112 #else
|
113 mday 1.4 snprintf(name, 254, "%s:%d", inet_ntoa(a.sin_addr), ntohs(a.sin_port) );
|
114 mday 1.1 #endif
|
115 mike 1.5
116 #endif
|
117 mday 1.4 addr.clear();
118 addr = name;
|
119 mday 1.2 delete [] name;
|
120 mday 1.1 }
|
121 mday 1.4 return ;
122 }
123
124 PEGASUS_EXPORT void slp_get_host_string_from_url(const Sint8 *url, String &host)
125 {
126 Sint8 *s;
127 struct sockaddr_in addr;
128 get_addr_from_url(url, &addr, &s );
129 host.clear();
130 host = s;
131 delete [] s;
132 return ;
|
133 mday 1.1 }
134
|
135 mday 1.4 PEGASUS_EXPORT Boolean get_addr_from_url(const Sint8 *url, struct sockaddr_in *addr, Sint8 **host)
|
136 mday 1.1 {
137 Sint8 *bptr, *url_dup;
138 Boolean ccode = false;
139
140 // isolate the host field
|
141 mday 1.4 bptr = (url_dup = strdup(url));
|
142 mday 1.1 if(bptr == NULL)
143 return(false );
144
145 while( (*bptr != '/') && (*bptr != 0x00) )
146 bptr++;
147
148 if(*bptr == '/' && *(bptr + 1) == '/') {
149 Sint8 *endptr, *portptr;
150 endptr = bptr + 2;
151 while (*endptr != 0x00 && *endptr != '/' && *endptr != ';')
152 endptr++;
153 *endptr = 0x00;
154 portptr = (endptr - 1) ;
155
156 while( ( portptr > ( bptr + 2 ) ) && ( *portptr != ':' ) )
157 portptr--;
158
159 if( *portptr == ':') {
160 *portptr = 0x00;
161 portptr++;
162 } else { portptr = NULL; }
163 mday 1.1
164 // bptr points to the host name or address
165 // portptr points to the port or is null
166
|
167 mday 1.4 bptr += 2;
168
169 if(host != NULL) {
170 *host = new Sint8[ strlen(bptr) + strlen(portptr) + 3] ;
171 strcpy(*host, bptr);
172 strcat(*host, ":");
173 strcat(*host, portptr);
174 }
|
175 mday 1.1 if (portptr != NULL)
176 addr->sin_port = htons( (Sint16)strtoul(portptr, NULL, 0) );
177 else
178 addr->sin_port = 0x0000;
179 addr->sin_family = AF_INET;
180
|
181 mday 1.4
|
182 mday 1.1 addr->sin_addr.s_addr = inet_addr(bptr);
183 if(addr->sin_addr.s_addr == INADDR_NONE) {
184 struct hostent *host;
185 struct hostent hostbuf;
186 Uint8 *temp ;
187 Uint32 result, err;
188 size_t hostbuflen = 256;
189
190 // hopefully a hostname because dotted decimal notation was invalid
191 // look for the user@hostname production
192 Sint8 *userptr;
193 userptr = bptr;
194 while( (*userptr != 0x00 ) && (*userptr != '@' ) )
195 userptr++;
196 if( *userptr == '@' )
197 bptr = userptr + 1;
198
199 temp = (Uint8 *)malloc(hostbuflen);
200 if(temp != NULL) {
201 host = NULL;
|
202 mike 1.5 while(temp != NULL && (result = gethostbyname_r(bptr, &hostbuf,
203 (char *)temp,
204 hostbuflen,
205 &host, (int *)&err)) == ERANGE){
|
206 mday 1.1 hostbuflen *= 2;
207 temp = (Uint8 *)realloc(temp, hostbuflen);
208 }
209 if(host != NULL) {
210 struct in_addr *ptr;
211 if (((ptr = (struct in_addr *)*(host->h_addr_list)) != NULL ) ) {
212 addr->sin_addr.s_addr = ptr->s_addr;
213 ccode = true;
214 }
215 }
216 free(temp);
217 } /* we allocated the temp buffer for gethostbyname */
218 } else { ccode = true; } /* host field is not in a valid dotted decimal form */
219 } /* isolated the host field in the url */
220 return(ccode);
221 }
222
223
|
224 mday 1.4
225 static int slp_get_local_interfaces(Uint32 **list)
226 {
227 SOCKET sock;
228 int interfaces = 0;
229
230 delete [] *list;
231
232 #ifdef PEGASUS_OS_TYPE_WINDOWS
233
234 if ( INVALID_SOCKET != ( sock = WSASocket(AF_INET,
235 SOCK_RAW, 0, NULL, 0, 0) ) ) {
236 char *output_buf = new char[1024];
237 DWORD buf_size = 1024, bytes_returned = 0;
238
239 if ( 0 == WSAIoctl( sock, SIO_ADDRESS_LIST_QUERY, NULL, 0,
240 output_buf, buf_size, &bytes_returned, NULL, NULL) ) {
241 socket_addr_list *addr_list = (socket_addr_list *)output_buf;
242 *list = new Uint32 [ addr_list->count + 1 ] ;
243 socket_addr *addr = addr_list->list;
244 Uint32 *intp;
245 mday 1.4 sockaddr_in *sin;
246 for( interfaces = 0, intp = *list, sin = (sockaddr_in *)addr ;
247 interfaces < addr_list->count;
248 interfaces++ , intp++ ) {
249 *intp = sin->sin_addr.s_addr;
250 addr++;
251 sin = (sockaddr_in *)addr;
252 }
253 *intp = INADDR_ANY;
254 }
255 delete [] output_buf;
256 _LSLP_CLOSESOCKET(sock);
257 }
258
259 #else
260 if( -1 < (sock = socket(AF_INET, SOCK_DGRAM, 0) ) ) {
261 struct ifconf conf;
262
263 conf.ifc_buf = new char [ 128 * sizeof(struct ifreq ) ];
264 conf.ifc_len = 128 * sizeof( struct ifreq ) ;
265 if( -1 < ioctl(sock, SIOCGIFCONF, &conf ) ) {
266 mday 1.4
267 // count the interfaces
268
269
270 struct ifreq *r = conf.ifc_req;
271 struct sockaddr_in *addr ;
272 addr = (struct sockaddr_in *)&r->ifr_addr;
273 while( addr->sin_addr.s_addr != 0 ) {
274 interfaces++;
275 r++;
276 addr = (struct sockaddr_in *)&r->ifr_addr;
277 }
278
279 // now store the addresses
280
281 *list = new Uint32 [interfaces + 1 ];
282 Uint32 *this_addr = *list;
283 r = conf.ifc_req;
284 addr = (struct sockaddr_in *)&r->ifr_addr;
285 while( addr->sin_addr.s_addr != 0 ) {
286 *this_addr = addr->sin_addr.s_addr;
287 mday 1.4 r++;
288 this_addr++;
289 addr = (struct sockaddr_in *)&r->ifr_addr;
290 }
291 *this_addr = INADDR_ANY;
292 } // did the ioctl
293 delete [] conf.ifc_buf;
294 _LSLP_CLOSESOCKET(sock);
295 } // opened the socket
296
297 #endif
298 // failsafe if the ioctl doesn't work
299 if( interfaces == 0 ) {
300 *list = new Uint32 [1] ;
301 *list[0] = INADDR_ANY;
302 }
303
304 return(interfaces);
305 }
306
307
308 mday 1.4 static Boolean slp_join_multicast(SOCKET sock, Uint32 addr)
|
309 mday 1.2 {
310
311 // don't join on the loopback interface
|
312 mday 1.4 if (addr == inet_addr("127.0.0.1") )
|
313 mday 1.2 return(false);
314
315 struct ip_mreq mreq;
316 mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.253");
|
317 mday 1.4 mreq.imr_interface.s_addr = addr;
|
318 mday 1.2
319 if(SOCKET_ERROR == setsockopt(sock,IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq)))
320 return(false);
321 return(true);
322 }
323
324
325
326 static int slp_join_multicast_all(SOCKET sock)
327 {
328
|
329 mday 1.4 Uint32 *list = NULL , *lptr = NULL;
330 int num_interfaces = slp_get_local_interfaces(&list);
331 lptr = list;
332 while ( *lptr != INADDR_ANY ) {
333 slp_join_multicast(sock, *lptr) ;
334 lptr++;
335 }
336 delete [] list;
|
337 mday 1.2 return(num_interfaces);
338 }
339
340
|
341 mday 1.4 static SOCKET slp_open_listen_sock( void )
|
342 mday 1.2 {
343
344 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0) ;
345 int err = 1;
346 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err));
347 struct sockaddr_in local;
348 local.sin_family = AF_INET;
349 local.sin_port = htons(427);
350 local.sin_addr.s_addr = INADDR_ANY;
|
351 mday 1.4 if( 0 == bind(sock, (struct sockaddr *)&local, sizeof(local)) )
352 slp_join_multicast_all(sock);
|
353 mday 1.2 return(sock);
354 }
355
|
356 mday 1.1
|
357 mday 1.4 static Boolean slp_scope_intersection(const Sint8 *our_scopes, Sint8 *his_scopes)
358 {
359 const Sint8 delimiters [] = " ," ;
360 Sint8 *saveptr = NULL, *bptr;
361
362 if(our_scopes == NULL || his_scopes == NULL)
363 return(true);
364 bptr = _LSLP_STRTOK(his_scopes, delimiters, &saveptr);
365 while (NULL != bptr) {
366
367 // convert hist scope string upper case
368 for( Sint8 *cp = bptr; *cp; ++cp) {
369 if( 'a' <= *cp && *cp <= 'z' )
370 *cp += 'A' - 'a' ;
371 }
372
373 if( NULL != strstr( bptr , our_scopes) )
374 return(true);
375 bptr = _LSLP_STRTOK(NULL, delimiters, &saveptr);
376 }
377 return(false);
378 mday 1.4 }
379
380
|
381 mday 1.1 // static class members (windows only )
382 #ifdef _WIN32
383 int slp_client::_winsock_count = 0;
384 WSADATA slp_client::_wsa_data ;
385 #endif
386
|
387 mday 1.2
388 // insert new node at the back of the list
389 template<class L> void slp2_list<L>::insert(L *element)
|
390 mday 1.1 {
391 slp2_list *ins = new slp2_list(false);
392 ins->_rep = element;
|
393 mday 1.2 ins->_next = this;
394 ins->_prev = this->_prev;
395 this->_prev->_next = ins;
396 this->_prev = ins;
|
397 mday 1.1 _count++;
398 return;
399 }
400
401
402 template<class L> inline L *slp2_list<L>::next(L * init)
403 {
404 if( init == NULL )
405 _cur = _next;
406 else {
|
407 mike 1.5 assert( (init = _cur->_rep) != 0 );
|
408 mday 1.1 _cur = _cur->_next;
409 }
410 return(_cur->_rep);
411 }
412
413 template<class L> inline L *slp2_list<L>::prev( L * init )
414 {
415 if( init == NULL )
416 _cur = _next;
417 else {
418 assert( init = _cur->rep ) ;
419 _cur = _cur->_prev;
420 }
421 return(_cur->_rep);
422 }
423
424 template<class L> inline int slp2_list<L>::count(void) { return(_count) ; }
425
426 template<class L> void slp2_list<L>::empty_list(void)
427 {
428 while( _count > 0 ) {
429 mday 1.1 slp2_list *temp = _next;
430 temp->unlink();
431 if(temp->_rep != NULL)
432 delete temp->_rep;
433 delete temp;
434 _count--;
435 }
436 assert(_count == 0);
437 return;
438 }
439
440
441 template<class L> L *slp2_list<L>::remove( void )
442 {
443 L *ret = NULL;
444 if( _count > 0 ) {
445 slp2_list *temp = _next;
446 temp->unlink();
447 ret = temp->_rep;
448 // unhinge ret from temp so it doesn't get destroyed
449 temp->_rep = NULL ;
450 mday 1.1 delete temp;
451 _count--;
452 }
453 return(ret);
454 }
455
|
456 mday 1.2
457 template<class L> L *slp2_list<L>::remove(Sint8 *key)
458 {
459 L *ret = NULL;
460 if( _count > 0 ) {
461 slp2_list *temp = _next;
462 while ( temp->_isHead == false ) {
463 if( temp->_rep->operator==( key )) {
464 temp->unlink();
465 ret = temp->_rep;
466 temp->_rep = NULL;
467 delete temp;
468 _count--;
469 break;
470 }
471 temp = temp->_next;
472 }
473 }
474 return(ret);
475 }
476
477 mday 1.2
|
478 mday 1.4 template<class L> L *slp2_list<L>::reference(Sint8 *key)
479 {
480 if( _count > 0 ) {
481 slp2_list *temp = _next;
482 while(temp->_isHead == false ) {
483 if( temp->_rep->operator==(key))
484 return(temp->_rep);
485 temp = temp->_next;
486 }
487 }
488 return(NULL);
489 }
490
|
491 mday 1.2 template<class L> Boolean slp2_list<L>::exists(Sint8 *key)
492 {
493 if( _count > 0) {
494 slp2_list *temp = _next;
495 while(temp->_isHead == false ) {
496 if( temp->_rep->operator==( key ))
497 return(true);
498 temp = temp->_next;
499 }
500 }
501 return(false);
502 }
503
504
|
505 mday 1.1 da_list::~da_list()
506 {
507 // unlink();
|
508 mday 1.2 delete[] url;
509 delete[] scope;
510 delete[] attr;
511 delete[] spi;
512 delete[] auth;
|
513 mday 1.1 }
514
515
|
516 mday 1.2 Boolean da_list::operator ==(const Sint8 *key) const
517 {
518 if( ! strcasecmp(url, key) )
519 return(true);
520 return(false);
521 }
|
522 mday 1.1
523 rply_list::~rply_list()
524 {
525 // unlink();
|
526 mday 1.2 delete[] url;
527 delete[] auth;
528 }
529
530
531 Boolean rply_list::operator ==(const Sint8 *key ) const
532 {
533 if (! strcasecmp(url, key) )
534 return(true);
535 return(false);
536 }
537
538
|
539 mday 1.4 reg_list::reg_list(Sint8 *r_url,
540 Sint8 *r_attributes,
541 Sint8 *r_service_type,
542 Sint8 *r_scopes,
543 time_t r_lifetime)
544 {
545 if( r_url != NULL ) {
546 url = new Sint8[ strlen(r_url + 1 ) ];
547 strcpy(url, r_url);
548 }
549
550 if( r_attributes != NULL ) {
551 attributes = new Sint8[ strlen(r_attributes) + 1 ];
552 strcpy(attributes, r_attributes);
553 }
554
555 if(r_service_type != NULL ) {
556 service_type = new Sint8[ strlen(r_service_type) + 1 ];
557 strcpy(service_type, r_service_type);
558 }
559
560 mday 1.4 if(r_scopes != NULL) {
561 scopes = new Sint8[ strlen(r_scopes ) + 1 ];
562 strcpy(scopes, r_scopes);
563 }
564 lifetime = r_lifetime;
565
566 }
567
|
568 mday 1.2 reg_list::~reg_list()
569 {
570 delete[] url;
571 delete[] attributes;
572 delete[] service_type;
573 delete[] scopes;
574 }
575
576
577 Boolean reg_list::operator ==(const Sint8 *key ) const
578 {
579 if( ! strcasecmp(url, key) )
580 return(true);
581 return(false);
|
582 mday 1.1 }
583
|
584 mday 1.4 url_entry::url_entry( Uint16 u_lifetime,
585 Sint8 *u_url,
586 Uint8 u_num_auths,
587 Uint8 *u_auth_blocks)
588 {
589
590 lifetime = u_lifetime;
591 if(u_url != NULL && (len = strlen(u_url) )) {
592 len++;
593 url = new Sint8[len];
594 strcpy(url, u_url);
595 } else { len = 0 ; }
596
597 num_auths = 0;
598 auth_blocks = NULL;
599 }
600
601 url_entry::~url_entry()
602 {
603 delete [] url;
604 delete [] auth_blocks;
605 mday 1.4 }
606
607
608 Boolean url_entry::operator ==(const Sint8 *key) const
609 {
610 if( ! strcasecmp(url, key) )
611 return(true);
612 return(false);
613 }
614
|
615 mday 1.1
616 void slp_client::set_target_addr(const Sint8 *addr)
617 {
618 if(addr == NULL)
619 _target_addr = inet_addr("239.255.255.253") ;
620 else
621 _target_addr = inet_addr(addr);
622 }
623
624 void slp_client::set_local_interface(const Sint8 *iface)
625 {
626
627 if(iface == NULL)
628 _local_addr = INADDR_ANY;
629 else
630 _local_addr = inet_addr(iface);
631 }
632
633 void slp_client::set_spi(const Sint8 *spi)
634 {
|
635 mday 1.4 delete [] _spi;
636 if(spi != NULL && strlen(spi) ) {
637 _spi = new Sint8[strlen(spi) + 1 ];
638 strcpy(_spi, spi);
639 }
|
640 mday 1.1 return ;
641 }
642
|
643 mday 1.4 void slp_client::set_scopes(const Sint8 *scopes)
644 {
645 delete [] _scopes;
646 if( scopes != NULL && strlen(scopes) ) {
647 _scopes = new Sint8[ strlen(scopes) + 1 ];
648 strcpy(_scopes, scopes);
649 }
650 return;
651 }
652
|
653 mday 1.1 slp_client::slp_client(const Sint8 *target_addr,
654 const Sint8 *local_addr,
655 Uint16 target_port,
|
656 mday 1.4 const Sint8 *spi,
657 const Sint8 *scopes )
|
658 mday 1.1
|
659 mday 1.2 : _pr_buf_len(0), _buf_len (LSLP_MTU), _version((Uint8)1),
|
660 mday 1.4 _xid(1), _target_port(htons(target_port)), _local_addr_list(NULL),
661 _spi(NULL), _scopes(NULL), _use_das(false), _last_da_cycle(0), _retries(3),
662 _ttl(255), _convergence(5), _crypto_context(NULL), das( ),
663 replies( ), regs( )
|
664 mday 1.1
665 {
666 set_target_addr(target_addr);
667 set_local_interface(local_addr);
668 set_spi(spi);
|
669 mday 1.4 set_scopes(scopes);
|
670 mday 1.2 _pr_buf = new Sint8[LSLP_MTU];
671 _msg_buf = new Sint8[LSLP_MTU] ;
672 _rcv_buf = new Sint8[LSLP_MTU] ;
|
673 mday 1.4 _tv.tv_sec = 0;
674 _tv.tv_usec = 200000;
|
675 mday 1.1 #ifdef _WIN32
676 if(_winsock_count == 0)
677 WSAStartup(0x0002, &_wsa_data);
678 _winsock_count++;
679 #endif
|
680 mday 1.2
|
681 mday 1.4 // build our local address list
682 slp_get_local_interfaces( &_local_addr_list ) ;
683
684 // before opening the listen socket we need to see if the local machine is a da
685 // if it is, don't open the listen socket
686 _rcv_sock = INVALID_SOCKET;
687 local_srv_req(NULL, NULL, "DEFAULT");
688 if(0 < das.count() )
689 _rcv_sock = INVALID_SOCKET;
690 else
691 _rcv_sock = slp_open_listen_sock( );
|
692 mday 1.1 }
693
694
695 slp_client::~slp_client()
696 {
|
697 mday 1.2 // close the receive socket
|
698 mday 1.4 _LSLP_CLOSESOCKET( _rcv_sock ) ;
|
699 mday 1.2 #ifdef _WIN32
700 _winsock_count--;
701 if(_winsock_count == 0)
702 WSACleanup();
703 #endif
704
|
705 mday 1.4 delete [] _pr_buf;
706 delete [] _msg_buf;
707 delete [] _rcv_buf;
708 delete [] _local_addr_list;
709 delete [] _spi;
710 delete [] _scopes;
711
|
712 mday 1.1 if(_crypto_context != NULL)
713 free(_crypto_context);
714 das.empty_list();
715 replies.empty_list();
716 }
717
718
719 void slp_client::prepare_pr_buf(const Sint8 *a)
720 {
721 if(a == NULL)
722 return;;
723 if(_pr_buf_len > 0)
724 *(_pr_buf + _pr_buf_len - 1) = ',' ;
725 do {
726 *(_pr_buf + _pr_buf_len) = *a;
727 a++;
728 _pr_buf_len++;
729 }while((*a != 0x00) && (_pr_buf_len < LSLP_MTU - 1));
730 _pr_buf_len++;
731 }
732
733 mday 1.1 Boolean slp_client::prepare_query( Uint16 xid,
734 const Sint8 *service_type,
735 const Sint8 *scopes,
736 const Sint8 *predicate )
737 {
738 Sint16 len, total_len;
739 Sint8 *bptr;
740 if(_msg_buf == NULL || _pr_buf == NULL)
741 return(false);
742 if(xid != _xid) {
743 /* this is a new request */
744 memset(_pr_buf, 0x00, LSLP_MTU);
745 _pr_buf_len = 0;
746 _xid = xid;
747 }
748 memset(_msg_buf, 0x00, LSLP_MTU);
749 bptr = _msg_buf;
750 _LSLP_SETVERSION(bptr, LSLP_PROTO_VER);
751 _LSLP_SETFUNCTION(bptr, LSLP_SRVRQST);
752 /* we don't know the length yet */
|
753 mday 1.4 _LSLP_SETFLAGS(bptr, 0);
|
754 mday 1.1 _LSLP_SETXID(bptr, xid);
755 _LSLP_SETLAN(bptr, LSLP_EN_US);
756 bptr += ( total_len = _LSLP_HDRLEN(bptr) ) ;
757
758 if(_pr_buf_len + total_len < LSLP_MTU) {
759 /* set the pr list length */
760 _LSLP_SETSHORT(bptr, (len = _pr_buf_len), 0);
761 if(len)
762 memcpy(bptr + 2, _pr_buf, len);
763 total_len += ( 2 + len );
764 bptr += (2 + len);
765
766 if(service_type == NULL)
767 len = DA_SRVTYPELEN;
768 else
769 len = strlen(service_type) + 1;
770 if(total_len + 2 + len < LSLP_MTU) {
771 /* set the service type string length */
772 _LSLP_SETSHORT(bptr, len, 0);
773 if(service_type != NULL)
774 memcpy(bptr + 2, service_type, len);
775 mday 1.1 else
776 memcpy(bptr + 2, DA_SRVTYPE, len);
777
778 total_len += (2 + len);
779 bptr += (2 + len);
780
781 /* set the scope len and scope type, advance the buffer */
782
783 if(scopes == NULL)
784 len = DA_SCOPELEN;
785 else
786 len = strlen(scopes) + 1;
787 if( total_len + 2 + len < LSLP_MTU) {
788 _LSLP_SETSHORT(bptr, len, 0);
789 if(scopes != NULL)
790 memcpy(bptr + 2, scopes, len);
791 else
792 memcpy(bptr + 2, DA_SCOPE, DA_SCOPELEN);
793
794 total_len += ( 2 + len);
795 bptr += (2 + len);
796 mday 1.1
797 /* stuff the predicate if there is one */
798 if(predicate == NULL)
799 len = 0;
800 else
801 len = strlen(predicate) + 1;
802 if( total_len + 2 + len < LSLP_MTU) {
803 _LSLP_SETSHORT(bptr, len, 0);
804 if(predicate != NULL)
805 memcpy(bptr + 2, predicate, len);
806
807 total_len += (2 + len);
808 bptr += (2 + len);
809
810 /* stuff the spi */
811
812 /* set the spi len and spi string */
813 if(_spi == NULL)
814 len = 0;
815 else
816 len = strlen(_spi) + 1;
817 mday 1.1
818 if(total_len + 2 + len < LSLP_MTU) {
819 _LSLP_SETSHORT(bptr, len, 0);
820
821 if(_spi != NULL)
822 memcpy(bptr + 2, _spi, len);
823
824 total_len += ( 2 + len);
825 bptr += (2 + len);
826 assert(total_len == bptr - _msg_buf);
827 /* now go back and set the length for the entire message */
828 _LSLP_SETLENGTH(_msg_buf, total_len );
829 return(true);
830 } /* room for the spi */
831 } /* room for predicate */
832 } /* room for the scope */
833 } /* room for the service type */
834 } /* room for the pr list */
835 return(false);
836 }
837
838 mday 1.1
839 rply_list *slp_client::get_response( void )
840 {
841
|
842 mday 1.4 return(replies.remove());
|
843 mday 1.1 }
844
845
846 int slp_client::find_das(const Sint8 *predicate,
847 const Sint8 *scopes)
848 {
849 converge_srv_req(NULL, predicate, scopes);
|
850 mday 1.2 time(&_last_da_cycle);
851 if(0 < das.count() )
852 _use_das = true;
853 else
854 _use_das = false;
|
855 mday 1.1 return( das.count( ) );
856 }
857
|
858 mday 1.4
859 // smart interface to slp discovery. uses das if they are present,
860 // convergence otherwise.
861 // periodically forces an active da discovery cycle
862
863 void slp_client::discovery_cycle ( const Sint8 *type,
864 const Sint8 *predicate,
865 const Sint8 *scopes)
866
867 {
868 // see if we have built a cache of directory agents
869 if( 0 == das.count() ) {
870 // we don't know of any directory agents - see if we need to do active da discovery
871 if( ((time(NULL)) - _last_da_cycle ) > (60 * 5) )
872 find_das(NULL, scopes) ;
873 }
874
875 // if there are das, unicast a srvreq to each da
876
877 if( 0 < das.count() ) {
878
879 mday 1.4 da_list *da = das.next(NULL);
880 struct sockaddr_in addr;
881 while( da != NULL ) {
882 addr.sin_port = htons(427);
883 addr.sin_family = AF_INET;
884 addr.sin_addr.s_addr = inet_addr(da->remote);
885 unicast_srv_req(type, predicate, scopes, &addr);
886 da = das.next(da);
887 }
888 } else {
889 // do a convergence request because we don't have any das to use
890
891 converge_srv_req(type, predicate, scopes );
892 }
893 return;
894 }
895
896 // this request MUST be retried <_convergence> times on EACH interface
897 // regardless of how many responses we have received
898 // it can be VERY time consuming but is the most thorough
899 // discovery method
900 mday 1.4 void slp_client::converge_srv_req( const Sint8 *type,
901 const Sint8 *predicate,
902 const Sint8 *scopes)
903 {
904
905 Uint32 old_target_addr = _target_addr;
906 Uint32 old_local_addr = _local_addr;
907 set_target_addr( "239.255.255.253" ) ;
908
909 Uint32 *p_addr = _local_addr_list;
910 Uint16 convergence;
911 Uint32 loopback = inet_addr("127.0.0.1");
912
913 do {
914 if( *p_addr == loopback ) {
915 p_addr++;
916 continue;
917 }
918 _local_addr = *p_addr;
919 convergence = _convergence;
920
921 mday 1.4 if(prepare_query( _xid + 1, type, scopes, predicate)) {
922 _LSLP_SETFLAGS(_msg_buf, LSLP_FLAGS_MCAST) ;
923 send_rcv_udp( );
924 }
925
926 while(--convergence > 0) {
927 if(prepare_query( _xid, type, scopes, predicate)) {
928 _LSLP_SETFLAGS(_msg_buf, LSLP_FLAGS_MCAST) ;
929 send_rcv_udp( );
930 }
931 }
932 p_addr++;
933 } while( *p_addr != INADDR_ANY ) ;
934
935
936 // always try a local request
937 local_srv_req(type, predicate, scopes);
938
939 _target_addr = old_target_addr;
940 _local_addr = old_local_addr;
941 return ;
942 mday 1.4 }
943
944
945
946 // this request will be retried MAX <_retries> times
947 // but will always end when the first response is received
948 // This request is best when using a directory agent
949 void slp_client::unicast_srv_req( const Sint8 *type,
|
950 mday 1.1 const Sint8 *predicate,
|
951 mday 1.4 const Sint8 *scopes,
952 struct sockaddr_in *addr )
953 {
954
955 Uint32 target_addr_save, local_addr_save;
956 Uint16 target_port_save;
957 struct timeval tv_save;
958
959 target_addr_save = _target_addr;
960 local_addr_save = _local_addr;
961 target_port_save = _target_port;
962
963 tv_save.tv_sec = _tv.tv_sec;
964 _tv.tv_sec = 1;
965
966 // let the host decide which interface to use
967 _local_addr = INADDR_ANY;
968 _target_addr = addr->sin_addr.s_addr;
969 _target_port = addr->sin_port;
970
971
972 mday 1.4 int retries = _retries ;
973 int old_count = replies.count() ;
974 srv_req(type, predicate, scopes, false) ;
975 while( --retries > 0 && replies.count() == old_count ) {
976 srv_req(type, predicate, scopes, true );
977 }
978 _target_addr = target_addr_save;
979 _local_addr = local_addr_save;
980 _target_port = target_port_save;
981 _tv.tv_sec = tv_save.tv_sec;
982 return;
983 }
984
985 // this request is targeted to the loopback interface,
986 // and has a tiny wait timer. It should be resolved quickly.
987 // It will never be retried.
988 void slp_client::local_srv_req( const Sint8 *type,
989 const Sint8 *predicate,
990 const Sint8 *scopes )
991
992
|
993 mday 1.1 {
994
|
995 mday 1.4 Uint32 target_addr_save;
996 struct timeval tv_save;
997
998 target_addr_save = _target_addr;
999
1000 tv_save.tv_sec = _tv.tv_sec;
1001 tv_save.tv_usec = _tv.tv_usec;
1002 _tv.tv_sec = 0;
1003 _tv.tv_usec = 1000000;
1004
1005 // let the host decide which interface to use
1006 _local_addr = INADDR_ANY;
1007 _target_addr = inet_addr("127.0.0.1");
1008 _target_port = htons(427);
1009
|
1010 mday 1.1
|
1011 mday 1.4 srv_req(type, predicate, scopes, false) ;
1012
1013 _target_addr = target_addr_save;
1014
1015 _tv.tv_sec = tv_save.tv_sec;
1016 _tv.tv_usec = tv_save.tv_usec;
1017 return;
1018
|
1019 mday 1.1 }
1020
1021
|
1022 mday 1.4 // workhorse request function
|
1023 mday 1.1 void slp_client::srv_req( const Sint8 *type,
1024 const Sint8 *predicate,
|
1025 mday 1.4 const Sint8 *scopes,
1026 Boolean retry )
|
1027 mday 1.1 {
|
1028 mday 1.4 if ((true == prepare_query( (retry == true) ? _xid : _xid + 1,
1029 type,
1030 scopes,
1031 predicate ))) {
|
1032 mday 1.1 send_rcv_udp( ) ;
1033 } /* prepared query */
1034 return ;
1035 }
1036
|
1037 mday 1.4 void slp_client::decode_msg( struct sockaddr_in *remote )
|
1038 mday 1.1 {
1039
|
1040 mday 1.2 if( _xid == _LSLP_GETXID( _rcv_buf ))
1041 prepare_pr_buf( inet_ntoa(remote->sin_addr) );
1042
1043 Sint8 function = _LSLP_GETFUNCTION( _rcv_buf );
1044 switch(function) {
1045 case LSLP_DAADVERT:
1046 decode_daadvert( remote );
1047 return;
|
1048 mday 1.4 case LSLP_SRVRQST:
1049 decode_srvreq( remote );
1050 return;
|
1051 mday 1.2 case LSLP_SRVRPLY:
1052 decode_srvrply( remote );
1053 return;
1054 case LSLP_SRVACK:
1055 default:
1056 break;
1057 }
|
1058 mday 1.1 return;
1059 }
1060
1061
1062 void slp_client::decode_srvrply( struct sockaddr_in *remote )
1063 {
1064 Sint8 *bptr;
1065 Sint16 str_len, err, count;
1066 Sint32 total_len, purported_len;
1067
|
1068 mday 1.2 bptr = _rcv_buf;
|
1069 mday 1.1 purported_len = _LSLP_GETLENGTH(bptr);
1070 bptr += (total_len = _LSLP_HDRLEN(bptr));
1071 if(total_len < purported_len) {
1072 rply_list *reply = new rply_list();
1073 if(reply == NULL) abort();
1074 err = _LSLP_GETSHORT(bptr, 0);
1075 count = _LSLP_GETSHORT(bptr, 2);
1076 bptr += 4;
1077 total_len += 4;
1078 /* loop on the url entries */
1079 while( ( total_len <= purported_len ) && ( count > 0 ) && reply != NULL ) {
1080 reply->function = LSLP_SRVRPLY;
1081 reply->err = err;
1082 reply->lifetime = _LSLP_GETSHORT(bptr, 1);
1083 total_len += (5 + (str_len = _LSLP_GETSHORT(bptr, 3)));
1084 if(total_len <= purported_len) {
1085 Sint8 num_auths;
1086 if(str_len > 0) {
|
1087 mday 1.2 reply->url = new Sint8[str_len + 1];
1088 memcpy(reply->url, bptr + 5, str_len);
1089 *((reply->url) + str_len) = 0x00;
|
1090 mday 1.1 bptr += (5 + str_len);
1091 reply->auth_blocks = (num_auths = _LSLP_GETBYTE(bptr, 0));
1092 total_len += 1;
1093 bptr += 1;
1094 while(num_auths && (total_len <= purported_len )) {
1095 /* iterate past the authenticators for now */
1096 /* need extra code here to authenticate url entries */
1097 total_len += (str_len = _LSLP_GETSHORT(bptr, 2));
1098 bptr += str_len;
1099 num_auths--;
1100 }
|
1101 mday 1.2 // handling duplicate responses is really inefficient, and we're
1102 // not helping things out by checking for dupes this late in the game
1103 // however, in order to get to any further urls that may be in the
1104 // reply buffer we need to unstuff it anyway. So we are optimizing
1105 // for the case where there are no dupes.
1106 if( false == replies.exists(reply->url) ) {
1107 strcpy(&(reply->remote[0]), inet_ntoa( remote->sin_addr )) ;
1108 replies.insert(reply);
1109 } else { delete reply ; }
|
1110 mday 1.1 count--;
1111 if((total_len <= purported_len) && (count > 0) )
1112 reply = new rply_list( );
1113 else
1114 reply = NULL;
1115 } else { delete reply; reply = NULL ; } /* bad packet */
1116 } else { delete reply; reply = NULL ; } /* bad packet */
1117 } // while unwrapping multi-response message
1118 } /* if the hdr length field is consistent with reality */
1119 return;
1120 }
1121
1122
1123 void slp_client::decode_daadvert(struct sockaddr_in *remote)
1124 {
1125 Sint8 *bptr;
1126 Sint16 str_len;
1127 Sint32 total_len, purported_len;
1128
|
1129 mday 1.2 bptr = _rcv_buf;
|
1130 mday 1.1 purported_len = _LSLP_GETLENGTH(bptr);
1131 bptr += (total_len = _LSLP_HDRLEN(bptr));
1132 if(total_len < purported_len) {
1133 da_list *adv = new da_list( );
1134 if(adv == NULL) abort();
1135
1136 adv->function = LSLP_DAADVERT;
1137 adv->err = _LSLP_GETSHORT(bptr, 0);
1138 adv->stateless_boot = _LSLP_GETLONG(bptr, 2);
1139 total_len += (8 + (str_len = _LSLP_GETSHORT(bptr, 6)));
1140 if(total_len < purported_len) {
1141 /* decode and capture the url - note: this is a string, not a url-entry structure */
|
1142 mday 1.2 adv->url = new Sint8[str_len + 1] ;
1143 memcpy(adv->url, bptr + 8, str_len);
1144 *((adv->url) + str_len) = 0x00;
1145 /* advance the pointer past the url string */
1146 bptr += (str_len + 8);
1147 total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
1148 if(total_len < purported_len) {
1149 if(str_len > 0) {
1150 adv->scope = new Sint8[str_len + 1] ;
1151 memcpy(adv->scope, bptr + 2, str_len);
1152 *((adv->scope) + str_len) = 0x00;
1153 }
1154 /* advance the pointer past the scope string */
1155 bptr += (str_len + 2);
|
1156 mday 1.1 total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
1157 if(total_len < purported_len) {
1158 if(str_len > 0) {
|
1159 mday 1.2 adv->attr = new Sint8[str_len + 1] ;
1160 memcpy(adv->attr, bptr + 2, str_len);
1161 *((adv->attr) + str_len) = 0x00;
|
1162 mday 1.1 }
|
1163 mday 1.2 /* advance the pointer past the attr string */
|
1164 mday 1.1 bptr += (str_len + 2);
1165 total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
1166 if(total_len < purported_len) {
|
1167 mday 1.2 if(str_len > 0 ) {
1168 adv->spi = new Sint8[str_len + 1];
1169 memcpy(adv->spi, bptr + 2, str_len);
1170 *((adv->spi) + str_len) = 0x00;
1171 } /* if there is an spi */
1172
1173 /* advance the pointer past the spi string */
|
1174 mday 1.1 bptr += (str_len + 2);
|
1175 mday 1.2 adv->auth_blocks = _LSLP_GETBYTE(bptr, 0);
1176
1177 // if we already know about this da, remove the existing
1178 // entry from our cache and insert this new entry
1179 // maybe the stateless boot field changed or the da
1180 // supports new scopes, etc.
1181 da_list * exists = das.remove(adv->url);
1182 delete exists;
1183
1184 /* need code here to handle authenticated urls */
1185 strcpy(&(adv->remote[0]), inet_ntoa(remote->sin_addr)) ;
1186 das.insert(adv);
1187 return;
1188 } /* spi length field is consistent with hdr */
1189 } /* attr length field is consistent with hdr */
1190 } /* scope length field is consistent with hdr */
|
1191 mday 1.1 }
1192 }
1193 return;
1194 }
1195
1196
|
1197 mday 1.4 void slp_client::decode_srvreq(struct sockaddr_in *remote )
1198 {
1199
1200 Sint8 *bptr;
1201 Sint16 str_len, err = LSLP_PARSE_ERROR ;
1202 Sint32 total_len, purported_len;
1203 time_t current;
1204
1205 bptr = _rcv_buf;
1206 purported_len = _LSLP_GETLENGTH(bptr);
1207 bptr += (total_len = _LSLP_HDRLEN(bptr));
1208 if(total_len < purported_len) {
1209 if( 0 < regs.count() ) {
1210 // advance past the slp v2 header
1211 // get the previous responder list
1212 str_len = _LSLP_GETSHORT(bptr, 0);
1213 if ( (str_len + total_len + 2 < purported_len )) {
1214 if( false == slp_previous_responder( (str_len ? bptr + 2 : NULL ) )) {
1215 Sint8 *service_type = NULL;
1216 Sint8 *scopes = NULL;
1217 Sint8 *spi = NULL;
1218 mday 1.4 slp2_list<url_entry> url_list ;
1219
1220 bptr += 2 + str_len;
1221 total_len += 2 + str_len;
1222 // extract the service type string
1223 str_len = _LSLP_GETSHORT(bptr, 0);
1224 if(str_len && (str_len + total_len + 2 < purported_len )) {
1225 service_type = new Sint8[str_len + 1]; // one extra byte
1226 strcpy(service_type, bptr + 2);
1227
1228 // set the error code to zero
1229 err = 0;
1230 bptr += 2 + str_len;
1231 total_len += 2 + str_len;
1232
1233 // extract the scope list
1234
1235 str_len = _LSLP_GETSHORT(bptr, 0);
1236 if( str_len + total_len + 2 < purported_len) {
1237 if(str_len > 0 ) {
1238 scopes = new Sint8[str_len + 1] ; // one extra byte
1239 mday 1.4 strcpy(scopes, bptr + 2);
1240 }
1241
1242 // see if the requested scopes intersect with our scopes
1243
1244 if (true == slp_scope_intersection(_scopes, scopes) ) {
1245
1246 bptr += 2 + str_len;
1247 total_len += 2 + str_len;
1248
1249 // this is a very lightweight client and currently
1250 // doesn't support predicate evaluation.
1251 // we will answer srvreq messages with no predicate
1252 // however, if there is a predicate, we can't evaluate it
1253 // so we won't answer it.
1254
1255 // extract the predicate
1256 str_len = _LSLP_GETSHORT(bptr, 0) ;
1257 if(str_len == 0 ) {
1258 // ignore the spi for now.
1259 // look for a srvtype match
1260 mday 1.4
1261 reg_list *reg = regs.next(NULL);
1262 while( reg != 0 ) {
1263 // check the lifetime
1264
1265 if( (current = time(NULL)) > reg->lifetime ) {
1266 // this guy is stale, unlink him and start over
1267 regs.remove(reg->url);
1268 delete reg;
1269 reg = regs.next(NULL);
1270 continue;
1271 }
1272 if( ! strcasecmp( reg->service_type, service_type ) ) {
1273 // found a match
1274
1275
1276
1277
1278 url_entry *entry = new url_entry((reg->lifetime - time(NULL) ),
1279 reg->url ) ;
1280 url_list.insert(entry);
1281 mday 1.4 }
1282 reg = regs.next(reg);
1283 } // traversing list
1284
1285 } // if there is no predicate
1286 } // scopes intersect
1287 } // scope string fits
1288 } // svc type string fits
1289
1290 Boolean mcast = ( ((_LSLP_GETFLAGS( _rcv_buf )) & (LSLP_FLAGS_MCAST) ) ? true : false ) ;
1291 if(mcast == false || url_list.count() ) {
1292
1293 // we need to respond to this message
1294
1295 _LSLP_SETVERSION(_msg_buf, LSLP_PROTO_VER);
1296 _LSLP_SETFUNCTION(_msg_buf, LSLP_SRVRPLY);
1297 // skip the length for now
1298 _LSLP_SETFLAGS(_msg_buf, 0);
1299 _LSLP_SETNEXTEXT(_msg_buf, 0, LSLP_NEXT_EX);
1300 _LSLP_SETXID( _msg_buf, ( _LSLP_GETXID(_rcv_buf) ) );
1301 _LSLP_SETLAN(_msg_buf, LSLP_EN_US );
1302 mday 1.4 Sint32 msg_len = _LSLP_HDRLEN(_msg_buf);
1303 Sint8 *bptr = _msg_buf + msg_len;
1304 _LSLP_SETSHORT(bptr, err, 0);
1305 _LSLP_SETSHORT( bptr, url_list.count() , 2 );
1306
1307 bptr += 4;
1308 msg_len += 4;
1309 while ( 0 < url_list.count() ) {
1310 url_entry *entry = url_list.remove() ;
1311 assert(entry != NULL);
1312
1313 // check the length
1314 if ( (msg_len + 6 + entry->len ) <= LSLP_MTU ) {
1315 _LSLP_SETSHORT(bptr, entry->lifetime, 1);
1316 _LSLP_SETSHORT(bptr, entry->len, 3);
1317 memcpy(bptr + 5, entry->url, entry->len);
1318
1319 bptr += (5 + entry->len );
1320 msg_len += (5 + entry->len);
1321
1322 // for now don't support authentication
1323 mday 1.4 _LSLP_SETBYTE(bptr, 0, 0);
1324 bptr++;
1325 msg_len++;
1326
1327 } else {
1328 // set the overvlow flag because we ran out of room
1329 // also decrement the count of urls
1330 // possibly a subsequent url will fit so kee going
1331 _LSLP_SETFLAGS(_msg_buf, LSLP_FLAGS_OVERFLOW);
1332 Sint8 *save = bptr;
1333 bptr = _msg_buf + _LSLP_HDRLEN(_msg_buf) ;
1334 _LSLP_SETSHORT(bptr, ( _LSLP_GETSHORT(bptr, 2) - 1 ) , 2 );
1335 bptr = save;
1336 }
1337 delete entry;
1338 }
1339
1340 // ok, now we can set the length
1341 _LSLP_SETLENGTH(_msg_buf, msg_len );
1342
1343 // _msg_buf is stuffed with the service reply. now we need
1344 mday 1.4 // to allocate a socket and send it back to the requesting node
1345 SOCKET sock;
1346 if(INVALID_SOCKET != (sock = socket(AF_INET, SOCK_DGRAM, 0))) {
1347 int err = 1;
1348 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err) );
1349 struct sockaddr_in local;
1350 local.sin_family = AF_INET;
1351 local.sin_port = _target_port ;
1352 local.sin_addr.s_addr = _local_addr;
1353 if(SOCKET_ERROR != bind(sock, (struct sockaddr *)&local, sizeof(local))) {
1354 sendto(sock, _msg_buf, msg_len , 0,
1355 (struct sockaddr *)remote, sizeof(struct sockaddr_in )) ;
1356 } // successfully bound this socket
1357 _LSLP_CLOSESOCKET(sock);
1358 } // successfully opened this socket
1359 } // we must respond to this request
1360 delete [] spi;
1361 delete [] scopes;
1362 delete [] service_type;
1363 } // not on the pr list
1364 } // pr list length is consistent
1365 mday 1.4 } // if there are local registrations
1366 } // if length is consistent
1367 }
1368
1369
|
1370 mday 1.1 Boolean slp_client::srv_reg(Sint8 *url,
1371 Sint8 *attributes,
1372 Sint8 *service_type,
1373 Sint8 *scopes,
1374 Sint16 lifetime)
1375 {
1376 Sint32 len;
1377 Sint16 str_len;
1378 Sint8 *bptr;
1379
1380
1381 /* this is always a new request */
1382 memset( _pr_buf, 0x00, LSLP_MTU);
1383 _pr_buf_len = 0;
1384 _xid++ ;
1385
1386 memset(_msg_buf, 0x00, LSLP_MTU);
1387 bptr = _msg_buf;
1388 _LSLP_SETVERSION(bptr, LSLP_PROTO_VER);
1389 _LSLP_SETFUNCTION(bptr, LSLP_SRVREG);
1390 /* we don't know the length yet */
1391 mday 1.1 _LSLP_SETXID(bptr, _xid);
1392 _LSLP_SETLAN(bptr, LSLP_EN_US);
1393 bptr += (len = _LSLP_HDRLEN(bptr) ) ;
1394
1395 /* construct a url-entry */
1396
1397 _LSLP_SETSHORT(bptr, lifetime, 1);
1398 _LSLP_SETSHORT(bptr, (str_len = (strlen(url) + 1)), 3);
1399 len += (5 + str_len );
1400 if(len + 1 < LSLP_MTU ) {
1401 memcpy(bptr + 5, url, str_len);
1402 bptr += (5 + str_len);
1403 /* no auth blocks for now */
1404 _LSLP_SETBYTE(bptr, 0x00, 0);
1405 bptr++;
1406 len++;
1407 /* stuff the service type */
1408 str_len = strlen(service_type) + 1;
1409 if(len + 2 + str_len < LSLP_MTU) {
1410 _LSLP_SETSHORT(bptr, str_len, 0);
1411 memcpy(bptr + 2, service_type, str_len);
1412 mday 1.1 bptr += (2 + str_len);
1413 len += (2 + str_len);
1414 /* stuff the scope list if there is one */
1415 if(scopes == NULL)
1416 str_len = 0;
1417 else
1418 str_len = strlen(scopes) + 1;
1419 if(str_len == 1)
1420 str_len = 0;
1421 if(len + 2 + str_len < LSLP_MTU) {
1422 _LSLP_SETSHORT(bptr, str_len, 0);
1423 if(str_len)
1424 memcpy(bptr + 2, scopes, str_len);
1425
1426 len += (2 + str_len);
1427 bptr += (2 + str_len);
1428 /* stuff the attribute string if there is one */
1429 if(attributes == NULL)
1430 str_len = 0;
1431 else
1432 str_len = strlen(attributes) + 1;
1433 mday 1.1 if(str_len == 1)
1434 str_len = 0;
1435 if(len + 2 + str_len < LSLP_MTU) {
1436 _LSLP_SETSHORT(bptr, str_len, 0);
1437 if(str_len)
1438 memcpy(bptr + 2, attributes, str_len);
1439
1440 len += ( 2 + str_len);
1441 bptr += (2 + str_len);
1442
1443 /* no attribute auths for now */
1444 if(len + 1 < LSLP_MTU) {
1445 _LSLP_SETBYTE(bptr, 0x00, 0);
1446 }
1447 len += 1;
1448 /* set the length field in the header */
1449 _LSLP_SETLENGTH( _msg_buf, len );
|
1450 mday 1.4 int retries = _retries;
1451 while( --retries ) {
1452 if(true == send_rcv_udp( )) {
1453 if(LSLP_SRVACK == _LSLP_GETFUNCTION( _rcv_buf )) {
1454 if(0x0000 == _LSLP_GETSHORT( _rcv_buf, (_LSLP_HDRLEN( _rcv_buf )))) {
1455 memset(_msg_buf, 0x00, LSLP_MTU);
1456 return(true);
1457 }
|
1458 mday 1.1 }
|
1459 mday 1.4 } // received a response
1460 } // retrying the unicast
|
1461 mday 1.1 } /* attribute string fits into buffer */
1462 } /* scope string fits into buffer */
1463 } /* service type fits into buffer */
1464 } /* url fits into buffer */
1465 memset( _msg_buf, 0x00, LSLP_MTU);
1466 return(false);
1467 }
1468
1469
1470
1471 Boolean slp_client::send_rcv_udp( void )
1472 {
1473 SOCKET sock;
1474 struct sockaddr_in target, local;
1475 Boolean ccode = false;
1476 if(INVALID_SOCKET != (sock = socket(AF_INET, SOCK_DGRAM, 0))) {
1477 int err = 1;
1478 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err) );
1479
1480 local.sin_family = AF_INET;
1481 local.sin_port = 0;
1482 mday 1.1 local.sin_addr.s_addr = _local_addr;
1483 if(SOCKET_ERROR != bind(sock, (struct sockaddr *)&local, sizeof(local))) {
1484 int bcast = ( (_LSLP_GETFLAGS(_msg_buf)) & LSLP_FLAGS_MCAST) ? 1 : 0 ;
1485 if(bcast) {
1486 if( (SOCKET_ERROR == _LSLP_SET_TTL(sock, _ttl) ) ||
1487 (SOCKET_ERROR == setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const Sint8 *)&bcast, sizeof(bcast)))) {
1488 _LSLP_CLOSESOCKET(sock);
1489 return(false);
1490 }
1491 if(_local_addr != INADDR_ANY ) {
1492 struct sockaddr_in ma;
1493 memset(&ma, 0x00, sizeof(ma));
1494 ma.sin_addr.s_addr = _local_addr;
1495 if( (SOCKET_ERROR == setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&ma, sizeof(struct sockaddr_in))) ) {
1496 _LSLP_CLOSESOCKET(sock);
1497 return(false);
1498 }
1499 }
1500 }
1501 target.sin_family = AF_INET;
|
1502 mday 1.4 target.sin_port = _target_port;
|
1503 mday 1.1 target.sin_addr.s_addr = _target_addr;
1504 if(SOCKET_ERROR == (err = sendto(sock,
1505 _msg_buf,
1506 _LSLP_GETLENGTH(_msg_buf),
1507 0,
1508 (struct sockaddr *)&target, sizeof(target) ))) {
1509 _LSLP_CLOSESOCKET(sock);
1510 return(false);
1511 } /* oops - error sending data */
|
1512 mday 1.4
1513
1514 while ( 0 < service_listener( sock ) ) { ccode = true; }
1515
|
1516 mday 1.2 } // bound the socket
|
1517 mday 1.1 _LSLP_CLOSESOCKET(sock);
1518 } /* got the socket */
1519 return(ccode);
1520 }
1521
|
1522 mday 1.2 // must be called regularly to process responses
1523
1524 Sint32 slp_client::service_listener(void)
1525 {
1526 return service_listener((SOCKET) 0);
1527 }
1528
1529
1530 Sint32 slp_client::service_listener_wait(time_t wait, SOCKET extra_sock, Boolean one_only)
1531 {
1532 Sint32 rcv = 0;
1533 time_t now;
1534 time_t start = time(NULL);
1535
1536 while( time(&now) && ((now - wait ) <= start ) ) {
1537 rcv += service_listener(extra_sock);
1538 if(rcv > 0)
1539 if(one_only == true)
1540 return(rcv);
|
1541 mike 1.5
1542 #ifdef PEGASUS_OS_TRU64
1543 usleep(10 * 1000);
1544 #else
|
1545 mday 1.2 _LSLP_SLEEP(10);
|
1546 mike 1.5 #endif
|
1547 mday 1.2 }
1548 rcv += service_listener(extra_sock);
1549 return(rcv);
1550 }
1551
1552 Sint32 slp_client::service_listener(SOCKET extra_sock )
1553 {
1554
|
1555 mday 1.4 struct timeval tv;
|
1556 mday 1.2 fd_set fds;
1557 FD_ZERO(&fds);
|
1558 mday 1.4 if(_rcv_sock != INVALID_SOCKET) {
1559 FD_SET(_rcv_sock, &fds);
1560 }
|
1561 mday 1.2 if(extra_sock)
1562 FD_SET( extra_sock, &fds);
1563 Sint32 err;
1564 do {
|
1565 mday 1.4 tv.tv_sec = _tv.tv_sec;
1566 tv.tv_usec = _tv.tv_usec;
|
1567 mday 1.2 err = select(_rcv_sock > extra_sock ? _rcv_sock + 1: extra_sock + 1, &fds, NULL, NULL, &tv);
1568 } while ( (err < 0 )&& (errno == EINTR)) ;
1569 if( 0 < err ) {
1570 struct sockaddr_in remote;
|
1571 mday 1.4
|
1572 mike 1.5 #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_TRU64)
|
1573 mday 1.2 int size = sizeof(remote);
|
1574 karl 1.3 #else
|
1575 mday 1.4 socklen_t size = sizeof(remote);
|
1576 karl 1.3 #endif
|
1577 mday 1.4
1578 if(extra_sock && FD_ISSET(extra_sock, &fds) )
1579 err = recvfrom(extra_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, &size);
1580 if(_rcv_sock != INVALID_SOCKET) {
1581 if(FD_ISSET(_rcv_sock, &fds))
1582 err = recvfrom(_rcv_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, &size);
|
1583 mday 1.2 }
|
1584 mday 1.4
1585 if(err && err != SOCKET_ERROR)
1586 decode_msg( &remote );
1587 }
1588 if (err == SOCKET_ERROR) {
1589 // our interfaces could be disconnected or we could be a laptop that
1590 // just got pulled from the network, etc.
1591 _LSLP_CLOSESOCKET(_rcv_sock );
1592 if( 0 < slp_get_local_interfaces( & _local_addr_list ) ) {
1593 if(_rcv_sock != INVALID_SOCKET)
1594 _rcv_sock = slp_open_listen_sock( );
|
1595 mday 1.2 }
|
1596 mday 1.4 }
|
1597 mday 1.2 return(err);
1598 }
1599
|
1600 mday 1.1 int slp_client::srv_reg_all( Sint8 *url,
1601 Sint8 *attributes,
1602 Sint8 *service_type,
1603 Sint8 *scopes,
1604 Sint16 lifetime)
1605 {
1606
1607 assert(url != NULL && attributes != NULL && service_type != NULL && scopes != NULL);
1608 if(url == NULL || attributes == NULL || service_type == NULL || scopes == NULL )
1609 return(0);
1610
1611 // see if we have built a cache of directory agents
1612 if( 0 == das.count() ) {
|
1613 mday 1.4 // we don't know of any directory agents - see if we need to do active da discovery
1614 if( ((time(NULL)) - _last_da_cycle ) > (60 * 5) )
1615 find_das(NULL, scopes) ;
|
1616 mday 1.1 }
1617
|
1618 mday 1.4 // keep track of how many times we register
|
1619 mday 1.1 int registrations = 0;
|
1620 mday 1.4
1621 // save target and convergence parameters
|
1622 mday 1.1 Uint32 target_addr_save = _target_addr;
1623 int convergence_save = _convergence;
1624 _convergence = 0;
1625
|
1626 mday 1.4 // if there are das, unicast a srvreg to each da
1627
1628 if( 0 < das.count() ) {
1629
1630 da_list *da = das.next(NULL);
1631 while( da != NULL ) {
1632 set_target_addr(da->remote);
1633 if( true == srv_reg( url, attributes, service_type, scopes, lifetime) )
1634 registrations++;
1635 da = das.next(da);;
1636 }
|
1637 mday 1.1 }
1638
|
1639 mday 1.4 // restore parameters
|
1640 mday 1.1 _convergence = convergence_save;
1641 _target_addr = target_addr_save;
1642
|
1643 mday 1.4
1644 // if we have registered with any das, act like a service agent and cache our
1645 // own registration. This provides a failsafe in case the DA is not available
1646 srv_reg_local(url, attributes, service_type, scopes, lifetime);
1647 registrations++;
1648
|
1649 mday 1.1 return(registrations);
1650 }
1651
|
1652 mday 1.4
1653 void slp_client::srv_reg_local ( Sint8 *url,
1654 Sint8 *attributes,
1655 Sint8 *service_type,
1656 Sint8 *scopes,
1657 Sint16 lifetime)
1658 {
1659 reg_list *reg = NULL;
1660 // first see if the reg already exists. if it does, just update the lifetime
1661 if ( NULL != (reg = regs.reference(url))) {
1662 reg->lifetime = lifetime + time(NULL);
1663 } else { // new reg
1664 reg = new reg_list(url, attributes, service_type, scopes, (lifetime + time(NULL)));
1665 regs.insert(reg);
1666 }
1667 return;
1668 }
1669
1670 Boolean slp_client::slp_previous_responder(Sint8 *pr_list)
1671 {
1672
1673 mday 1.4 Sint8 *a, *s = NULL;
1674 Uint32 addr, *list_addr;
1675 if(pr_list == NULL || 0 == strlen(pr_list))
1676 return(false);
1677
1678 a = _LSLP_STRTOK(pr_list, ",", &s);
1679 while(NULL != a ) {
1680 if(INADDR_NONE != (addr = inet_addr(a))) {
1681 list_addr = _local_addr_list;
1682 while( INADDR_ANY != *list_addr ) {
1683 if(*list_addr == addr)
1684 return(true);
1685 list_addr++;
1686 }
1687 }
1688 a = _LSLP_STRTOK(NULL, ",", &s);
1689 }
1690 return(false);
1691 }
|
1692 mday 1.1
1693 PEGASUS_NAMESPACE_END
|