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