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.