DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T s

⟦742fe5e8d⟧ TextFile

    Length: 6731 (0x1a4b)
    Types: TextFile
    Names: »server.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/inet/server.c« 

TextFile

set noglob
echo Extracting client.c
cat > client.c <<'##EOF##'
#include <stdio.h>
#include <netdb.h>

#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <net/if.h>

extern void request_service();

/*
 *	These variables may be accessed externally in order to verify that
 *	further messages received on the socket are actually being sent by
 *	the same server.  This may easily be done using the command:
 *
 *	    bcmp( (char *) &server_addr, (char *) &addr, server_addr_size )
 */

struct sockaddr_in server_addr;
int server_addr_size = sizeof(server_addr);

/*
 *	int obtain_service( char *name, int port, int timeout_sec,
 *			    char *request, int request_size )
 *
 *	    Sends a broadcast message over the net asking for the existence
 *	of a server socket on the given port associated with the named
 *	service.  The port argument is a default port number if the service
 *	is not found in the local net DB.  If there is no response after
 *	timeout_sec seconds, then we return with -1.  If a response is
 *	received, then the socket is connected to that address and the socket
 *	number is returned.  The socket type used is SOCK_DGRAM.
 */

int
obtain_service( serv_name, serv_port, timeout_sec, request, request_size )
char *serv_name;
int serv_port;
int timeout_sec;
char *request;
int request_size;
{
    int sock;
    fd_set mask;
    struct timeval timeout;
    struct servent  *serv,  *getservbyname();
    struct protoent *proto, *getprotobyname();
    int serv_proto = 0;
    static char tbuf[64];

    /* Initialize the timeout structure */
    timeout.tv_sec = timeout_sec;
    timeout.tv_usec = 0;

    /* Get service information */
    serv_port = htons(serv_port);
    if ( (serv = getservbyname( serv_name, (char *) 0 )) != NULL ) {
	serv_port = serv->s_port;
#ifdef PROTO_SUPPORTED
	if ( (proto = getprotobyname(serv->s_proto)) != NULL )
	    serv_proto = proto->p_proto;
#endif PROTO_SUPPORTED
    }

#ifdef DEBUG
    printf( "Access port %d and proto %d\n", ntohs(serv_port), serv_proto );
    fflush(stdout);
#endif DEBUG
    /* Initialize the socket */
    if ( (sock = socket( AF_INET, SOCK_DGRAM, serv_proto )) < 0 ) {
	perror( "creating socket to server" );
	exit(1);
    }

    /* Make the request */
    printf( "[Request service ..." ); fflush(stdout);
    request_service( sock, serv_port, request, request_size );

    /* Now, wait for some response */
    FD_ZERO(&mask);
    FD_SET(sock,&mask);
    if ( select(FD_SETSIZE,&mask,(fd_set *)0,(fd_set *)0,&timeout) <= 0 ||
	 !FD_ISSET( sock, &mask ) ) {
	printf( " timed out]\n" ); fflush(stdout);
	return -1;
    }

    /* We got a response (YAY!) */
    printf( " answered..." ); fflush(stdout);

    /* So, peek at the response (to get address) */
    if ( recvfrom( sock, tbuf, sizeof(tbuf), MSG_PEEK,
		   &server_addr, &server_addr_size ) < 0 ) {
	perror( "receive initial response" );
	exit(1);
    }

#ifdef DEBUG
    printf( "[by %s %d]...",
	    inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port) );
    fflush(stdout);
#endif DEBUG

    /* Connect socket to the address */
    if ( connect( sock, &server_addr, server_addr_size ) < 0 ) {
	perror( "connect to server" );
	exit(1);
    }

    /* Return with a happy (:-) response */
    printf( " connected]\n" ); fflush(stdout);
    return sock;
}
\f


/*
 *	int get_ifc( int sock )
 *
 *	    Put the IFCONF data structure into the ifc structure and return
 *	the number of ifreq structures it contains.
 */

static struct ifconf ifc;

int
get_ifc( sock )
int sock;
{
    static char ifc_buffer[BUFSIZ];

    ifc.ifc_len = sizeof(ifc_buffer);
    ifc.ifc_buf = ifc_buffer;
    if ( (ioctl( sock, SIOCGIFCONF, (char *) &ifc )) < 0 ) {
	perror( "get ifconf" );
	exit(1);
    }
    return ifc.ifc_len / sizeof(struct ifreq);
}
\f


/*
 *	request_service( int sock, int port, char *data, int data_len )
 *
 *	    This function broadcasts a request for the given service using
 *	the socket sock.  The request is directed at servers on the named
 *	port on all machines in the local INET network.
 */

void
request_service( sock, port, data, data_len )
int sock;
int port;
char *data;
int data_len;
{
    struct sockaddr_in sin;
    struct sockaddr dst;
    int off = 0, on = 1;
    int n;
    struct ifreq *ifr;

    /* Set socket for broadcast mode */
    if ( (setsockopt( sock,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on) )) < 0 ) {
	perror( "set socket option for broadcast" );
	exit(1);
    }

    /* Initialize broadcast address and bind socket to it */
    sin.sin_family = AF_INET;
    sin.sin_port = port;
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    bind( sock, (struct sockaddr *) &sin, sizeof(sin) );

    for ( n = get_ifc(sock), ifr = ifc.ifc_req; n > 0; --n, ++ifr ) {

	/* Only deal with AF_INET networks */
	if ( ifr->ifr_addr.sa_family != AF_INET ) continue;

	/* Use the current address by default */
	bzero( (char *) &dst, sizeof(dst) );
	bcopy( (char *)&ifr->ifr_addr, (char *)&dst, sizeof(ifr->ifr_addr) );

	/* Get the flags */
	if ( ioctl( sock, SIOCGIFFLAGS, (char *) ifr ) < 0 ) {
	    perror( "get ifr flags" );
	    exit(1);
	}

	/* Skip unusable cases */
	if ( !(ifr->ifr_flags & IFF_UP) ||	    /* If not up, OR */
	     (ifr->ifr_flags & IFF_LOOPBACK ) ||    /* if loopback, OR */
	     !(ifr->ifr_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) )
	    continue;

	/* Now, determine the address to send to */
	if ( ifr->ifr_flags & IFF_POINTOPOINT ) {
	    if ( ioctl( sock, SIOCGIFDSTADDR, (char *) ifr ) < 0 ) {
		perror( "get ifr destination address" );
		exit(1);
	    }
	    bcopy( (char *) &ifr->ifr_dstaddr,
		   (char *) &dst,
		   sizeof(ifr->ifr_dstaddr) );
	}
	if ( ifr->ifr_flags & IFF_BROADCAST ) {
	    if ( ioctl( sock, SIOCGIFBRDADDR, (char *) ifr ) < 0 ) {
		perror( "get ifr broadcast address" );
		exit(1);
	    }
	    bcopy( (char *) &ifr->ifr_broadaddr,
		   (char *) &dst,
		   sizeof(ifr->ifr_broadaddr) );
	}

	/* ... make sure that the port number is OK */
	if ( dst.sa_family == AF_INET ) {
	    struct sockaddr_in *sa_in = (struct sockaddr_in *) &dst;
	    sa_in->sin_port = port;
#ifdef DEBUG
	    printf( "Request address = %s (%d)\n",
		    inet_ntoa(sa_in->sin_addr), ntohs(port) );
	    fflush(stdout);
#endif DEBUG
	}

	/* ... and send the request */
	if ( sendto( sock, data, data_len, 0,
		     (struct sockaddr *) &dst, sizeof(dst) ) < 0 ) {
	    perror( "sendto" );
	    exit(1);
	}
    }

    /* Reset socket option to normal operation */
    if ( (setsockopt( sock,SOL_SOCKET,SO_BROADCAST,&off,sizeof(off) )) < 0 ) {
	perror( "reset socket option for no broadcast" );
	exit(1);
    }
}
##EOF##
echo Extracting service.h
cat > service.h <<'##EOF##'