1 /* vi: set sw=4 ts=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.
10 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
14 #include <net/if.h> /* struct ifreq and co. */
17 #include "libnetlink.h"
26 unsigned char addr
[8];
30 static struct idxmap
*idxmap
[16];
32 static struct idxmap
*find_by_index(int idx
)
36 for (im
= idxmap
[idx
& 0xF]; im
; im
= im
->next
)
42 int ll_remember_index(const struct sockaddr_nl
*who UNUSED_PARAM
,
44 void *arg UNUSED_PARAM
)
47 struct ifinfomsg
*ifi
= NLMSG_DATA(n
);
48 struct idxmap
*im
, **imp
;
49 struct rtattr
*tb
[IFLA_MAX
+1];
51 if (n
->nlmsg_type
!= RTM_NEWLINK
)
54 if (n
->nlmsg_len
< NLMSG_LENGTH(sizeof(ifi
)))
57 memset(tb
, 0, sizeof(tb
));
58 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(ifi
), IFLA_PAYLOAD(n
));
59 if (tb
[IFLA_IFNAME
] == NULL
)
62 h
= ifi
->ifi_index
& 0xF;
64 for (imp
= &idxmap
[h
]; (im
= *imp
) != NULL
; imp
= &im
->next
)
65 if (im
->index
== ifi
->ifi_index
)
68 im
= xmalloc(sizeof(*im
));
70 im
->index
= ifi
->ifi_index
;
73 im
->type
= ifi
->ifi_type
;
74 im
->flags
= ifi
->ifi_flags
;
75 if (tb
[IFLA_ADDRESS
]) {
77 im
->alen
= alen
= RTA_PAYLOAD(tb
[IFLA_ADDRESS
]);
78 if (alen
> (int)sizeof(im
->addr
))
79 alen
= sizeof(im
->addr
);
80 memcpy(im
->addr
, RTA_DATA(tb
[IFLA_ADDRESS
]), alen
);
83 memset(im
->addr
, 0, sizeof(im
->addr
));
85 strcpy(im
->name
, RTA_DATA(tb
[IFLA_IFNAME
]));
89 const char *ll_idx_n2a(int idx
, char *buf
)
95 im
= find_by_index(idx
);
98 snprintf(buf
, 16, "if%d", idx
);
103 const char *ll_index_to_name(int idx
)
105 static char nbuf
[16];
107 return ll_idx_n2a(idx
, nbuf
);
111 int ll_index_to_type(int idx
)
117 im
= find_by_index(idx
);
124 unsigned ll_index_to_flags(int idx
)
130 im
= find_by_index(idx
);
136 int xll_name_to_index(const char *const name
)
141 /* caching is not warranted - no users which repeatedly call it */
143 static char ncache
[16];
151 if (icache
&& strcmp(name
, ncache
) == 0) {
155 for (i
= 0; i
< 16; i
++) {
156 for (im
= idxmap
[i
]; im
; im
= im
->next
) {
157 if (strcmp(im
->name
, name
) == 0) {
159 strcpy(ncache
, name
);
165 /* We have not found the interface in our cache, but the kernel
166 * may still know about it. One reason is that we may be using
167 * module on-demand loading, which means that the kernel will
168 * load the module and make the interface exist only when
169 * we explicitely request it (check for dev_load() in net/core/dev.c).
170 * I can think of other similar scenario, but they are less common...
174 sock_fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
179 strncpy_IFNAMSIZ(ifr
.ifr_name
, name
);
180 ifr
.ifr_ifindex
= -1;
181 tmp
= ioctl(sock_fd
, SIOCGIFINDEX
, &ifr
);
184 /* In theory, we should redump the interface list
185 * to update our cache, this is left as an exercise
186 * to the reader... Jean II */
187 ret
= ifr
.ifr_ifindex
;
191 bb_error_msg_and_die("cannot find device \"%s\"", name
);
195 int ll_init_map(struct rtnl_handle
*rth
)
197 xrtnl_wilddump_request(rth
, AF_UNSPEC
, RTM_GETLINK
);
198 xrtnl_dump_filter(rth
, ll_remember_index
, &idxmap
);