busybox/networking/libiproute/ll_map.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * This program is free software; you can redistribute it and/or
   4 * modify it under the terms of the GNU General Public License
   5 * as published by the Free Software Foundation; either version
   6 * 2 of the License, or (at your option) any later version.
   7 *
   8 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
   9 */
  10#include <net/if.h>  /* struct ifreq and co. */
  11
  12#include "libbb.h"
  13#include "libnetlink.h"
  14#include "ll_map.h"
  15
  16struct idxmap {
  17        struct idxmap *next;
  18        int            index;
  19        int            type;
  20        int            alen;
  21        unsigned       flags;
  22        unsigned char  addr[8];
  23        char           name[16];
  24};
  25
  26static struct idxmap **idxmap; /* treat as *idxmap[16] */
  27
  28static struct idxmap *find_by_index(int idx)
  29{
  30        struct idxmap *im;
  31
  32        if (idxmap)
  33                for (im = idxmap[idx & 0xF]; im; im = im->next)
  34                        if (im->index == idx)
  35                                return im;
  36        return NULL;
  37}
  38
  39int FAST_FUNC ll_remember_index(const struct sockaddr_nl *who UNUSED_PARAM,
  40                struct nlmsghdr *n,
  41                void *arg UNUSED_PARAM)
  42{
  43        int h;
  44        struct ifinfomsg *ifi = NLMSG_DATA(n);
  45        struct idxmap *im, **imp;
  46        struct rtattr *tb[IFLA_MAX+1];
  47
  48        if (n->nlmsg_type != RTM_NEWLINK)
  49                return 0;
  50
  51        if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
  52                return -1;
  53
  54        //memset(tb, 0, sizeof(tb)); - parse_rtattr does this
  55        parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
  56        if (tb[IFLA_IFNAME] == NULL)
  57                return 0;
  58
  59        if (!idxmap)
  60                idxmap = xzalloc(sizeof(idxmap[0]) * 16);
  61
  62        h = ifi->ifi_index & 0xF;
  63        for (imp = &idxmap[h]; (im = *imp) != NULL; imp = &im->next)
  64                if (im->index == ifi->ifi_index)
  65                        goto found;
  66
  67        im = xmalloc(sizeof(*im));
  68        im->next = *imp;
  69        im->index = ifi->ifi_index;
  70        *imp = im;
  71 found:
  72        im->type = ifi->ifi_type;
  73        im->flags = ifi->ifi_flags;
  74        if (tb[IFLA_ADDRESS]) {
  75                int alen;
  76                im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
  77                if (alen > (int)sizeof(im->addr))
  78                        alen = sizeof(im->addr);
  79                memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
  80        } else {
  81                im->alen = 0;
  82                memset(im->addr, 0, sizeof(im->addr));
  83        }
  84        strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]));
  85        return 0;
  86}
  87
  88static
  89const char FAST_FUNC *ll_idx_n2a(int idx/*, char *buf*/)
  90{
  91        struct idxmap *im;
  92
  93        if (idx == 0)
  94                return "*";
  95        im = find_by_index(idx);
  96        if (im)
  97                return im->name;
  98        //snprintf(buf, 16, "if%d", idx);
  99        //return buf;
 100        return auto_string(xasprintf("if%d", idx));
 101}
 102
 103const char FAST_FUNC *ll_index_to_name(int idx)
 104{
 105        //static char nbuf[16];
 106        return ll_idx_n2a(idx/*, nbuf*/);
 107}
 108
 109#ifdef UNUSED
 110int ll_index_to_type(int idx)
 111{
 112        struct idxmap *im;
 113
 114        if (idx == 0)
 115                return -1;
 116        im = find_by_index(idx);
 117        if (im)
 118                return im->type;
 119        return -1;
 120}
 121#endif
 122
 123unsigned FAST_FUNC ll_index_to_flags(int idx)
 124{
 125        struct idxmap *im;
 126
 127        if (idx == 0)
 128                return 0;
 129        im = find_by_index(idx);
 130        if (im)
 131                return im->flags;
 132        return 0;
 133}
 134
 135int FAST_FUNC xll_name_to_index(const char *name)
 136{
 137        int ret = 0;
 138
 139/* caching is not warranted - no users which repeatedly call it */
 140#ifdef UNUSED
 141        static char ncache[16];
 142        static int icache;
 143
 144        struct idxmap *im;
 145        int i;
 146
 147        if (name == NULL)
 148                goto out;
 149        if (icache && strcmp(name, ncache) == 0) {
 150                ret = icache;
 151                goto out;
 152        }
 153        if (idxmap) {
 154                for (i = 0; i < 16; i++) {
 155                        for (im = idxmap[i]; im; im = im->next) {
 156                                if (strcmp(im->name, name) == 0) {
 157                                        icache = im->index;
 158                                        strcpy(ncache, name);
 159                                        ret = im->index;
 160                                        goto out;
 161                                }
 162                        }
 163                }
 164        }
 165#endif
 166        ret = if_nametoindex(name);
 167/* out:*/
 168        if (ret <= 0)
 169                bb_error_msg_and_die("can't find device '%s'", name);
 170        return ret;
 171}
 172
 173int FAST_FUNC ll_init_map(struct rtnl_handle *rth)
 174{
 175        xrtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK);
 176        xrtnl_dump_filter(rth, ll_remember_index, NULL);
 177        return 0;
 178}
 179