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