xref: /aosp_15_r20/external/iproute2/lib/ll_map.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * ll_map.c
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  *		This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker  *		modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker  *		as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker  *		2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker  *
9*de1e4e89SAndroid Build Coastguard Worker  * Authors:	Alexey Kuznetsov, <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker  *
11*de1e4e89SAndroid Build Coastguard Worker  */
12*de1e4e89SAndroid Build Coastguard Worker 
13*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <net/if.h>
22*de1e4e89SAndroid Build Coastguard Worker 
23*de1e4e89SAndroid Build Coastguard Worker #include "libnetlink.h"
24*de1e4e89SAndroid Build Coastguard Worker #include "ll_map.h"
25*de1e4e89SAndroid Build Coastguard Worker #include "list.h"
26*de1e4e89SAndroid Build Coastguard Worker 
27*de1e4e89SAndroid Build Coastguard Worker struct ll_cache {
28*de1e4e89SAndroid Build Coastguard Worker 	struct hlist_node idx_hash;
29*de1e4e89SAndroid Build Coastguard Worker 	struct hlist_node name_hash;
30*de1e4e89SAndroid Build Coastguard Worker 	unsigned	flags;
31*de1e4e89SAndroid Build Coastguard Worker 	unsigned 	index;
32*de1e4e89SAndroid Build Coastguard Worker 	unsigned short	type;
33*de1e4e89SAndroid Build Coastguard Worker 	char		name[];
34*de1e4e89SAndroid Build Coastguard Worker };
35*de1e4e89SAndroid Build Coastguard Worker 
36*de1e4e89SAndroid Build Coastguard Worker #define IDXMAP_SIZE	1024
37*de1e4e89SAndroid Build Coastguard Worker static struct hlist_head idx_head[IDXMAP_SIZE];
38*de1e4e89SAndroid Build Coastguard Worker static struct hlist_head name_head[IDXMAP_SIZE];
39*de1e4e89SAndroid Build Coastguard Worker 
ll_get_by_index(unsigned index)40*de1e4e89SAndroid Build Coastguard Worker static struct ll_cache *ll_get_by_index(unsigned index)
41*de1e4e89SAndroid Build Coastguard Worker {
42*de1e4e89SAndroid Build Coastguard Worker 	struct hlist_node *n;
43*de1e4e89SAndroid Build Coastguard Worker 	unsigned h = index & (IDXMAP_SIZE - 1);
44*de1e4e89SAndroid Build Coastguard Worker 
45*de1e4e89SAndroid Build Coastguard Worker 	hlist_for_each(n, &idx_head[h]) {
46*de1e4e89SAndroid Build Coastguard Worker 		struct ll_cache *im
47*de1e4e89SAndroid Build Coastguard Worker 			= container_of(n, struct ll_cache, idx_hash);
48*de1e4e89SAndroid Build Coastguard Worker 		if (im->index == index)
49*de1e4e89SAndroid Build Coastguard Worker 			return im;
50*de1e4e89SAndroid Build Coastguard Worker 	}
51*de1e4e89SAndroid Build Coastguard Worker 
52*de1e4e89SAndroid Build Coastguard Worker 	return NULL;
53*de1e4e89SAndroid Build Coastguard Worker }
54*de1e4e89SAndroid Build Coastguard Worker 
namehash(const char * str)55*de1e4e89SAndroid Build Coastguard Worker unsigned namehash(const char *str)
56*de1e4e89SAndroid Build Coastguard Worker {
57*de1e4e89SAndroid Build Coastguard Worker 	unsigned hash = 5381;
58*de1e4e89SAndroid Build Coastguard Worker 
59*de1e4e89SAndroid Build Coastguard Worker 	while (*str)
60*de1e4e89SAndroid Build Coastguard Worker 		hash = ((hash << 5) + hash) + *str++; /* hash * 33 + c */
61*de1e4e89SAndroid Build Coastguard Worker 
62*de1e4e89SAndroid Build Coastguard Worker 	return hash;
63*de1e4e89SAndroid Build Coastguard Worker }
64*de1e4e89SAndroid Build Coastguard Worker 
ll_get_by_name(const char * name)65*de1e4e89SAndroid Build Coastguard Worker static struct ll_cache *ll_get_by_name(const char *name)
66*de1e4e89SAndroid Build Coastguard Worker {
67*de1e4e89SAndroid Build Coastguard Worker 	struct hlist_node *n;
68*de1e4e89SAndroid Build Coastguard Worker 	unsigned h = namehash(name) & (IDXMAP_SIZE - 1);
69*de1e4e89SAndroid Build Coastguard Worker 
70*de1e4e89SAndroid Build Coastguard Worker 	hlist_for_each(n, &name_head[h]) {
71*de1e4e89SAndroid Build Coastguard Worker 		struct ll_cache *im
72*de1e4e89SAndroid Build Coastguard Worker 			= container_of(n, struct ll_cache, name_hash);
73*de1e4e89SAndroid Build Coastguard Worker 
74*de1e4e89SAndroid Build Coastguard Worker 		if (strncmp(im->name, name, IFNAMSIZ) == 0)
75*de1e4e89SAndroid Build Coastguard Worker 			return im;
76*de1e4e89SAndroid Build Coastguard Worker 	}
77*de1e4e89SAndroid Build Coastguard Worker 
78*de1e4e89SAndroid Build Coastguard Worker 	return NULL;
79*de1e4e89SAndroid Build Coastguard Worker }
80*de1e4e89SAndroid Build Coastguard Worker 
ll_remember_index(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)81*de1e4e89SAndroid Build Coastguard Worker int ll_remember_index(const struct sockaddr_nl *who,
82*de1e4e89SAndroid Build Coastguard Worker 		      struct nlmsghdr *n, void *arg)
83*de1e4e89SAndroid Build Coastguard Worker {
84*de1e4e89SAndroid Build Coastguard Worker 	unsigned int h;
85*de1e4e89SAndroid Build Coastguard Worker 	const char *ifname;
86*de1e4e89SAndroid Build Coastguard Worker 	struct ifinfomsg *ifi = NLMSG_DATA(n);
87*de1e4e89SAndroid Build Coastguard Worker 	struct ll_cache *im;
88*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[IFLA_MAX+1];
89*de1e4e89SAndroid Build Coastguard Worker 
90*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
91*de1e4e89SAndroid Build Coastguard Worker 		return 0;
92*de1e4e89SAndroid Build Coastguard Worker 
93*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*ifi)))
94*de1e4e89SAndroid Build Coastguard Worker 		return -1;
95*de1e4e89SAndroid Build Coastguard Worker 
96*de1e4e89SAndroid Build Coastguard Worker 	im = ll_get_by_index(ifi->ifi_index);
97*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_type == RTM_DELLINK) {
98*de1e4e89SAndroid Build Coastguard Worker 		if (im) {
99*de1e4e89SAndroid Build Coastguard Worker 			hlist_del(&im->name_hash);
100*de1e4e89SAndroid Build Coastguard Worker 			hlist_del(&im->idx_hash);
101*de1e4e89SAndroid Build Coastguard Worker 			free(im);
102*de1e4e89SAndroid Build Coastguard Worker 		}
103*de1e4e89SAndroid Build Coastguard Worker 		return 0;
104*de1e4e89SAndroid Build Coastguard Worker 	}
105*de1e4e89SAndroid Build Coastguard Worker 
106*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
107*de1e4e89SAndroid Build Coastguard Worker 	ifname = rta_getattr_str(tb[IFLA_IFNAME]);
108*de1e4e89SAndroid Build Coastguard Worker 	if (ifname == NULL)
109*de1e4e89SAndroid Build Coastguard Worker 		return 0;
110*de1e4e89SAndroid Build Coastguard Worker 
111*de1e4e89SAndroid Build Coastguard Worker 	if (im) {
112*de1e4e89SAndroid Build Coastguard Worker 		/* change to existing entry */
113*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(im->name, ifname) != 0) {
114*de1e4e89SAndroid Build Coastguard Worker 			hlist_del(&im->name_hash);
115*de1e4e89SAndroid Build Coastguard Worker 			h = namehash(ifname) & (IDXMAP_SIZE - 1);
116*de1e4e89SAndroid Build Coastguard Worker 			hlist_add_head(&im->name_hash, &name_head[h]);
117*de1e4e89SAndroid Build Coastguard Worker 		}
118*de1e4e89SAndroid Build Coastguard Worker 
119*de1e4e89SAndroid Build Coastguard Worker 		im->flags = ifi->ifi_flags;
120*de1e4e89SAndroid Build Coastguard Worker 		return 0;
121*de1e4e89SAndroid Build Coastguard Worker 	}
122*de1e4e89SAndroid Build Coastguard Worker 
123*de1e4e89SAndroid Build Coastguard Worker 	im = malloc(sizeof(*im) + strlen(ifname) + 1);
124*de1e4e89SAndroid Build Coastguard Worker 	if (im == NULL)
125*de1e4e89SAndroid Build Coastguard Worker 		return 0;
126*de1e4e89SAndroid Build Coastguard Worker 	im->index = ifi->ifi_index;
127*de1e4e89SAndroid Build Coastguard Worker 	strcpy(im->name, ifname);
128*de1e4e89SAndroid Build Coastguard Worker 	im->type = ifi->ifi_type;
129*de1e4e89SAndroid Build Coastguard Worker 	im->flags = ifi->ifi_flags;
130*de1e4e89SAndroid Build Coastguard Worker 
131*de1e4e89SAndroid Build Coastguard Worker 	h = ifi->ifi_index & (IDXMAP_SIZE - 1);
132*de1e4e89SAndroid Build Coastguard Worker 	hlist_add_head(&im->idx_hash, &idx_head[h]);
133*de1e4e89SAndroid Build Coastguard Worker 
134*de1e4e89SAndroid Build Coastguard Worker 	h = namehash(ifname) & (IDXMAP_SIZE - 1);
135*de1e4e89SAndroid Build Coastguard Worker 	hlist_add_head(&im->name_hash, &name_head[h]);
136*de1e4e89SAndroid Build Coastguard Worker 
137*de1e4e89SAndroid Build Coastguard Worker 	return 0;
138*de1e4e89SAndroid Build Coastguard Worker }
139*de1e4e89SAndroid Build Coastguard Worker 
ll_idx_n2a(unsigned idx,char * buf)140*de1e4e89SAndroid Build Coastguard Worker const char *ll_idx_n2a(unsigned idx, char *buf)
141*de1e4e89SAndroid Build Coastguard Worker {
142*de1e4e89SAndroid Build Coastguard Worker 	const struct ll_cache *im;
143*de1e4e89SAndroid Build Coastguard Worker 
144*de1e4e89SAndroid Build Coastguard Worker 	if (idx == 0)
145*de1e4e89SAndroid Build Coastguard Worker 		return "*";
146*de1e4e89SAndroid Build Coastguard Worker 
147*de1e4e89SAndroid Build Coastguard Worker 	im = ll_get_by_index(idx);
148*de1e4e89SAndroid Build Coastguard Worker 	if (im)
149*de1e4e89SAndroid Build Coastguard Worker 		return im->name;
150*de1e4e89SAndroid Build Coastguard Worker 
151*de1e4e89SAndroid Build Coastguard Worker 	if (if_indextoname(idx, buf) == NULL)
152*de1e4e89SAndroid Build Coastguard Worker 		snprintf(buf, IFNAMSIZ, "if%d", idx);
153*de1e4e89SAndroid Build Coastguard Worker 
154*de1e4e89SAndroid Build Coastguard Worker 	return buf;
155*de1e4e89SAndroid Build Coastguard Worker }
156*de1e4e89SAndroid Build Coastguard Worker 
ll_index_to_name(unsigned idx)157*de1e4e89SAndroid Build Coastguard Worker const char *ll_index_to_name(unsigned idx)
158*de1e4e89SAndroid Build Coastguard Worker {
159*de1e4e89SAndroid Build Coastguard Worker 	static char nbuf[IFNAMSIZ];
160*de1e4e89SAndroid Build Coastguard Worker 
161*de1e4e89SAndroid Build Coastguard Worker 	return ll_idx_n2a(idx, nbuf);
162*de1e4e89SAndroid Build Coastguard Worker }
163*de1e4e89SAndroid Build Coastguard Worker 
ll_index_to_type(unsigned idx)164*de1e4e89SAndroid Build Coastguard Worker int ll_index_to_type(unsigned idx)
165*de1e4e89SAndroid Build Coastguard Worker {
166*de1e4e89SAndroid Build Coastguard Worker 	const struct ll_cache *im;
167*de1e4e89SAndroid Build Coastguard Worker 
168*de1e4e89SAndroid Build Coastguard Worker 	if (idx == 0)
169*de1e4e89SAndroid Build Coastguard Worker 		return -1;
170*de1e4e89SAndroid Build Coastguard Worker 
171*de1e4e89SAndroid Build Coastguard Worker 	im = ll_get_by_index(idx);
172*de1e4e89SAndroid Build Coastguard Worker 	return im ? im->type : -1;
173*de1e4e89SAndroid Build Coastguard Worker }
174*de1e4e89SAndroid Build Coastguard Worker 
ll_index_to_flags(unsigned idx)175*de1e4e89SAndroid Build Coastguard Worker int ll_index_to_flags(unsigned idx)
176*de1e4e89SAndroid Build Coastguard Worker {
177*de1e4e89SAndroid Build Coastguard Worker 	const struct ll_cache *im;
178*de1e4e89SAndroid Build Coastguard Worker 
179*de1e4e89SAndroid Build Coastguard Worker 	if (idx == 0)
180*de1e4e89SAndroid Build Coastguard Worker 		return 0;
181*de1e4e89SAndroid Build Coastguard Worker 
182*de1e4e89SAndroid Build Coastguard Worker 	im = ll_get_by_index(idx);
183*de1e4e89SAndroid Build Coastguard Worker 	return im ? im->flags : -1;
184*de1e4e89SAndroid Build Coastguard Worker }
185*de1e4e89SAndroid Build Coastguard Worker 
ll_name_to_index(const char * name)186*de1e4e89SAndroid Build Coastguard Worker unsigned ll_name_to_index(const char *name)
187*de1e4e89SAndroid Build Coastguard Worker {
188*de1e4e89SAndroid Build Coastguard Worker 	const struct ll_cache *im;
189*de1e4e89SAndroid Build Coastguard Worker 	unsigned idx;
190*de1e4e89SAndroid Build Coastguard Worker 
191*de1e4e89SAndroid Build Coastguard Worker 	if (name == NULL)
192*de1e4e89SAndroid Build Coastguard Worker 		return 0;
193*de1e4e89SAndroid Build Coastguard Worker 
194*de1e4e89SAndroid Build Coastguard Worker 	im = ll_get_by_name(name);
195*de1e4e89SAndroid Build Coastguard Worker 	if (im)
196*de1e4e89SAndroid Build Coastguard Worker 		return im->index;
197*de1e4e89SAndroid Build Coastguard Worker 
198*de1e4e89SAndroid Build Coastguard Worker 	idx = if_nametoindex(name);
199*de1e4e89SAndroid Build Coastguard Worker 	if (idx == 0)
200*de1e4e89SAndroid Build Coastguard Worker 		sscanf(name, "if%u", &idx);
201*de1e4e89SAndroid Build Coastguard Worker 	return idx;
202*de1e4e89SAndroid Build Coastguard Worker }
203*de1e4e89SAndroid Build Coastguard Worker 
ll_init_map(struct rtnl_handle * rth)204*de1e4e89SAndroid Build Coastguard Worker void ll_init_map(struct rtnl_handle *rth)
205*de1e4e89SAndroid Build Coastguard Worker {
206*de1e4e89SAndroid Build Coastguard Worker 	static int initialized;
207*de1e4e89SAndroid Build Coastguard Worker 
208*de1e4e89SAndroid Build Coastguard Worker 	if (initialized)
209*de1e4e89SAndroid Build Coastguard Worker 		return;
210*de1e4e89SAndroid Build Coastguard Worker 
211*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
212*de1e4e89SAndroid Build Coastguard Worker 		perror("Cannot send dump request");
213*de1e4e89SAndroid Build Coastguard Worker 		exit(1);
214*de1e4e89SAndroid Build Coastguard Worker 	}
215*de1e4e89SAndroid Build Coastguard Worker 
216*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_dump_filter(rth, ll_remember_index, NULL) < 0) {
217*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Dump terminated\n");
218*de1e4e89SAndroid Build Coastguard Worker 		exit(1);
219*de1e4e89SAndroid Build Coastguard Worker 	}
220*de1e4e89SAndroid Build Coastguard Worker 
221*de1e4e89SAndroid Build Coastguard Worker 	initialized = 1;
222*de1e4e89SAndroid Build Coastguard Worker }
223