source: trunk/third/sysinfo/netif.c @ 12269

Revision 12269, 13.4 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12268, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 1992-1998 Michael A. Cooper.
3 * This software may be freely used and distributed provided it is not
4 * sold for profit or used in part or in whole for commercial gain
5 * without prior written agreement, and the author is credited
6 * appropriately.
7 */
8
9#ifndef lint
10static char *RCSid = "$Revision: 1.1.1.3 $";
11#endif
12
13/*
14 * Portions of code found in this file are based on the 4.3BSD
15 * netstat(8) program.
16 */
17
18/*
19 * Network Interface routines
20 */
21
22#include <stdio.h>
23#include "os.h"
24
25#include <sys/types.h>
26#include <sys/socket.h>
27#if     defined(NEED_SOCKIO)
28#include <sys/sockio.h>
29#endif  /* NEED_SOCKIO */
30#include <sys/param.h>
31#include <sys/errno.h>
32#include <netdb.h>
33#include <net/if.h>
34#include <netinet/in.h>
35#include <netinet/if_ether.h>
36#if     defined(HAVE_IN_IFADDR)
37#include <netinet/in_var.h>
38#endif  /* HAVE_IN_IFADDR */
39
40#include "defs.h"
41
42#if     GETNETIF_TYPE == GETNETIF_IFNET
43/*
44 * Network Interface symbol
45 */
46char                            NetifSYM[] = "_ifnet";
47#endif  /* GETNETIF_IFNET */
48
49/*
50 * Interface Address union
51 */
52union {
53    struct ifaddr       ifaddr;
54#if     defined(HAVE_IN_IFADDR)
55    struct in_ifaddr    in_ifaddr;
56#endif  /* HAVE_IN_IFADDR */
57}                               ifaddress;
58
59/*
60 * Create a DevInfo_t for a network interface.
61 */
62static DevInfo_t *CreateNetif(ProbeData, FullName, IfNet)
63     ProbeData_t               *ProbeData;
64     char                      *FullName;
65     struct ifnet              *IfNet;
66{
67    DevInfo_t                  *DevInfo;
68
69    /* There's no guarentee this is already set */
70    if (!ProbeData->DevDefine)
71        ProbeData->DevDefine = DevDefGet(NULL, DT_NETIF, 0);
72    else
73        ProbeData->DevDefine->Type = DT_NETIF;
74    if (FullName)
75        ProbeData->DevName = FullName;
76
77    /* Create the device */
78    if (!(DevInfo = DeviceCreate(ProbeData)))
79        return((DevInfo_t *) NULL);
80
81    if (IfNet)
82        DevInfo->Unit   = IfNet->if_unit;
83
84    if (!DevInfo->Model) {
85#if     defined(HAVE_IF_VERSION)
86        if (IfNet->if_version && IfNet->if_version[0])
87            DevInfo->Model      = strdup(IfNet->if_version);
88        else
89#endif  /* HAVE_IF_VERSION */
90            if (ProbeData->DevDefine)
91                DevInfo->Model  = ProbeData->DevDefine->Model;
92    }
93
94    if (!DevInfo->ModelDesc && ProbeData->DevDefine)
95        DevInfo->ModelDesc = ProbeData->DevDefine->Desc;
96
97    return(DevInfo);
98}
99
100/*
101 * Return the netent of the network whose address is given.
102 * The address is assumed to be that of a net or subnet, not a host.
103 */
104static struct netent *GetNet(inaddr, mask)
105    u_long                      inaddr;
106    u_long                      mask;
107{
108    u_long                      net;
109    register u_long             i, netaddr;
110    int                         subnetshift;
111    static struct in_addr       in_addr;
112
113    if (in_addr.s_addr = inaddr) {
114        i = in_addr.s_addr;
115        if (mask == 0) {
116            if (IN_CLASSA(i)) {
117                mask = IN_CLASSA_NET;
118                subnetshift = 8;
119            } else if (IN_CLASSB(i)) {
120                mask = IN_CLASSB_NET;
121                subnetshift = 8;
122            } else {
123                mask = IN_CLASSC_NET;
124                subnetshift = 4;
125            }
126            /*
127             * If there are more bits than the standard mask
128             * would suggest, subnets must be in use.
129             * Guess at the subnet mask, assuming reasonable
130             * width subnet fields.
131             */
132            while (in_addr.s_addr &~ mask)
133                mask = (long)mask >> subnetshift;
134        }
135        net = in_addr.s_addr & mask;
136        while ((mask & 1) == 0)
137            mask >>= 1, net >>= 1;
138        netaddr = net;
139    } else {
140        netaddr = inaddr;
141    }
142
143    return(getnetbyaddr(netaddr, AF_INET));
144}
145
146/*
147 * Get NetIF_t for an Internet address
148 */
149extern NetIF_t *GetNetifINET(AddrFam, hostaddr, maskaddr)
150    AddrFamily_t               *AddrFam;
151    struct sockaddr_in         *hostaddr;
152    struct sockaddr_in         *maskaddr;
153{
154    struct in_addr              in_addr;
155    struct netent              *np;
156    struct hostent             *hp;
157    struct sockaddr_in         *sin;
158    char                       *inet_ntoa();
159    NetIF_t                    *ni;
160
161    ni = NewNetif(NULL);
162
163    if (hostaddr && maskaddr) {
164        np = GetNet((u_long) hostaddr->sin_addr.s_addr,
165                    (u_long) maskaddr->sin_addr.s_addr);
166        in_addr.s_addr = hostaddr->sin_addr.s_addr &
167          maskaddr->sin_addr.s_addr;
168        ni->NetAddr = strdup(inet_ntoa(in_addr));
169        sin = hostaddr;
170    } else {
171#if     defined(HAVE_IN_IFADDR)
172        np = GetNet((u_long) ifaddress.in_ifaddr.ia_subnet,
173                    (u_long) ifaddress.in_ifaddr.ia_subnetmask);
174        in_addr.s_addr = ifaddress.in_ifaddr.ia_subnet;
175        ni->NetAddr = strdup(inet_ntoa(in_addr));
176        sin = (struct sockaddr_in *) &ifaddress.in_ifaddr.ia_addr;
177#endif  /* HAVE_IN_IFADDR */
178    }
179
180    ni->HostAddr = strdup(inet_ntoa(sin->sin_addr));
181    hp = gethostbyaddr((char *) &(sin->sin_addr),
182                       sizeof(struct in_addr), AF_INET);
183
184    if (hp)
185        ni->HostName = strdup(hp->h_name);
186
187    if (np)
188        ni->NetName = strdup(np->n_name);
189           
190    if (AddrFam)
191        ni->TypeName = AddrFam->Name;
192
193    return(ni);
194}
195
196/*
197 * Get NetIF_t for an unknown address type
198 */
199extern NetIF_t *GetNetifUnknown(AddrFam)
200    AddrFamily_t               *AddrFam;
201{
202    NetIF_t                    *ni = NULL;
203
204    ni = NewNetif(NULL);
205    ni->HostAddr = "<unknown>";
206    if (AddrFam)
207        ni->TypeName = AddrFam->Name;
208
209    return(ni);
210}
211
212/*
213 * Get an Address Family table entry
214 */
215static AddrFamily_t *GetAddrFamily(type)
216    int                         type;
217{
218    extern AddrFamily_t         AddrFamily[];
219    register int                i;
220
221    for (i = 0; AddrFamily[i].Name; ++i)
222        if (AddrFamily[i].Type == type)
223            return(&AddrFamily[i]);
224
225    return((AddrFamily_t *) NULL);
226}
227
228/*
229 * See if IfName matches any names in ProbeData and return name
230 * found.
231 */
232static int IFmatch(ProbeData, IfName)
233     ProbeData_t               *ProbeData;
234     char                      *IfName;
235{
236    register char             **cpp;
237
238    if (!ProbeData)
239        return(FALSE);
240
241    if (EQ(ProbeData->DevName, IfName))
242        return(TRUE);
243
244    for (cpp = ProbeData->AliasNames; cpp && *cpp; ++cpp)
245        if (EQ(*cpp, IfName))
246            return(TRUE);
247
248    return(FALSE);
249}
250
251#if     GETNETIF_TYPE == GETNETIF_IFNET
252/*
253 * Get a linked list of NetIF_t's for each address starting at 'startaddr'.
254 */
255static NetIF_t *GetNetifAddrs(kd, startaddr, FullName, DevInfo)
256    kvm_t                      *kd;
257    off_t                       startaddr;
258    char                       *FullName;
259    DevInfo_t                  *DevInfo;
260{
261    u_long                      addr;
262    NetIF_t                    *base = NULL;
263    register NetIF_t           *ni, *pni;
264    AddrFamily_t               *AddrFamPtr;
265
266    for (addr = startaddr; addr; addr = (u_long) ifaddress.ifaddr.ifa_next) {
267        /*
268         * Read the ifaddr structure from kernel space
269         */
270        if (KVMget(kd, addr, (char *) &ifaddress,
271                   sizeof(ifaddress), KDT_DATA)) {
272            SImsg(SIM_GERR, "cannot read if address");
273            continue;
274        }
275
276        /*
277         * Now get and call the Address Family specific routine
278         * to extract a NetIF_t.
279         */
280        if (AddrFamPtr = GetAddrFamily(ifaddress.ifaddr.ifa_addr.sa_family)) {
281            if (ni = (*AddrFamPtr->GetNetIF)(AddrFamPtr, NULL, NULL))
282                SetMacInfo(DevInfo, ni);
283        } else {
284            SImsg(SIM_DBG, "Address family %d is not defined.",
285                             ifaddress.ifaddr.ifa_addr.sa_family);
286            continue;
287        }
288
289        /*
290         * Add the new NetIF_t to the base of the linked list.
291         */
292        if (base) {
293            for (pni = base; pni && pni->Next; pni = pni->Next);
294            pni->Next = ni;
295        } else {
296            base = ni;
297        }
298    }
299
300    return(base);
301}
302
303/*
304 * Query/find network interface devices and add them to devicelist
305 */
306extern DevInfo_t *ProbeNetif(ProbeData)
307     ProbeData_t               *ProbeData;
308{
309    DevInfo_t                  *DevInfo = NULL;
310    static struct ifnet         ifnet;
311    static char                 ifname[16], FullName[17];
312    nlist_t                    *nlptr;
313    register char              *p;
314    u_long                      ifnetaddr;
315    kvm_t                      *kd;
316    char                       *DevName;
317    DevData_t                  *DevData;
318    DevDefine_t                *DevDefine;
319    int                         NameMatch = FALSE;
320
321    if (!ProbeData || !ProbeData->DevName)
322        return((DevInfo_t *) NULL);
323
324    DevName = ProbeData->DevName;
325    DevData = ProbeData->DevData;
326    DevDefine = ProbeData->DevDefine;
327    SImsg(SIM_DBG, "ProbeNetif(%s)", DevName);
328
329    if (!(kd = KVMopen()))
330        return((DevInfo_t *) NULL);
331
332    if ((nlptr = KVMnlist(kd, NetifSYM, (nlist_t *)NULL, 0)) == NULL)
333        return((DevInfo_t *) NULL);
334
335    if (CheckNlist(nlptr))
336        return((DevInfo_t *) NULL);
337
338    /*
339     * Read address of ifnet structure from kernel space
340     */
341    if (KVMget(kd, nlptr->n_value, (char *) &ifnetaddr,
342                sizeof(ifnetaddr), KDT_DATA)) {
343        SImsg(SIM_GERR, "kvm_read ifnetaddr failed");
344        KVMclose(kd);
345        return((DevInfo_t *) NULL);
346    }
347
348    /*
349     * Read and then check each ifnet entry we found.
350     */
351    for (; ifnetaddr; ifnetaddr = (off_t) ifnet.if_next) {
352        /*
353         * Read the ifnet structure
354         */
355        if (KVMget(kd, ifnetaddr, (char *)&ifnet, sizeof(ifnet), KDT_DATA)) {
356            SImsg(SIM_GERR, "kvm_read ifnetaddr ifnet failed");
357            continue;
358        }
359
360        /*
361         * Read if_name from kernel space
362         */
363        if (KVMget(kd, (u_long)ifnet.if_name, ifname,
364                   sizeof(ifname), KDT_STRING)) {
365            SImsg(SIM_GERR, "kvm_read ifname failed");
366            continue;
367        }
368
369        /*
370         * Copy if_name to 'FullName' and add unit number
371         */
372        (void) snprintf(FullName, sizeof(FullName),  "%s%d", ifname, ifnet.if_unit);
373
374        /*
375         * Check to see if this is the interface we want.
376         */
377        if (IFmatch(ProbeData, FullName)) {
378            NameMatch = TRUE;
379            break;
380        }
381    }
382
383    if (!NameMatch) {
384        /* Device Not Found */
385        SImsg(SIM_DBG, "%s: Could not find netif in ifconf table.", DevName);
386        return((DevInfo_t *) NULL);
387    }
388
389    /*
390     * Create and set device
391     */
392    DevInfo = CreateNetif(ProbeData, FullName, &ifnet);
393
394    /*
395     * Get and set address info
396     */
397    if (ifnet.if_addrlist) {
398        NetIF_t                *ni;
399       
400        if (ni = GetNetifAddrs(kd, (off_t) ifnet.if_addrlist,
401                               FullName, DevInfo))
402            DevInfo->DevSpec = (caddr_t *) ni;
403    }
404
405    KVMclose(kd);
406
407    return(DevInfo);
408}
409#endif  /* GETNETIF_IFNET */
410
411#if     GETNETIF_TYPE == GETNETIF_IFCONF
412/*
413 * Set network address data.
414 */
415static int SetNetifAddrs(ifname, sock, hostaddr, maskaddr)
416    char                       *ifname;
417    int                         sock;
418    struct sockaddr_in         *hostaddr;
419    struct sockaddr_in         *maskaddr;
420{
421    struct ifreq                ifr;
422
423    (void) strcpy(ifr.ifr_name, ifname);
424
425    /*
426     * Get address info
427     */
428    if (ioctl(sock, SIOCGIFADDR, (char *) &ifr) < 0) {
429        SImsg(SIM_GERR, "%s: ioctl SIOCGIFADDR failed: %s.", ifname, SYSERR);
430        return(-1);
431    }
432    memcpy((char *)hostaddr, (char *)&ifr.ifr_addr,
433           sizeof(struct sockaddr_in));
434
435    /*
436     * Get the network mask
437     */
438    if (ioctl(sock, SIOCGIFNETMASK, (char *) &ifr) < 0) {
439        SImsg(SIM_GERR, "%s: ioctl SIOCGIFNETMASK failed: %s.",
440                         ifname, SYSERR);
441        return(-1);
442    }
443    memcpy((char *)maskaddr, (char *)&ifr.ifr_addr,
444           sizeof(struct sockaddr_in));
445
446    return(0);
447}
448
449/*
450 * Query/find network interface devices and add them to devicelist
451 */
452extern DevInfo_t *ProbeNetif(ProbeData)
453     ProbeData_t               *ProbeData;
454{
455    DevInfo_t                  *DevInfo = NULL;
456    NetIF_t                    *ni;
457    struct ifreq               *ifreq;
458    static struct ifconf        ifconf;
459    static struct sockaddr_in   HostAddr;
460    static struct sockaddr_in   MaskAddr;
461    static char                 ReqBuff[BUFSIZ];
462    static int                  SockDesc = -1;
463    register int                n;
464    register char             **cpp;
465    register char              *Alias = NULL;
466    AddrFamily_t               *AddrFamPtr;
467    int                         NameMatch = FALSE;
468    char                       *DevName;
469    DevData_t                  *DevData;
470    DevDefine_t                *DevDefine;
471
472    if (!ProbeData || !ProbeData->DevName)
473        return((DevInfo_t *) NULL);
474
475    DevName = ProbeData->DevName;
476    DevData = ProbeData->DevData;
477    DevDefine = ProbeData->DevDefine;
478    SImsg(SIM_DBG, "ProbeNetif(%s)", DevName);
479
480    if (SockDesc < 0) {
481        /*
482         * Get list of all interfaces
483         */
484        ifconf.ifc_len = sizeof(ReqBuff);
485        ifconf.ifc_buf = ReqBuff;
486
487        if ((SockDesc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
488            SImsg(SIM_GERR, "Cannot create socket: %s.", SYSERR);
489            return((DevInfo_t *)NULL);
490        }
491
492        if (ioctl(SockDesc, SIOCGIFCONF, (char *) &ifconf) < 0) {
493            SImsg(SIM_GERR, "%s: ioctl SIOCGIFCONF failed: %s.",
494                             DevName, SYSERR);
495            return((DevInfo_t *)NULL);
496        }
497    }
498
499    /*
500     * Iterate over all known interfaces
501     */
502    for (ifreq = ifconf.ifc_req, n = ifconf.ifc_len/sizeof(struct ifreq);
503         --n >= 0; ifreq++) {
504
505        /*
506         * Compare the hardware DevName as passed to us, the config file name
507         * and all config file aliases.
508         * Check to see if this is the interface we want.
509         */
510        if (IFmatch(ProbeData, ifreq->ifr_name)) {
511            NameMatch = TRUE;
512            break;
513        }
514
515        if (DevDefine && DevData && !NameMatch) {
516            /* Check config file name */
517            Alias = MkDevName(DevDefine->Name, DevData->DevUnit,
518                              DevDefine->Type, DevDefine->Flags);
519            if (EQ(Alias, ifreq->ifr_name)) {
520                NameMatch = TRUE;
521                break;
522            }
523         
524            /* Check all name aliases */
525            for (cpp = DevDefine->Aliases; !NameMatch && cpp && *cpp; ++cpp) {
526                Alias = MkDevName(*cpp, DevData->DevUnit,
527                                  DevDefine->Type, DevDefine->Flags);
528                if (EQ(Alias, ifreq->ifr_name)) {
529                    NameMatch = TRUE;
530                    break;
531                }
532            }
533        }
534    }
535
536    if (!NameMatch) {
537        /* Device Not Found */
538        SImsg(SIM_DBG, "%s: Could not find netif in ifconf table.", DevName);
539        return((DevInfo_t *) NULL);
540    }
541
542    /* Use the system's canonical name */
543    ProbeData->DevName = ifreq->ifr_name;
544    if (!(DevInfo = DeviceCreate(ProbeData)))
545        return((DevInfo_t *) NULL);
546
547    DevInfo->Type = DT_NETIF;
548
549    /*
550     * Set address info
551     */
552    if (SetNetifAddrs(ifreq->ifr_name, SockDesc, &HostAddr, &MaskAddr) == 0) {
553        /*
554         * Now get and call the Address Family specific routine
555         * to extract a NetIF_t.
556         */
557        if (AddrFamPtr = GetAddrFamily(HostAddr.sin_family)) {
558            if (ni = (*AddrFamPtr->GetNetIF)(AddrFamPtr, &HostAddr,
559                                             &MaskAddr)) {
560                SetMacInfo(DevInfo, ni);
561                DevInfo->DevSpec = (caddr_t *) ni;
562            }
563        } else
564            SImsg(SIM_DBG, "Address family %d is not defined.",
565                  HostAddr.sin_family);
566    }
567
568    return(ProbeData->RetDevInfo = DevInfo);
569}
570#endif  /* GETNETIF_IFCONF */
Note: See TracBrowser for help on using the repository browser.