• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ll_map.c
3  *
4  *		This program is free software; you can redistribute it and/or
5  *		modify it under the terms of the GNU General Public License
6  *		as published by the Free Software Foundation; either version
7  *		2 of the License, or (at your option) any later version.
8  *
9  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10  *
11  */
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <syslog.h>
17 #include <fcntl.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <string.h>
21 
22 #include "libnetlink.h"
23 #include "ll_map.h"
24 
25 extern unsigned int if_nametoindex (const char *);
26 
27 struct idxmap
28 {
29 	struct idxmap * next;
30 	unsigned	index;
31 	int		type;
32 	int		alen;
33 	unsigned	flags;
34 	unsigned char	addr[20];
35 	char		name[16];
36 };
37 
38 static struct idxmap *idxmap[16];
39 
ll_remember_index(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)40 int ll_remember_index(const struct sockaddr_nl *who,
41 		      struct nlmsghdr *n, void *arg)
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 
55 	memset(tb, 0, sizeof(tb));
56 	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
57 	if (tb[IFLA_IFNAME] == NULL)
58 		return 0;
59 
60 	h = ifi->ifi_index&0xF;
61 
62 	for (imp=&idxmap[h]; (im=*imp)!=NULL; imp = &im->next)
63 		if (im->index == ifi->ifi_index)
64 			break;
65 
66 	if (im == NULL) {
67 		im = malloc(sizeof(*im));
68 		if (im == NULL)
69 			return 0;
70 		im->next = *imp;
71 		im->index = ifi->ifi_index;
72 		*imp = im;
73 	}
74 
75 	im->type = ifi->ifi_type;
76 	im->flags = ifi->ifi_flags;
77 	if (tb[IFLA_ADDRESS]) {
78 		int alen;
79 		im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
80 		if (alen > sizeof(im->addr))
81 			alen = sizeof(im->addr);
82 		memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
83 	} else {
84 		im->alen = 0;
85 		memset(im->addr, 0, sizeof(im->addr));
86 	}
87 	strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]));
88 	return 0;
89 }
90 
ll_idx_n2a(unsigned idx,char * buf)91 const char *ll_idx_n2a(unsigned idx, char *buf)
92 {
93 	struct idxmap *im;
94 
95 	if (idx == 0)
96 		return "*";
97 	for (im = idxmap[idx&0xF]; im; im = im->next)
98 		if (im->index == idx)
99 			return im->name;
100 	snprintf(buf, 16, "if%d", idx);
101 	return buf;
102 }
103 
104 
ll_index_to_name(unsigned idx)105 const char *ll_index_to_name(unsigned idx)
106 {
107 	static char nbuf[16];
108 
109 	return ll_idx_n2a(idx, nbuf);
110 }
111 
ll_index_to_type(unsigned idx)112 int ll_index_to_type(unsigned idx)
113 {
114 	struct idxmap *im;
115 
116 	if (idx == 0)
117 		return -1;
118 	for (im = idxmap[idx&0xF]; im; im = im->next)
119 		if (im->index == idx)
120 			return im->type;
121 	return -1;
122 }
123 
ll_index_to_flags(unsigned idx)124 unsigned ll_index_to_flags(unsigned idx)
125 {
126 	struct idxmap *im;
127 
128 	if (idx == 0)
129 		return 0;
130 
131 	for (im = idxmap[idx&0xF]; im; im = im->next)
132 		if (im->index == idx)
133 			return im->flags;
134 	return 0;
135 }
136 
ll_index_to_addr(unsigned idx,unsigned char * addr,unsigned alen)137 unsigned ll_index_to_addr(unsigned idx, unsigned char *addr,
138 			  unsigned alen)
139 {
140 	struct idxmap *im;
141 
142 	if (idx == 0)
143 		return 0;
144 
145 	for (im = idxmap[idx&0xF]; im; im = im->next) {
146 		if (im->index == idx) {
147 			if (alen > sizeof(im->addr))
148 				alen = sizeof(im->addr);
149 			if (alen > im->alen)
150 				alen = im->alen;
151 			memcpy(addr, im->addr, alen);
152 			return alen;
153 		}
154 	}
155 	return 0;
156 }
157 
ll_name_to_index(const char * name)158 unsigned ll_name_to_index(const char *name)
159 {
160 	static char ncache[16];
161 	static int icache;
162 	struct idxmap *im;
163 	int i;
164 
165 	if (name == NULL)
166 		return 0;
167 	if (icache && strcmp(name, ncache) == 0)
168 		return icache;
169 	for (i=0; i<16; i++) {
170 		for (im = idxmap[i]; im; im = im->next) {
171 			if (strcmp(im->name, name) == 0) {
172 				icache = im->index;
173 				strcpy(ncache, name);
174 				return im->index;
175 			}
176 		}
177 	}
178 
179 	return if_nametoindex(name);
180 }
181 
ll_init_map(struct rtnl_handle * rth)182 int ll_init_map(struct rtnl_handle *rth)
183 {
184 	if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
185 		perror("Cannot send dump request");
186 		exit(1);
187 	}
188 
189 	if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) {
190 		fprintf(stderr, "Dump terminated\n");
191 		exit(1);
192 	}
193 	return 0;
194 }
195