Xinu7/contrib/distodt/src/netutils.c

Compare this file to the similar file:
Show the results in this format:


/* 
 * netutils.c - Handy routines for dealing with the network
 * 
 * Author:	Tim Korb/Shawn Oostermann/Jim Griffioen
 * 		Dept. of Computer Sciences
 * 		Purdue University
 * Date:	Thu Jun  9 21:32:25 1988
 *
 * Copyright (c) 1988 Tim Korb/Shawn Oostermann/Jim Griffioen
 */

# include <stdio.h>
# include <ctype.h>
# include <sys/time.h>
# include <assert.h>
# include <errno.h>

# include <netdb.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>

#include "../h/bed.h"

extern int errno;

# include "../h/utils.h"
# include "../h/netutils.h"

/*
 *---------------------------------------------------------------------------
 * GetNetName (ia) -- get name of network corresponding to network address ia.
 *---------------------------------------------------------------------------
 */
char *GetNetName (ia)
struct in_addr ia;
{
    struct netent *pne;

    if ((pne = getnetbyaddr (inet_netof (ia))) == NULL)
        SysError ("getnetbyaddr");
    return pne->n_name;
}

/*
 *---------------------------------------------------------------------------
 * ConnectUdp (sbHost, port) -- create a udp socket to destination
 * port on sbHost. Connect the socket to the port.
 *---------------------------------------------------------------------------
 */
int ConnectUdp (sbHost, port)
char *sbHost;
int port;
{
    int fd;
    struct sockaddr_in sa;	/* sa = socket address */
    struct hostent *phe;	/* he = host entry */
    struct in_addr na;		/* na = network address */
    struct servent *pse;	/* se = service entry */

    if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
        SysError ("socket");

    if ((phe = gethostbyname (sbHost)) == NULL)
        Error ("unknown host: %s", sbHost);

    na = *( (struct in_addr *) (phe->h_addr));

    sa.sin_port = htons(port);

    sa.sin_family = AF_INET;
    sa.sin_addr = na;
    if (connect (fd, &sa, lsa) == -1) {
        if (errno == ECONNREFUSED)
	    Error ("No process at port %d on host '%s'.\n", port, sbHost);
	else if (errno == ENETUNREACH)
	    Error ("Can't get to network %s from here.\n", GetNetName (sa.sin_addr));
        else
	    SysError ("connect");
	}
    return fd;
}

/*
 *---------------------------------------------------------------------------
 * FdToRemoteSa (fd) -- return psa of remote socket associated with fd.
 *---------------------------------------------------------------------------
 */
struct sockaddr_in *FdToRemoteSa (fd)
int fd;
{
    static struct sockaddr_in sa;
    int lsaT = lsa;

    if (getpeername (fd, &sa, &lsaT) == -1)
        SysError ("getpeername");
    assert (lsaT == lsa);
    assert (sa.sin_family == AF_INET);

    return &sa;
}

/*
 *---------------------------------------------------------------------------
 * FdToLocalSa (fd) -- return psa of local socket associated with fd.
 *---------------------------------------------------------------------------
 */
struct sockaddr_in *FdToLocalSa (fd)
int fd;
{
    static struct sockaddr_in sa;
    int lsaT = lsa;

    if (getsockname (fd, &sa, &lsaT) == -1)
        SysError ("getsockname");
    assert (lsaT == lsa);
    assert (sa.sin_family == AF_INET);

    {	/* since getsockname doesn't fill in our internet address... */
	char sb[100];
	struct hostent *phe;

	if (gethostname (sb, sizeof (sb)) != 0)
	    SysError ("gethostname");
	if ((phe = gethostbyname (sb)) == NULL)
	    SysError ("gethostbyname");
	sa.sin_addr = *(struct in_addr *) phe->h_addr;
    }

    return &sa;
}

/*
 *---------------------------------------------------------------------------
 * IaToSb (ia) -- convert internet address to string representation.
 *---------------------------------------------------------------------------
 */
char *IaToSb (ia)
struct in_addr ia;
{
    struct hostent *phe;
    static char sb[100];

# define iMax 100
    static char *rgsb[iMax];		/* cache */
    static struct in_addr rgia[iMax];
    static int iMac = 0;
    int i;

/* fprintf (stderr, "iatosb: %d (sb: '%s') ...\n", ia.s_addr, sb); fflush (stderr); */

    if (ia.s_addr == 0)
        return "0";

    for (i = 0; i < iMac; i++)
        if (rgia[i].s_addr == ia.s_addr)
	    return rgsb[i];

    phe = gethostbyaddr (&ia.s_addr, sizeof (ia.s_addr), AF_INET);
    if (phe == NULL)
        strcpy (sb, inet_ntoa (ia.s_addr));
    else {
        char *pch = (char *) index (phe->h_name, '-');
    	if (pch == NULL)	/* omit prefix on name if any */
            pch = phe->h_name;
    	else
            pch++;
        strcpy (sb, pch);
	}
    
/* fprintf (stderr, "sb: '%s'\n", sb); fflush (stderr); */

    if (iMac >= iMax) {
        Log ("IaToSb CACHE FULL");
	return sb;
	}
    else {
        rgsb[iMac] = (char *) strcpy (malloc (strlen (sb)+1), sb);
        rgia[iMac] = ia;
        return rgsb[iMac++];
	}
}

/*
 *---------------------------------------------------------------------------
 * ConnectTcp (sbHost, port) -- open a tcp connection to host sbHost at
 * the port named port. Return a two-way file descriptor to that socket.
 *---------------------------------------------------------------------------
 */
int ConnectTcp (sbHost, port)
char *sbHost;
int port;
{
    int fd;
    struct sockaddr_in sa;	/* sa = socket address */
    struct hostent *phe;	/* he = host entry */
    struct servent *pse;	/* se = service entry */

    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
        SysError ("socket");

    sa.sin_family = AF_INET;

    if ((phe = gethostbyname (sbHost)) == NULL)
        Error ("unknown host: %s\n", sbHost);
    assert (phe->h_length == 4);
    sa.sin_addr = *( (struct in_addr *) (phe->h_addr));

    sa.sin_port = htons (port);

    if (connect (fd, &sa, sizeof sa) == -1) {
        if (errno == ECONNREFUSED)
	    Error ("No process is listening on port %d at %s.", port, sbHost);
	else if (errno == ENETUNREACH)
	    Error ("Can't get to network %s from here.\n", GetNetName (sa.sin_addr));
        else
	    SysError ("connect");
	}
    return fd;
}

/*
 *---------------------------------------------------------------------------
 * ListenTcp () -- create and return an fd that will accept TCP connections.
 *---------------------------------------------------------------------------
 */
ListenTcp (pport)
     u_short *pport;
{
    int fd;
    struct sockaddr_in sa;
    int len;

    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
        SysError ("socket");
    sa.sin_family = AF_INET;
    sa.sin_port = htons(*pport);
    sa.sin_addr.s_addr = INADDR_ANY;	/* accept connection from all */

    if (bind (fd, &sa, lsa) == -1)
        SysError ("bind");

    len = sizeof (sa);
    if (getsockname(fd, &sa, &len) < 0) {
      SysError("listenTcp: getsockname");
    }
    
    if (listen (fd, SOMAXCONN) == -1)	/* set up for listening */
        SysError ("listen");

    *pport = ntohs(sa.sin_port);
    return fd;
}

/*
 *---------------------------------------------------------------------------
 * ListenUdp (port) -- create and return an fd that will receive
 * a datagram on port named by port
 *---------------------------------------------------------------------------
 */
ListenUdp (port)
     int port;
{
    int fd;
    struct sockaddr_in sa;
    struct servent *pse;

    if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
        SysError ("socket");

    sa.sin_family = AF_INET;
    sa.sin_port = htons(port);
    sa.sin_addr.s_addr = INADDR_ANY;

    if (bind (fd, &sa, lsa) == -1) {
        Log ("%d already running", port);
	exit (REALLYDIE);
	}
    return fd;
}