(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 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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2