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