mslpd_init.cpp   [plain text]



/*
 * mslpd_init.c : Minimal SLP v2 Service Agent - initialization 
 *             for networking.
 *
 * Version: 1.10
 * Date:    03/29/99
 *
 * Licensee will, at its expense,  defend and indemnify Sun Microsystems,
 * Inc.  ("Sun")  and  its  licensors  from  and  against any third party
 * claims, including costs and reasonable attorneys' fees,  and be wholly
 * responsible for  any liabilities  arising  out  of  or  related to the
 * Licensee's use of the Software or Modifications.   The Software is not
 * designed  or intended for use in  on-line  control  of  aircraft,  air
 * traffic,  aircraft navigation,  or aircraft communications;  or in the
 * design, construction, operation or maintenance of any nuclear facility
 * and Sun disclaims any express or implied warranty of fitness  for such
 * uses.  THE SOFTWARE IS PROVIDED TO LICENSEE "AS IS" AND ALL EXPRESS OR
 * IMPLIED CONDITION AND WARRANTIES, INCLUDING  ANY  IMPLIED  WARRANTY OF
 * MERCHANTABILITY,   FITNESS  FOR  WARRANTIES,   INCLUDING  ANY  IMPLIED
 * WARRANTY  OF  MERCHANTABILITY,  FITNESS FOR PARTICULAR PURPOSE OR NON-
 * INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT WILL SUN BE LIABLE HEREUNDER
 * FOR ANY DIRECT DAMAGES OR ANY INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL
 * OR CONSEQUENTIAL DAMAGES OF ANY KIND.
 *
 * (c) Sun Microsystems, 1998, All Rights Reserved.
 * Author: Erik Guttman
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>

#include "mslp_sd.h"
#include "slp.h"
#include "mslp.h"
#include "mslp_dat.h"
#include "mslpd_store.h"
#include "mslpd.h"

#ifdef MAC_OS_X
#include "slpipc.h"
#endif

/*
 * mslpd will need - 
 *   tcp listener (to inaddr_any) unless NOTCP
 *   udp listener (to mcast group on each and every interface!)
 *   fd_set and max socket descriptor.
 */
#if 0
SLPInternalError  mslpd_init_network(SAState *psa)
{
    int 				iErr, turnOn=1;
    SLPInternalError 			err;
    struct sockaddr_in	serv_addr;
    struct in_addr 		ina;
	char*				pc = NULL;

    if (OPEN_NETWORKING() < 0)
        return SLP_NETWORK_INIT_FAILED;

    psa->sdUDP = socket(AF_INET, SOCK_DGRAM, 0);
    psa->sdTCP = socket(AF_INET, SOCK_STREAM, 0);
    psa->sdReg = socket(AF_INET, SOCK_STREAM, 0);
    if (psa->sdUDP == INVALID_SOCKET || psa->sdTCP == INVALID_SOCKET ||
        psa->sdReg == INVALID_SOCKET)
    {
        SLP_LOG( SLP_LOG_DEBUG, "Could not allocate a socket" );
        return SLP_NETWORK_INIT_FAILED;
    }
    
    if (psa->sdUDP > psa->sdTCP)
        psa->sdMax = psa->sdUDP +1;
    else
        psa->sdMax = psa->sdTCP + 1;

    if ( setsockopt(psa->sdTCP, SOL_SOCKET, SO_REUSEADDR, &turnOn, sizeof(turnOn) ) <0 )
    {
        SLP_LOG( SLP_LOG_DEBUG, "Could not set reuse port option on TCP socket: %s", strerror(errno) );

        return SLP_NETWORK_INIT_FAILED;
    }

    // I need to get my host name and build in a sin

    if ((iErr = GetOurIPAdrs( &ina, NULL )) < 0)
    {
        SLP_LOG( SLP_LOG_DEBUG, "mslpd_init_network: could not get host address" );
        return SLP_NETWORK_INIT_FAILED;
    }

	pc = inet_ntoa(ina);

    psa->pcSAHost = safe_malloc(strlen(pc)+1,pc,strlen(pc));

    assert( psa->pcSAHost );
    errno = 0; 

    psa->pcSANumAddr = safe_malloc(strlen(pc)+1,pc,strlen(pc));
    assert( psa->pcSANumAddr );
    
    psa->sin.sin_addr.s_addr = ina.s_addr;
    psa->sin.sin_family = AF_INET;
    psa->sin.sin_port = htons(SLP_PORT);

    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SLP_PORT);
//    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_addr.s_addr = ina.s_addr;				// use interface specific address

#ifdef SLPTCP
    iErr = bind(psa->sdTCP,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

    if ((iErr < 0)||(iErr == SOCKET_ERROR))
    {
        SLP_LOG( SLP_LOG_DEBUG, "Error binding to TCP socket: %s", strerror(errno) );
        
        return SLP_NETWORK_INIT_FAILED;
    }
    iErr = listen(psa->sdTCP,5);

    if ((iErr < 0)||(iErr == SOCKET_ERROR))
    {
        SLP_LOG( SLP_LOG_DEBUG, "Error calling listen on TCP socket: %s", strerror(errno) );

        return SLP_NETWORK_INIT_FAILED;
    }
#endif // SLPTCP

   serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);		// listen for UDP from any interface?
   iErr = bind(psa->sdUDP,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

    if ((iErr < 0)||(iErr == SOCKET_ERROR))
    {
        SLP_LOG( SLP_LOG_DEBUG, "Error binding to UDP socket: %s", strerror(errno) );
        
        return SLP_NETWORK_INIT_FAILED;
    }

    if ( !OnlyUsePreConfiguredDAs() )
    {
    // set up multicast
        if ((err = set_multicast_sender_interf(psa->sdUDP)) != SLP_OK)
        {
            SLP_LOG(SLP_LOG_DEBUG,"mslpd_init_network: set_multicast_sender_interf",err);
            return err;
        }
        else
            SLP_LOG( SLP_LOG_DEBUG, "mslpd_init_network: set_multicast_sender_interf ok" );
    }
    
    FD_ZERO(&(psa->fds));
    FD_SET(psa->sdUDP,&(psa->fds));
    FD_SET(psa->sdTCP,&(psa->fds));
   
#ifdef EXTRA_MSGS
    {
        char *pcTemp = "service:service-agent://";
        int iLen = strlen(pcTemp);
        psa->pcSAURL = safe_malloc(iLen+strlen(pc)+1,pcTemp,iLen);
        assert( psa->pcSAURL );
        
        strcat(psa->pcSAURL,pc);
    }
#endif // EXTRA_MSGS

#ifdef MAC_OS_X        
    {
        char *pcTemp = "service:directory-agent://";
        int iLen = strlen(pcTemp);
        psa->pcDAURL = safe_malloc(iLen+strlen(pc)+1,pcTemp,iLen);
        assert( psa->pcDAURL );
        
        strcat(psa->pcDAURL,pc);
    }

    psa->pcSPIList = safe_malloc(1,NULL,0);
    assert( psa->pcSPIList );
    
    psa->pcSPIList[0] = '\0';	// this is just a null list for now

#endif // MAC_OS_X

  return SLP_OK;  
}

#else
SLPInternalError  mslpd_init_network(SAState *psa)
{
    int 				iErr, turnOn=1;
    SLPInternalError	err;
    struct sockaddr_in	serv_addr;
    struct in_addr 		ina;
    char 				pcHost[256];
	char*				pc = NULL;
    const char*			pcInterf = SLPGetProperty("net.slp.interfaces");

    if (OPEN_NETWORKING() < 0)
        return SLP_NETWORK_INIT_FAILED;

    psa->sdUDP = socket(AF_INET, SOCK_DGRAM, 0);
    psa->sdTCP = socket(AF_INET, SOCK_STREAM, 0);
    psa->sdReg = socket(AF_INET, SOCK_STREAM, 0);
    if (psa->sdUDP == INVALID_SOCKET || psa->sdTCP == INVALID_SOCKET ||
        psa->sdReg == INVALID_SOCKET)
    {
        SLP_LOG( SLP_LOG_ERR, "Could not allocate a socket" );
        return SLP_NETWORK_INIT_FAILED;
    }
    
    if (psa->sdUDP > psa->sdTCP)
        psa->sdMax = psa->sdUDP +1;
    else
        psa->sdMax = psa->sdTCP + 1;

    /* set the reuse socket option */
/*    if ( setsockopt(psa->sdUDP, SOL_SOCKET, SO_REUSEADDR, &turnOn, sizeof(turnOn) ) <0 )
    {
        char	msg[256];
        
        sprintf( msg, "Could not set reuse option on UDP socket: %s", strerror(errno) );
        SLP_LOG( SLP_LOG_ERR, msg );
        return SLP_NETWORK_INIT_FAILED;
    }

    if ( setsockopt(psa->sdUDP, SOL_SOCKET, SO_REUSEPORT, &turnOn, sizeof(turnOn) ) <0 )
    {
        char	msg[256];
        
        sprintf( msg, "Could not set reuse port option on UDP socket: %s", strerror(errno) );
        SLP_LOG( SLP_LOG_ERR, msg );
        return SLP_NETWORK_INIT_FAILED;
    }
*/
    if ( setsockopt(psa->sdTCP, SOL_SOCKET, SO_REUSEADDR, &turnOn, sizeof(turnOn) ) <0 )
    {
        char	msg[256];
        
        sprintf( msg, "Could not set reuse port option on TCP socket: %s", strerror(errno) );
        SLP_LOG( SLP_LOG_ERR, msg );
        return SLP_NETWORK_INIT_FAILED;
    }

    /* I need to get my host name and build in a sin */

    if (pcInterf != NULL)
    {
        strcpy(pcHost,pcInterf);
    }
    else if ((iErr = GetOurIPAdrs( &ina, NULL )) < 0)
    {
        SLP_LOG( SLP_LOG_ERR, "mslpd_init_network: could not get host address" );
        return SLP_NETWORK_INIT_FAILED;
    }

	pc = inet_ntoa(ina);

    psa->pcSAHost = safe_malloc(strlen(pc)+1,pc,strlen(pc));
    {
        errno = 0;
 
        psa->pcSANumAddr = safe_malloc(strlen(pc)+1,pc,strlen(pc));
        psa->sin.sin_addr.s_addr = ina.s_addr;
		psa->sin.sin_family = AF_INET;
        psa->sin.sin_port = htons(SLP_PORT);
    }

    if (pcInterf != NULL)
    {
        serv_addr = psa->sin;
    }
    else
    {
        memset(&serv_addr,0,sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(SLP_PORT);
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    }

#ifdef SLPTCP
    iErr = bind(psa->sdTCP,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

    if ((iErr < 0)||(iErr == SOCKET_ERROR))
    {
        char	msg[256];
        
        sprintf( msg, "Error binding to TCP socket: %s", strerror(errno) );
        SLP_LOG( SLP_LOG_ERR, msg );
        
        return SLP_NETWORK_INIT_FAILED;
    }
    iErr = listen(psa->sdTCP,5);

    if ((iErr < 0)||(iErr == SOCKET_ERROR))
    {
        char	msg[256];
        
        sprintf( msg, "Error calling listen on TCP socket: %s", strerror(errno) );
        SLP_LOG( SLP_LOG_ERR, msg );

        return SLP_NETWORK_INIT_FAILED;
    }
#endif /* SLPTCP */

   iErr = bind(psa->sdUDP,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

    if ((iErr < 0)||(iErr == SOCKET_ERROR))
    {
        char	msg[256];
        
        sprintf( msg, "Error binding to UDP socket: %s", strerror(errno) );
        SLP_LOG( SLP_LOG_ERR, msg );
        
        return SLP_NETWORK_INIT_FAILED;
    }

/*    if ( setsockopt(psa->sdUDP, SOL_SOCKET, SO_RCVBUF, &socketBufSize, sizeof(socketBufSize) ) <0 )
    {
        char	msg[256];
        
        sprintf( msg, "Could not set receive buffer on socket: %s", strerror(errno) );
        SLP_LOG( SLP_LOG_ERR, msg );
    }
*/
 /* set up multicast */
    if ((err = set_multicast_sender_interf(psa->sdUDP)) != SLP_OK)
    {
        SLP_LOG( SLP_LOG_DEBUG,"mslpd_init_network: set_multicast_sender_interf",err);
    }
    else
        SLP_LOG( SLP_LOG_DEBUG, "mslpd_init_network: set_multicast_sender_interf ok" );

  FD_ZERO(&(psa->fds));
  FD_SET(psa->sdUDP,&(psa->fds));
  FD_SET(psa->sdTCP,&(psa->fds));
   
#ifdef EXTRA_MSGS
    {
        char *pcTemp = "service:service-agent://";
        int iLen = strlen(pcTemp);
        psa->pcSAURL = safe_malloc(iLen+strlen(pc)+1,pcTemp,iLen);
        strcat(psa->pcSAURL,pc);
    }
#endif /* EXTRA_MSGS */

#ifdef MAC_OS_X        
    {
        char *pcTemp = "service:directory-agent://";
        int iLen = strlen(pcTemp);
        psa->pcDAURL = safe_malloc(iLen+strlen(pc)+1,pcTemp,iLen);
        strcat(psa->pcDAURL,pc);
    }

    psa->pcSPIList = safe_malloc(1,NULL,0);
    psa->pcSPIList[0] = '\0';	// this is just a null list for now

#endif /* MAC_OS_X */

  return SLP_OK;  
}

#endif