(file) Return to slp.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / slp

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2