OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [userland/] [route/] [lib/] [interface.c] - Blame information for rev 1767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 745 simons
/* Code to manipulate interface information, shared between ifconfig and
2
   netstat.
3
 
4
   10/1998 partly rewriten by Andi Kleen to support an interface list.
5
   I don't claim that the list operations are efficient @).
6
 
7
   $Id: interface.c,v 1.1 2002-03-17 19:58:53 simons Exp $
8
 */
9
 
10
#include "config.h"
11
 
12
#include <sys/types.h>
13
#include <sys/socket.h>
14
#include <sys/ioctl.h>
15
#include <netinet/in.h>
16
#include <net/if.h>
17
#include <stdio.h>
18
#include <errno.h>
19
#include <stdlib.h>
20
#include <string.h>
21
#include <unistd.h>
22
#include <ctype.h>
23
 
24
#if HAVE_AFIPX
25
#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
26
#include <netipx/ipx.h>
27
#else
28
#include "ipx.h"
29
#endif
30
#endif
31
 
32
#if HAVE_AFECONET
33
#include <neteconet/ec.h>
34
#endif
35
 
36
#ifdef HAVE_HWSLIP
37
#include <linux/if_slip.h>
38
#include <net/if_arp.h>
39
#endif
40
 
41
#include "net-support.h"
42
#include "pathnames.h"
43
#include "version.h"
44
#include "proc.h"
45
 
46
#include "interface.h"
47
#include "sockets.h"
48
#include "util.h"
49
#include "intl.h"
50
 
51
int procnetdev_vsn = 1;
52
 
53
static struct interface *int_list;
54
 
55
void add_interface(struct interface *n)
56
{
57
    struct interface *ife, **pp;
58
 
59
    pp = &int_list;
60
    for (ife = int_list; ife; pp = &ife->next, ife = ife->next) {
61
        if (nstrcmp(ife->name, n->name) > 0)
62
            break;
63
    }
64
    n->next = (*pp);
65
    (*pp) = n;
66
}
67
 
68
struct interface *lookup_interface(char *name)
69
{
70
    struct interface *ife = NULL;
71
 
72
    if (int_list || if_readlist() >= 0) {
73
        for (ife = int_list; ife; ife = ife->next) {
74
            if (!strcmp(ife->name, name))
75
                break;
76
        }
77
    }
78
 
79
    if (!ife) {
80
        new(ife);
81
        safe_strncpy(ife->name, name, IFNAMSIZ);
82
        add_interface(ife);
83
    }
84
 
85
    return ife;
86
}
87
 
88
int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
89
{
90
    struct interface *ife;
91
 
92
    if (!int_list && (if_readlist() < 0))
93
        return -1;
94
    for (ife = int_list; ife; ife = ife->next) {
95
        int err = doit(ife, cookie);
96
        if (err)
97
            return err;
98
    }
99
    return 0;
100
}
101
 
102
static int if_readconf(void)
103
{
104
    int numreqs = 30;
105
    struct ifconf ifc;
106
    struct ifreq *ifr;
107
    int n, err = -1;
108
    int skfd;
109
 
110
    /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
111
       (as of 2.1.128) */
112
    skfd = get_socket_for_af(AF_INET);
113
    if (skfd < 0) {
114
        fprintf(stderr, _("warning: no inet socket available: %s\n"),
115
                strerror(errno));
116
        /* Try to soldier on with whatever socket we can get hold of.  */
117
        skfd = sockets_open(0);
118
        if (skfd < 0)
119
            return -1;
120
    }
121
 
122
    ifc.ifc_buf = NULL;
123
    for (;;) {
124
        ifc.ifc_len = sizeof(struct ifreq) * numreqs;
125
        ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
126
 
127
        if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
128
            perror("SIOCGIFCONF");
129
            goto out;
130
        }
131
        if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
132
            /* assume it overflowed and try again */
133
            numreqs += 10;
134
            continue;
135
        }
136
        break;
137
    }
138
 
139
    ifr = ifc.ifc_req;
140
    for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
141
        lookup_interface(ifr->ifr_name);
142
        ifr++;
143
    }
144
    err = 0;
145
 
146
out:
147
    free(ifc.ifc_buf);
148
    return err;
149
}
150
 
151
static char *get_name(char *name, char *p)
152
{
153
    while (isspace(*p))
154
        p++;
155
    while (*p) {
156
        if (isspace(*p))
157
            break;
158
        if (*p == ':') {        /* could be an alias */
159
            char *dot = p, *dotname = name;
160
            *name++ = *p++;
161
            while (isdigit(*p))
162
                *name++ = *p++;
163
            if (*p != ':') {    /* it wasn't, backup */
164
                p = dot;
165
                name = dotname;
166
            }
167
            if (*p == '\0')
168
                return NULL;
169
            p++;
170
            break;
171
        }
172
        *name++ = *p++;
173
    }
174
    *name++ = '\0';
175
    return p;
176
}
177
 
178
static int procnetdev_version(char *buf)
179
{
180
    if (strstr(buf, "compressed"))
181
        return 3;
182
    if (strstr(buf, "bytes"))
183
        return 2;
184
    return 1;
185
}
186
 
187
static int get_dev_fields(char *bp, struct interface *ife)
188
{
189
    switch (procnetdev_vsn) {
190
    case 3:
191
        sscanf(bp,
192
        "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
193
               &ife->stats.rx_bytes,
194
               &ife->stats.rx_packets,
195
               &ife->stats.rx_errors,
196
               &ife->stats.rx_dropped,
197
               &ife->stats.rx_fifo_errors,
198
               &ife->stats.rx_frame_errors,
199
               &ife->stats.rx_compressed,
200
               &ife->stats.rx_multicast,
201
 
202
               &ife->stats.tx_bytes,
203
               &ife->stats.tx_packets,
204
               &ife->stats.tx_errors,
205
               &ife->stats.tx_dropped,
206
               &ife->stats.tx_fifo_errors,
207
               &ife->stats.collisions,
208
               &ife->stats.tx_carrier_errors,
209
               &ife->stats.tx_compressed);
210
        break;
211
    case 2:
212
        sscanf(bp, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
213
               &ife->stats.rx_bytes,
214
               &ife->stats.rx_packets,
215
               &ife->stats.rx_errors,
216
               &ife->stats.rx_dropped,
217
               &ife->stats.rx_fifo_errors,
218
               &ife->stats.rx_frame_errors,
219
 
220
               &ife->stats.tx_bytes,
221
               &ife->stats.tx_packets,
222
               &ife->stats.tx_errors,
223
               &ife->stats.tx_dropped,
224
               &ife->stats.tx_fifo_errors,
225
               &ife->stats.collisions,
226
               &ife->stats.tx_carrier_errors);
227
        ife->stats.rx_multicast = 0;
228
        break;
229
    case 1:
230
        sscanf(bp, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld",
231
               &ife->stats.rx_packets,
232
               &ife->stats.rx_errors,
233
               &ife->stats.rx_dropped,
234
               &ife->stats.rx_fifo_errors,
235
               &ife->stats.rx_frame_errors,
236
 
237
               &ife->stats.tx_packets,
238
               &ife->stats.tx_errors,
239
               &ife->stats.tx_dropped,
240
               &ife->stats.tx_fifo_errors,
241
               &ife->stats.collisions,
242
               &ife->stats.tx_carrier_errors);
243
        ife->stats.rx_bytes = 0;
244
        ife->stats.tx_bytes = 0;
245
        ife->stats.rx_multicast = 0;
246
        break;
247
    }
248
    return 0;
249
}
250
 
251
int if_readlist(void)
252
{
253
    FILE *fh;
254
    char buf[512];
255
    struct interface *ife;
256
    int err;
257
 
258
    fh = fopen(_PATH_PROCNET_DEV, "r");
259
    if (!fh) {
260
        perror(_PATH_PROCNET_DEV);
261
        return -1;
262
    }
263
    fgets(buf, sizeof buf, fh); /* eat line */
264
    fgets(buf, sizeof buf, fh);
265
 
266
#if 0                           /* pretty, but can't cope with missing fields */
267
    fmt = proc_gen_fmt(_PATH_PROCNET_DEV, 1, fh,
268
                       "face", "",      /* parsed separately */
269
                       "bytes", "%lu",
270
                       "packets", "%lu",
271
                       "errs", "%lu",
272
                       "drop", "%lu",
273
                       "fifo", "%lu",
274
                       "frame", "%lu",
275
                       "compressed", "%lu",
276
                       "multicast", "%lu",
277
                       "bytes", "%lu",
278
                       "packets", "%lu",
279
                       "errs", "%lu",
280
                       "drop", "%lu",
281
                       "fifo", "%lu",
282
                       "colls", "%lu",
283
                       "carrier", "%lu",
284
                       "compressed", "%lu",
285
                       NULL);
286
    if (!fmt)
287
        return -1;
288
#else
289
    procnetdev_vsn = procnetdev_version(buf);
290
#endif
291
 
292
    err = 0;
293
    while (fgets(buf, sizeof buf, fh)) {
294
        char *s;
295
 
296
        new(ife);
297
 
298
        s = get_name(ife->name, buf);
299
        get_dev_fields(s, ife);
300
        ife->statistics_valid = 1;
301
 
302
        add_interface(ife);
303
    }
304
    if (ferror(fh)) {
305
        perror(_PATH_PROCNET_DEV);
306
        err = -1;
307
    }
308
    if (!err)
309
        err = if_readconf();
310
 
311
#if 0
312
    free(fmt);
313
#endif
314
    return err;
315
}
316
 
317
/* Support for fetching an IPX address */
318
 
319
#if HAVE_AFIPX
320
static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
321
{
322
    ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
323
    return ioctl(sock, SIOCGIFADDR, ifr);
324
}
325
#endif
326
 
327
/* Fetch the interface configuration from the kernel. */
328
int if_fetch(struct interface *ife)
329
{
330
    struct ifreq ifr;
331
    int fd;
332
    char *ifname = ife->name;
333
 
334
    strcpy(ifr.ifr_name, ifname);
335
    if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
336
        return (-1);
337
    ife->flags = ifr.ifr_flags;
338
 
339
    strcpy(ifr.ifr_name, ifname);
340
    if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
341
        memset(ife->hwaddr, 0, 32);
342
    else
343
        memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
344
 
345
    ife->type = ifr.ifr_hwaddr.sa_family;
346
 
347
    strcpy(ifr.ifr_name, ifname);
348
    if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
349
        ife->metric = 0;
350
    else
351
        ife->metric = ifr.ifr_metric;
352
 
353
    strcpy(ifr.ifr_name, ifname);
354
    if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
355
        ife->mtu = 0;
356
    else
357
        ife->mtu = ifr.ifr_mtu;
358
 
359
    if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
360
        ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
361
        ife->type == ARPHRD_ADAPT) {
362
#ifdef SIOCGOUTFILL
363
        strcpy(ifr.ifr_name, ifname);
364
        if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
365
            ife->outfill = 0;
366
        else
367
            ife->outfill = (unsigned int) ifr.ifr_data;
368
#endif
369
#ifdef SIOCGKEEPALIVE
370
        strcpy(ifr.ifr_name, ifname);
371
        if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
372
            ife->keepalive = 0;
373
        else
374
            ife->keepalive = (unsigned int) ifr.ifr_data;
375
#endif
376
    }
377
    strcpy(ifr.ifr_name, ifname);
378
    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
379
        memset(&ife->map, 0, sizeof(struct ifmap));
380
    else
381
        memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
382
 
383
    strcpy(ifr.ifr_name, ifname);
384
    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
385
        memset(&ife->map, 0, sizeof(struct ifmap));
386
    else
387
        ife->map = ifr.ifr_map;
388
 
389
#ifdef HAVE_TXQUEUELEN
390
    strcpy(ifr.ifr_name, ifname);
391
    if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
392
        ife->tx_queue_len = -1; /* unknown value */
393
    else
394
        ife->tx_queue_len = ifr.ifr_qlen;
395
#else
396
    ife->tx_queue_len = -1;     /* unknown value */
397
#endif
398
 
399
#if HAVE_AFINET
400
    /* IPv4 address? */
401
    fd = get_socket_for_af(AF_INET);
402
    if (fd >= 0) {
403
        strcpy(ifr.ifr_name, ifname);
404
        ifr.ifr_addr.sa_family = AF_INET;
405
        if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
406
            ife->has_ip = 1;
407
            ife->addr = ifr.ifr_addr;
408
            strcpy(ifr.ifr_name, ifname);
409
            if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
410
                memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
411
            else
412
                ife->dstaddr = ifr.ifr_dstaddr;
413
 
414
            strcpy(ifr.ifr_name, ifname);
415
            if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
416
                memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
417
            else
418
                ife->broadaddr = ifr.ifr_broadaddr;
419
 
420
            strcpy(ifr.ifr_name, ifname);
421
            if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
422
                memset(&ife->netmask, 0, sizeof(struct sockaddr));
423
            else
424
                ife->netmask = ifr.ifr_netmask;
425
        } else
426
            memset(&ife->addr, 0, sizeof(struct sockaddr));
427
    }
428
#endif
429
 
430
#if HAVE_AFATALK
431
    /* DDP address maybe ? */
432
    fd = get_socket_for_af(AF_APPLETALK);
433
    if (fd >= 0) {
434
        strcpy(ifr.ifr_name, ifname);
435
        if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
436
            ife->ddpaddr = ifr.ifr_addr;
437
            ife->has_ddp = 1;
438
        }
439
    }
440
#endif
441
 
442
#if HAVE_AFIPX
443
    /* Look for IPX addresses with all framing types */
444
    fd = get_socket_for_af(AF_IPX);
445
    if (fd >= 0) {
446
        strcpy(ifr.ifr_name, ifname);
447
        if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
448
            ife->has_ipx_bb = 1;
449
            ife->ipxaddr_bb = ifr.ifr_addr;
450
        }
451
        strcpy(ifr.ifr_name, ifname);
452
        if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
453
            ife->has_ipx_sn = 1;
454
            ife->ipxaddr_sn = ifr.ifr_addr;
455
        }
456
        strcpy(ifr.ifr_name, ifname);
457
        if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
458
            ife->has_ipx_e3 = 1;
459
            ife->ipxaddr_e3 = ifr.ifr_addr;
460
        }
461
        strcpy(ifr.ifr_name, ifname);
462
        if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
463
            ife->has_ipx_e2 = 1;
464
            ife->ipxaddr_e2 = ifr.ifr_addr;
465
        }
466
    }
467
#endif
468
 
469
#if HAVE_AFECONET
470
    /* Econet address maybe? */
471
    fd = get_socket_for_af(AF_ECONET);
472
    if (fd >= 0) {
473
        strcpy(ifr.ifr_name, ifname);
474
        if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
475
            ife->ecaddr = ifr.ifr_addr;
476
            ife->has_econet = 1;
477
        }
478
    }
479
#endif
480
 
481
    return 0;
482
}
483
 
484
int do_if_fetch(struct interface *ife)
485
{
486
    if (if_fetch(ife) < 0) {
487
        char *errmsg;
488
        if (errno == ENODEV) {
489
            /* Give better error message for this case. */
490
            errmsg = _("Device not found");
491
        } else {
492
            errmsg = strerror(errno);
493
        }
494
        fprintf(stderr, _("%s: error fetching interface information: %s\n"),
495
                ife->name, errmsg);
496
        return -1;
497
    }
498
    return 0;
499
}
500
 
501
int do_if_print(struct interface *ife, void *cookie)
502
{
503
    int *opt_a = (int *) cookie;
504
    int res;
505
 
506
    res = do_if_fetch(ife);
507
    if (res >= 0) {
508
        if ((ife->flags & IFF_UP) || *opt_a)
509
            ife_print(ife);
510
    }
511
    return res;
512
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.