ftp.nice.ch/pub/next/unix/admin/sysinfo.1.1.0.s.tar.gz#/netif.c

This is netif.c in view mode; [Download] [Up]

/*
 * Copyright (c) 1992 Michael A. Cooper.
 * This software may be freely distributed provided it is not sold for 
 * profit and the author is credited appropriately.
 */

#ifndef lint
static char *RCSid = "$Header: /src/common/usc/bin/sysinfo/RCS/netif.c,v 1.20 1992/11/24 04:12:19 mcooper Exp mcooper $";
#endif

/*
 * $Log: netif.c,v $
 * Revision 1.20  1992/11/24  04:12:19  mcooper
 * Use new KVM/nlist interface.
 *
 * Revision 1.19  1992/07/07  23:28:38  mcooper
 * Put wrapper macro around nlist stuff to fix NeXT/Mach declaration
 * problem.  Now works with NeXT 2.* cc compiler.
 *
 * Revision 1.18  1992/04/26  23:32:06  mcooper
 * Add Copyright notice
 *
 * Revision 1.17  1992/04/17  01:07:59  mcooper
 * More de-linting
 *
 * Revision 1.16  1992/04/16  02:25:39  mcooper
 * Bug fixes, de-linting, and other changes found with CodeCenter.
 *
 * Revision 1.15  1992/03/31  01:55:17  mcooper
 * Use new CheckNlist to check nlist success.
 *
 * Revision 1.14  1992/03/31  00:15:09  mcooper
 * Add error check for nlist.n_type.
 *
 * Revision 1.13  1992/03/28  21:29:38  mcooper
 * Initial port to NeXT.  Only works partially.
 *
 * Revision 1.12  1992/03/22  00:20:10  mcooper
 * Major cleanup and re-org.
 *
 * Revision 1.11  1992/03/09  01:24:05  mcooper
 * Remove HAVE_NIT stuff.
 *
 * Revision 1.10  1992/03/08  23:09:18  mcooper
 * - Cleanup set_macinfo() code to support Ultrix packetfilter.
 * - Pass device down to set_macinfo().
 *
 * Revision 1.9  1992/03/08  04:53:39  mcooper
 * Major re-write to clean things up and add better
 * support for multiple addresses per interface.
 *
 * Revision 1.8  1992/03/05  22:36:35  mcooper
 * Cleanup format.
 *
 * Revision 1.7  1992/03/05  22:11:02  mcooper
 * Cleanup variable declarations.
 *
 * Revision 1.6  1992/02/25  23:36:58  mcooper
 * Remove NULL garbage at end of source file.
 *
 * Revision 1.5  1992/02/25  03:08:43  mcooper
 * Fix gethostbyaddr() stuff for sun3/sun386.
 *
 * Revision 1.4  1992/02/25  00:16:57  mcooper
 * Use new mkmaster_from_devdata().
 *
 * Revision 1.3  1992/02/22  02:20:19  mcooper
 * Major changes to support scanning kernel mainbus and
 * openprom data for device's.
 *
 * Revision 1.2  1992/02/20  04:15:16  mcooper
 * Update known interfaces.
 *
 * Revision 1.1  1992/02/16  22:48:39  mcooper
 * Initial revision
 *
 */


/*
 * Portions of code found in this file are based on the 4.3BSD 
 * netstat(8) program.
 */

/*
 * Network Interface routines
 */

#include <stdio.h>
#include "system.h"

#include <fcntl.h>
#include <nlist.h>
#include <sys/types.h>
#include <sys/socket.h>
#if	defined(NEED_SOCKIO)
#include <sys/sockio.h>
#endif	/* NEED_SOCKIO */
#include <sys/param.h>
#include <sys/errno.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
#include <netdb.h>

#include "defs.h"

/*
 * Network Interface symbol
 */
char 				NetifSYM[] = "_ifnet";

static struct netent 	       *GetNet();
static void 			SetMacInfo();

/*
 * Interface Address union
 */
union {
    struct ifaddr 	ifa;
    struct in_ifaddr 	in;
} 				ifaddr;

/*
 * Create a DEVICE for a network interface.
 */
static DEVICE *CreateNetif(FullName, IfNet, DevData, DevDataTab)
    char		       *FullName;
    struct ifnet               *IfNet;
    DEVDATA		       *DevData;
    DEVDATATAB		       *DevDataTab;
{
    DEVICE		       *dev;

    dev = NewDevice(NULL);

    dev->dv_name 	= strdup(FullName);
    dev->dv_type 	= DT_NETIF;
    dev->dv_unit 	= IfNet->if_unit;
    dev->dv_master 	= MkMasterFromDevData(DevData);

#if	defined(HAVE_IF_VERSION)
    if (IfNet->if_version && IfNet->if_version[0])
	dev->dv_model 	= strdup(IfNet->if_version);
    else
#endif	/* HAVE_IF_VERSION */
	dev->dv_model 	= DevDataTab->ddt_model;

    dev->dv_desc 	= DevDataTab->ddt_desc;

    return(dev);
}

/*
 * Get NETIF for an Internet address
 */
extern NETIF *GetNetifINET(aftab)
    AFTAB		       *aftab;
{
    struct in_addr		in_addr;
    struct netent 	       *np;
    struct hostent 	       *hp;
    struct sockaddr_in 	       *sin;
    char		       *inet_ntoa();
    NETIF		       *ni;

    ni = NewNetif(NULL);

    np = GetNet(htonl(ifaddr.in.ia_subnet), ifaddr.in.ia_subnetmask);
    in_addr.s_addr = ntohl(ifaddr.in.ia_subnet);
    ni->ni_netaddr = strdup(inet_ntoa(in_addr));
    if (np)
	ni->ni_netname = strdup(np->n_name);
	    
    sin = (struct sockaddr_in *)&ifaddr.in.ia_addr;
    ni->ni_hostaddr = strdup(inet_ntoa(sin->sin_addr));
    hp = gethostbyaddr((char *) &(sin->sin_addr),
		       sizeof(struct in_addr),
		       AF_INET);
    if (hp)
	ni->ni_hostname = strdup(hp->h_name);

    if (aftab)
	ni->ni_typename = aftab->af_name;

    return(ni);
}

/*
 * Get NETIF for an unknown address type
 */
extern NETIF *GetNetifUnknown(aftab)
    AFTAB		       *aftab;
{
    NETIF		       *ni = NULL;

    ni = NewNetif(NULL);
    ni->ni_hostaddr = "<unknown>";
    if (aftab) {
	ni->ni_typename = aftab->af_name;
    }

    return(ni);
}

/*
 * Get an Address Family table entry
 */
static AFTAB *GetAFTab(type)
    int				type;
{
    extern AFTAB		AFTab[];
    register int		i;

    for (i = 0; AFTab[i].af_name; ++i)
	if (AFTab[i].af_type == type)
	    return(&AFTab[i]);

    return((AFTAB *) NULL);
}

/*
 * Get a linked list of NETIF's for each address starting at 'startaddr'.
 */
static NETIF *GetNetifAddrs(kd, startaddr, FullName, Device)
    kvm_t		       *kd;
    off_t			startaddr;
    char		       *FullName;
    DEVICE		       *Device;
{
    u_long			addr;
    NETIF		       *base = NULL;
    register NETIF	       *ni, *pni;
    AFTAB		       *paftab;

    for (addr = startaddr; addr; addr = (off_t) ifaddr.ifa.ifa_next) {
	/*
	 * Read the ifaddr structure from kernel space
	 */
	if (KVMread(kd, addr, (char *) &ifaddr, sizeof(ifaddr))) {
	    Error("cannot read if address");
	    continue;
	}

	/*
	 * Now get and call the Address Family specific routine
	 * to extract a NETIF.
	 */
	if (paftab = GetAFTab(ifaddr.ifa.ifa_addr.sa_family)) {
	    if (ni = (*paftab->af_getnetif)(paftab))
		SetMacInfo(FullName, ni, Device);
	} else {
	    if (Debug) Error("Address family %d is not defined.", 
			     ifaddr.ifa.ifa_addr.sa_family);
	    continue;
	}

	/*
	 * Add the new NETIF to the base of the linked list.
	 */
	if (base) {
	    for (pni = base; pni && pni->ni_nxt; pni = pni->ni_nxt);
	    pni->ni_nxt = ni;
	} else {
	    base = ni;
	}
    }

    return(base);
}

/*
 * Find and set the MAC info
 */
static void SetMacInfo(DevName, NetIf, Device)
    char 		       *DevName;
    NETIF 		       *NetIf;
    DEVICE		       *Device;	/* ARGSUSED */
{
#if	defined(HAVE_NIT)
    extern void 		SetMacInfoNIT();

    SetMacInfoNIT(DevName, NetIf);
    return;
#endif	/* HAVE_NIT */

#if	defined(HAVE_PACKETFILTER)
    extern void			SetMacInfoPacketFilter();

    SetMacInfoPacketFilter(DevName, NetIf, Device);
    return;
#endif	/* HAVE_PACKETFILTER */
}

/*
 * Return the netent of the network whose address is given.
 * The address is assumed to be that of a net or subnet, not a host.
 */
static struct netent *GetNet(inaddr, mask)
    u_long 			inaddr;
    u_long 			mask;
{
    u_long 			net;
    register u_long 		i, netaddr;
    int 			subnetshift;
    static struct in_addr 	in;

    if (in.s_addr = ntohl(inaddr)) {
	i = in.s_addr;
	if (mask == 0) {
	    if (IN_CLASSA(i)) {
		mask = IN_CLASSA_NET;
		subnetshift = 8;
	    } else if (IN_CLASSB(i)) {
		mask = IN_CLASSB_NET;
		subnetshift = 8;
	    } else {
		mask = IN_CLASSC_NET;
		subnetshift = 4;
	    }
	    /*
	     * If there are more bits than the standard mask
	     * would suggest, subnets must be in use.
	     * Guess at the subnet mask, assuming reasonable
	     * width subnet fields.
	     */
	    while (in.s_addr &~ mask)
		mask = (long)mask >> subnetshift;
	}
	net = in.s_addr & mask;
	while ((mask & 1) == 0)
	    mask >>= 1, net >>= 1;
	netaddr = net;
    } else {
	netaddr = inaddr;
    }

    return(getnetbyaddr(netaddr, AF_INET));
}

/*
 * Query/find network interface devices and add them to devicelist
 */
extern DEVICE *ProbeNetif(name, DevData, DevDataTab)
    char 		       *name;
    DEVDATA 		       *DevData;
    DEVDATATAB	 	       *DevDataTab;
{
    DEVICE 		       *dev = NULL;
    static struct ifnet         ifnet;
    static char 		ifname[16], FullName[17];
    struct nlist	       *nlptr;
    register char	       *p;
    u_long 		        ifnetaddr;
    kvm_t 		       *kd;

    if (!(kd = KVMopen()))
	return((DEVICE *) NULL);

    if ((nlptr = KVMnlist(kd, NetifSYM, (struct nlist *)NULL)) == NULL)
	return((DEVICE *) NULL);

    if (CheckNlist(nlptr))
	return((DEVICE *) NULL);

    /*
     * Read address of ifnet structure from kernel space
     */
    if (KVMread(kd, nlptr->n_value, (char *) &ifnetaddr, 
		sizeof(ifnetaddr))) {
	if (Debug) Error("kvm_read ifnetaddr failed");
	KVMclose(kd);
	return((DEVICE *) NULL);
    }

    /*
     * Read and then check each ifnet entry we found.
     */
    for (; ifnetaddr; ifnetaddr = (off_t) ifnet.if_next) {
	/*
	 * Read the ifnet structure
	 */
	if (KVMread(kd, ifnetaddr, (char *)&ifnet, sizeof(ifnet))) {
	    if (Debug) Error("kvm_read ifnetaddr ifnet failed");
	    continue;
	}

	/*
	 * Read if_name from kernel space
	 */
	if (KVMread(kd, (u_long)ifnet.if_name, ifname, sizeof(ifname))) {
	    if (Debug) Error("kvm_read ifname failed");
	    continue;
	}

	/*
	 * Copy if_name to 'FullName' and add unit number
	 */
	strncpy(FullName, ifname, sizeof(ifname));
	p = (char *) index(FullName, C_NULL);
	*p++ = ifnet.if_unit + '0';
	*p = C_NULL;
	ifname[sizeof(ifname)-1] = C_NULL;

	/*
	 * Check to see if this is the interface we want.
	 */
	if (!EQ(FullName, name))
	    continue;

	/*
	 * Create and set device
	 */
	dev = CreateNetif(FullName, &ifnet, DevData, DevDataTab);

	/*
	 * Get and set address info
	 */
	if (ifnet.if_addrlist) {
	    NETIF 	       *ni;

	    if (ni = GetNetifAddrs(kd, (off_t) ifnet.if_addrlist, 
				   FullName, dev))
		dev->dv_devspec = (caddr_t *) ni;
	}
    }

    KVMclose(kd);

    return(dev);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.