upload tizen1.0 source
[external/busybox.git] / util-linux / networking / libiproute / ll_map.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ll_map.c
4  *
5  *              This program is free software; you can redistribute it and/or
6  *              modify it under the terms of the GNU General Public License
7  *              as published by the Free Software Foundation; either version
8  *              2 of the License, or (at your option) any later version.
9  *
10  * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
11  *
12  */
13
14 #include <net/if.h>     /* struct ifreq and co. */
15
16 #include "libbb.h"
17 #include "libnetlink.h"
18 #include "ll_map.h"
19
20 struct idxmap {
21         struct idxmap *next;
22         int            index;
23         int            type;
24         int            alen;
25         unsigned       flags;
26         unsigned char  addr[8];
27         char           name[16];
28 };
29
30 static struct idxmap **idxmap; /* treat as *idxmap[16] */
31
32 static struct idxmap *find_by_index(int idx)
33 {
34         struct idxmap *im;
35
36         if (idxmap)
37                 for (im = idxmap[idx & 0xF]; im; im = im->next)
38                         if (im->index == idx)
39                                 return im;
40         return NULL;
41 }
42
43 int FAST_FUNC ll_remember_index(const struct sockaddr_nl *who UNUSED_PARAM,
44                 struct nlmsghdr *n,
45                 void *arg UNUSED_PARAM)
46 {
47         int h;
48         struct ifinfomsg *ifi = NLMSG_DATA(n);
49         struct idxmap *im, **imp;
50         struct rtattr *tb[IFLA_MAX+1];
51
52         if (n->nlmsg_type != RTM_NEWLINK)
53                 return 0;
54
55         if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
56                 return -1;
57
58         memset(tb, 0, sizeof(tb));
59         parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
60         if (tb[IFLA_IFNAME] == NULL)
61                 return 0;
62
63         if (!idxmap)
64                 idxmap = xzalloc(sizeof(idxmap[0]) * 16);
65
66         h = ifi->ifi_index & 0xF;
67         for (imp = &idxmap[h]; (im = *imp) != NULL; imp = &im->next)
68                 if (im->index == ifi->ifi_index)
69                         goto found;
70
71         im = xmalloc(sizeof(*im));
72         im->next = *imp;
73         im->index = ifi->ifi_index;
74         *imp = im;
75  found:
76         im->type = ifi->ifi_type;
77         im->flags = ifi->ifi_flags;
78         if (tb[IFLA_ADDRESS]) {
79                 int alen;
80                 im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
81                 if (alen > (int)sizeof(im->addr))
82                         alen = sizeof(im->addr);
83                 memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
84         } else {
85                 im->alen = 0;
86                 memset(im->addr, 0, sizeof(im->addr));
87         }
88         strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]));
89         return 0;
90 }
91
92 const char FAST_FUNC *ll_idx_n2a(int idx, char *buf)
93 {
94         struct idxmap *im;
95
96         if (idx == 0)
97                 return "*";
98         im = find_by_index(idx);
99         if (im)
100                 return im->name;
101         snprintf(buf, 16, "if%d", idx);
102         return buf;
103 }
104
105
106 const char FAST_FUNC *ll_index_to_name(int idx)
107 {
108         static char nbuf[16];
109
110         return ll_idx_n2a(idx, nbuf);
111 }
112
113 #ifdef UNUSED
114 int ll_index_to_type(int idx)
115 {
116         struct idxmap *im;
117
118         if (idx == 0)
119                 return -1;
120         im = find_by_index(idx);
121         if (im)
122                 return im->type;
123         return -1;
124 }
125 #endif
126
127 unsigned FAST_FUNC ll_index_to_flags(int idx)
128 {
129         struct idxmap *im;
130
131         if (idx == 0)
132                 return 0;
133         im = find_by_index(idx);
134         if (im)
135                 return im->flags;
136         return 0;
137 }
138
139 int FAST_FUNC xll_name_to_index(const char *name)
140 {
141         int ret = 0;
142         int sock_fd;
143
144 /* caching is not warranted - no users which repeatedly call it */
145 #ifdef UNUSED
146         static char ncache[16];
147         static int icache;
148
149         struct idxmap *im;
150         int i;
151
152         if (name == NULL)
153                 goto out;
154         if (icache && strcmp(name, ncache) == 0) {
155                 ret = icache;
156                 goto out;
157         }
158         if (idxmap) {
159                 for (i = 0; i < 16; i++) {
160                         for (im = idxmap[i]; im; im = im->next) {
161                                 if (strcmp(im->name, name) == 0) {
162                                         icache = im->index;
163                                         strcpy(ncache, name);
164                                         ret = im->index;
165                                         goto out;
166                                 }
167                         }
168                 }
169         }
170         /* We have not found the interface in our cache, but the kernel
171          * may still know about it. One reason is that we may be using
172          * module on-demand loading, which means that the kernel will
173          * load the module and make the interface exist only when
174          * we explicitely request it (check for dev_load() in net/core/dev.c).
175          * I can think of other similar scenario, but they are less common...
176          * Jean II */
177 #endif
178
179         sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
180         if (sock_fd >= 0) {
181                 struct ifreq ifr;
182                 int tmp;
183
184                 strncpy_IFNAMSIZ(ifr.ifr_name, name);
185                 ifr.ifr_ifindex = -1;
186                 tmp = ioctl(sock_fd, SIOCGIFINDEX, &ifr);
187                 close(sock_fd);
188                 if (tmp >= 0)
189                         /* In theory, we should redump the interface list
190                          * to update our cache, this is left as an exercise
191                          * to the reader... Jean II */
192                         ret = ifr.ifr_ifindex;
193         }
194 /* out:*/
195         if (ret <= 0)
196                 bb_error_msg_and_die("can't find device '%s'", name);
197         return ret;
198 }
199
200 int FAST_FUNC ll_init_map(struct rtnl_handle *rth)
201 {
202         xrtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK);
203         xrtnl_dump_filter(rth, ll_remember_index, NULL);
204         return 0;
205 }