xref: /aosp_15_r20/external/iproute2/ip/ipila.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * ipila.c	ILA (Identifier Locator Addressing) support
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:	Tom Herbert <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker  */
11*de1e4e89SAndroid Build Coastguard Worker 
12*de1e4e89SAndroid Build Coastguard Worker #include <netdb.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <net/if.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <linux/ila.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <linux/genetlink.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <linux/ip.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
21*de1e4e89SAndroid Build Coastguard Worker 
22*de1e4e89SAndroid Build Coastguard Worker #include "libgenl.h"
23*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
24*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
25*de1e4e89SAndroid Build Coastguard Worker 
usage(void)26*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
27*de1e4e89SAndroid Build Coastguard Worker {
28*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: ip ila add loc_match LOCATOR_MATCH "
29*de1e4e89SAndroid Build Coastguard Worker 		"loc LOCATOR [ dev DEV ]\n");
30*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "       ip ila del loc_match LOCATOR_MATCH "
31*de1e4e89SAndroid Build Coastguard Worker 		"[ loc LOCATOR ] [ dev DEV ]\n");
32*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "       ip ila list\n");
33*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
34*de1e4e89SAndroid Build Coastguard Worker 
35*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
36*de1e4e89SAndroid Build Coastguard Worker }
37*de1e4e89SAndroid Build Coastguard Worker 
38*de1e4e89SAndroid Build Coastguard Worker /* netlink socket */
39*de1e4e89SAndroid Build Coastguard Worker static struct rtnl_handle genl_rth = { .fd = -1 };
40*de1e4e89SAndroid Build Coastguard Worker static int genl_family = -1;
41*de1e4e89SAndroid Build Coastguard Worker 
42*de1e4e89SAndroid Build Coastguard Worker #define ILA_REQUEST(_req, _bufsiz, _cmd, _flags)	\
43*de1e4e89SAndroid Build Coastguard Worker 	GENL_REQUEST(_req, _bufsiz, genl_family, 0,	\
44*de1e4e89SAndroid Build Coastguard Worker 		     ILA_GENL_VERSION, _cmd, _flags)
45*de1e4e89SAndroid Build Coastguard Worker 
46*de1e4e89SAndroid Build Coastguard Worker #define ILA_RTA(g) ((struct rtattr *)(((char *)(g)) +	\
47*de1e4e89SAndroid Build Coastguard Worker 	NLMSG_ALIGN(sizeof(struct genlmsghdr))))
48*de1e4e89SAndroid Build Coastguard Worker 
49*de1e4e89SAndroid Build Coastguard Worker #define ADDR_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx")
50*de1e4e89SAndroid Build Coastguard Worker 
print_addr64(__u64 addr,char * buff,size_t len)51*de1e4e89SAndroid Build Coastguard Worker static int print_addr64(__u64 addr, char *buff, size_t len)
52*de1e4e89SAndroid Build Coastguard Worker {
53*de1e4e89SAndroid Build Coastguard Worker 	__u16 *words = (__u16 *)&addr;
54*de1e4e89SAndroid Build Coastguard Worker 	__u16 v;
55*de1e4e89SAndroid Build Coastguard Worker 	int i, ret;
56*de1e4e89SAndroid Build Coastguard Worker 	size_t written = 0;
57*de1e4e89SAndroid Build Coastguard Worker 	char *sep = ":";
58*de1e4e89SAndroid Build Coastguard Worker 
59*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < 4; i++) {
60*de1e4e89SAndroid Build Coastguard Worker 		v = ntohs(words[i]);
61*de1e4e89SAndroid Build Coastguard Worker 
62*de1e4e89SAndroid Build Coastguard Worker 		if (i == 3)
63*de1e4e89SAndroid Build Coastguard Worker 			sep = "";
64*de1e4e89SAndroid Build Coastguard Worker 
65*de1e4e89SAndroid Build Coastguard Worker 		ret = snprintf(&buff[written], len - written, "%x%s", v, sep);
66*de1e4e89SAndroid Build Coastguard Worker 		if (ret < 0)
67*de1e4e89SAndroid Build Coastguard Worker 			return ret;
68*de1e4e89SAndroid Build Coastguard Worker 
69*de1e4e89SAndroid Build Coastguard Worker 		written += ret;
70*de1e4e89SAndroid Build Coastguard Worker 	}
71*de1e4e89SAndroid Build Coastguard Worker 
72*de1e4e89SAndroid Build Coastguard Worker 	return written;
73*de1e4e89SAndroid Build Coastguard Worker }
74*de1e4e89SAndroid Build Coastguard Worker 
print_ila_locid(FILE * fp,int attr,struct rtattr * tb[],int space)75*de1e4e89SAndroid Build Coastguard Worker static void print_ila_locid(FILE *fp, int attr, struct rtattr *tb[], int space)
76*de1e4e89SAndroid Build Coastguard Worker {
77*de1e4e89SAndroid Build Coastguard Worker 	char abuf[256];
78*de1e4e89SAndroid Build Coastguard Worker 	size_t blen;
79*de1e4e89SAndroid Build Coastguard Worker 	int i;
80*de1e4e89SAndroid Build Coastguard Worker 
81*de1e4e89SAndroid Build Coastguard Worker 	if (tb[attr]) {
82*de1e4e89SAndroid Build Coastguard Worker 		blen = print_addr64(rta_getattr_u32(tb[attr]),
83*de1e4e89SAndroid Build Coastguard Worker 				    abuf, sizeof(abuf));
84*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "%s", abuf);
85*de1e4e89SAndroid Build Coastguard Worker 	} else {
86*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "-");
87*de1e4e89SAndroid Build Coastguard Worker 		blen = 1;
88*de1e4e89SAndroid Build Coastguard Worker 	}
89*de1e4e89SAndroid Build Coastguard Worker 
90*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < space - blen; i++)
91*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, " ");
92*de1e4e89SAndroid Build Coastguard Worker }
93*de1e4e89SAndroid Build Coastguard Worker 
print_ila_mapping(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)94*de1e4e89SAndroid Build Coastguard Worker static int print_ila_mapping(const struct sockaddr_nl *who,
95*de1e4e89SAndroid Build Coastguard Worker 			     struct nlmsghdr *n, void *arg)
96*de1e4e89SAndroid Build Coastguard Worker {
97*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp = (FILE *)arg;
98*de1e4e89SAndroid Build Coastguard Worker 	struct genlmsghdr *ghdr;
99*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[ILA_ATTR_MAX + 1];
100*de1e4e89SAndroid Build Coastguard Worker 	int len = n->nlmsg_len;
101*de1e4e89SAndroid Build Coastguard Worker 
102*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_type != genl_family)
103*de1e4e89SAndroid Build Coastguard Worker 		return 0;
104*de1e4e89SAndroid Build Coastguard Worker 
105*de1e4e89SAndroid Build Coastguard Worker 	len -= NLMSG_LENGTH(GENL_HDRLEN);
106*de1e4e89SAndroid Build Coastguard Worker 	if (len < 0)
107*de1e4e89SAndroid Build Coastguard Worker 		return -1;
108*de1e4e89SAndroid Build Coastguard Worker 
109*de1e4e89SAndroid Build Coastguard Worker 	ghdr = NLMSG_DATA(n);
110*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr(tb, ILA_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
111*de1e4e89SAndroid Build Coastguard Worker 
112*de1e4e89SAndroid Build Coastguard Worker 	print_ila_locid(fp, ILA_ATTR_LOCATOR_MATCH, tb, ADDR_BUF_SIZE);
113*de1e4e89SAndroid Build Coastguard Worker 	print_ila_locid(fp, ILA_ATTR_LOCATOR, tb, ADDR_BUF_SIZE);
114*de1e4e89SAndroid Build Coastguard Worker 
115*de1e4e89SAndroid Build Coastguard Worker 	if (tb[ILA_ATTR_IFINDEX])
116*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "%s", ll_index_to_name(rta_getattr_u32(tb[ILA_ATTR_IFINDEX])));
117*de1e4e89SAndroid Build Coastguard Worker 	else
118*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "-");
119*de1e4e89SAndroid Build Coastguard Worker 	fprintf(fp, "\n");
120*de1e4e89SAndroid Build Coastguard Worker 
121*de1e4e89SAndroid Build Coastguard Worker 	return 0;
122*de1e4e89SAndroid Build Coastguard Worker }
123*de1e4e89SAndroid Build Coastguard Worker 
124*de1e4e89SAndroid Build Coastguard Worker #define NLMSG_BUF_SIZE 4096
125*de1e4e89SAndroid Build Coastguard Worker 
do_list(int argc,char ** argv)126*de1e4e89SAndroid Build Coastguard Worker static int do_list(int argc, char **argv)
127*de1e4e89SAndroid Build Coastguard Worker {
128*de1e4e89SAndroid Build Coastguard Worker 	ILA_REQUEST(req, 1024, ILA_CMD_GET, NLM_F_REQUEST | NLM_F_DUMP);
129*de1e4e89SAndroid Build Coastguard Worker 
130*de1e4e89SAndroid Build Coastguard Worker 	if (argc > 0) {
131*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "\"ip ila show\" does not take "
132*de1e4e89SAndroid Build Coastguard Worker 			"any arguments.\n");
133*de1e4e89SAndroid Build Coastguard Worker 		return -1;
134*de1e4e89SAndroid Build Coastguard Worker 	}
135*de1e4e89SAndroid Build Coastguard Worker 
136*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_send(&genl_rth, (void *)&req, req.n.nlmsg_len) < 0) {
137*de1e4e89SAndroid Build Coastguard Worker 		perror("Cannot send dump request");
138*de1e4e89SAndroid Build Coastguard Worker 		exit(1);
139*de1e4e89SAndroid Build Coastguard Worker 	}
140*de1e4e89SAndroid Build Coastguard Worker 
141*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_dump_filter(&genl_rth, print_ila_mapping, stdout) < 0) {
142*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Dump terminated\n");
143*de1e4e89SAndroid Build Coastguard Worker 		return 1;
144*de1e4e89SAndroid Build Coastguard Worker 	}
145*de1e4e89SAndroid Build Coastguard Worker 
146*de1e4e89SAndroid Build Coastguard Worker 	return 0;
147*de1e4e89SAndroid Build Coastguard Worker }
148*de1e4e89SAndroid Build Coastguard Worker 
ila_parse_opt(int argc,char ** argv,struct nlmsghdr * n,bool adding)149*de1e4e89SAndroid Build Coastguard Worker static int ila_parse_opt(int argc, char **argv, struct nlmsghdr *n,
150*de1e4e89SAndroid Build Coastguard Worker 			 bool adding)
151*de1e4e89SAndroid Build Coastguard Worker {
152*de1e4e89SAndroid Build Coastguard Worker 	__u64 locator = 0;
153*de1e4e89SAndroid Build Coastguard Worker 	__u64 locator_match = 0;
154*de1e4e89SAndroid Build Coastguard Worker 	int ifindex = 0;
155*de1e4e89SAndroid Build Coastguard Worker 	bool loc_set = false;
156*de1e4e89SAndroid Build Coastguard Worker 	bool loc_match_set = false;
157*de1e4e89SAndroid Build Coastguard Worker 	bool ifindex_set = false;
158*de1e4e89SAndroid Build Coastguard Worker 
159*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
160*de1e4e89SAndroid Build Coastguard Worker 		if (!matches(*argv, "loc")) {
161*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
162*de1e4e89SAndroid Build Coastguard Worker 
163*de1e4e89SAndroid Build Coastguard Worker 			if (get_addr64(&locator, *argv) < 0) {
164*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Bad locator: %s\n", *argv);
165*de1e4e89SAndroid Build Coastguard Worker 				return -1;
166*de1e4e89SAndroid Build Coastguard Worker 			}
167*de1e4e89SAndroid Build Coastguard Worker 			loc_set = true;
168*de1e4e89SAndroid Build Coastguard Worker 		} else if (!matches(*argv, "loc_match")) {
169*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
170*de1e4e89SAndroid Build Coastguard Worker 
171*de1e4e89SAndroid Build Coastguard Worker 			if (get_addr64(&locator_match, *argv) < 0) {
172*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Bad locator to match: %s\n",
173*de1e4e89SAndroid Build Coastguard Worker 					*argv);
174*de1e4e89SAndroid Build Coastguard Worker 				return -1;
175*de1e4e89SAndroid Build Coastguard Worker 			}
176*de1e4e89SAndroid Build Coastguard Worker 			loc_match_set = true;
177*de1e4e89SAndroid Build Coastguard Worker 		} else if (!matches(*argv, "dev")) {
178*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
179*de1e4e89SAndroid Build Coastguard Worker 
180*de1e4e89SAndroid Build Coastguard Worker 			ifindex = ll_name_to_index(*argv);
181*de1e4e89SAndroid Build Coastguard Worker 			if (ifindex == 0) {
182*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "No such interface: %s\n",
183*de1e4e89SAndroid Build Coastguard Worker 					*argv);
184*de1e4e89SAndroid Build Coastguard Worker 				return -1;
185*de1e4e89SAndroid Build Coastguard Worker 			}
186*de1e4e89SAndroid Build Coastguard Worker 			ifindex_set = true;
187*de1e4e89SAndroid Build Coastguard Worker 		} else {
188*de1e4e89SAndroid Build Coastguard Worker 			usage();
189*de1e4e89SAndroid Build Coastguard Worker 			return -1;
190*de1e4e89SAndroid Build Coastguard Worker 		}
191*de1e4e89SAndroid Build Coastguard Worker 		argc--, argv++;
192*de1e4e89SAndroid Build Coastguard Worker 	}
193*de1e4e89SAndroid Build Coastguard Worker 
194*de1e4e89SAndroid Build Coastguard Worker 	if (adding) {
195*de1e4e89SAndroid Build Coastguard Worker 		if (!loc_set) {
196*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "ila: missing locator\n");
197*de1e4e89SAndroid Build Coastguard Worker 			return -1;
198*de1e4e89SAndroid Build Coastguard Worker 		}
199*de1e4e89SAndroid Build Coastguard Worker 		if (!loc_match_set) {
200*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "ila: missing locator0match\n");
201*de1e4e89SAndroid Build Coastguard Worker 			return -1;
202*de1e4e89SAndroid Build Coastguard Worker 		}
203*de1e4e89SAndroid Build Coastguard Worker 	}
204*de1e4e89SAndroid Build Coastguard Worker 
205*de1e4e89SAndroid Build Coastguard Worker 	if (loc_match_set)
206*de1e4e89SAndroid Build Coastguard Worker 		addattr64(n, 1024, ILA_ATTR_LOCATOR_MATCH, locator_match);
207*de1e4e89SAndroid Build Coastguard Worker 
208*de1e4e89SAndroid Build Coastguard Worker 	if (loc_set)
209*de1e4e89SAndroid Build Coastguard Worker 		addattr64(n, 1024, ILA_ATTR_LOCATOR, locator);
210*de1e4e89SAndroid Build Coastguard Worker 
211*de1e4e89SAndroid Build Coastguard Worker 	if (ifindex_set)
212*de1e4e89SAndroid Build Coastguard Worker 		addattr32(n, 1024, ILA_ATTR_IFINDEX, ifindex);
213*de1e4e89SAndroid Build Coastguard Worker 
214*de1e4e89SAndroid Build Coastguard Worker 	return 0;
215*de1e4e89SAndroid Build Coastguard Worker }
216*de1e4e89SAndroid Build Coastguard Worker 
do_add(int argc,char ** argv)217*de1e4e89SAndroid Build Coastguard Worker static int do_add(int argc, char **argv)
218*de1e4e89SAndroid Build Coastguard Worker {
219*de1e4e89SAndroid Build Coastguard Worker 	ILA_REQUEST(req, 1024, ILA_CMD_ADD, NLM_F_REQUEST);
220*de1e4e89SAndroid Build Coastguard Worker 
221*de1e4e89SAndroid Build Coastguard Worker 	ila_parse_opt(argc, argv, &req.n, true);
222*de1e4e89SAndroid Build Coastguard Worker 
223*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
224*de1e4e89SAndroid Build Coastguard Worker 		return -2;
225*de1e4e89SAndroid Build Coastguard Worker 
226*de1e4e89SAndroid Build Coastguard Worker 	return 0;
227*de1e4e89SAndroid Build Coastguard Worker }
228*de1e4e89SAndroid Build Coastguard Worker 
do_del(int argc,char ** argv)229*de1e4e89SAndroid Build Coastguard Worker static int do_del(int argc, char **argv)
230*de1e4e89SAndroid Build Coastguard Worker {
231*de1e4e89SAndroid Build Coastguard Worker 	ILA_REQUEST(req, 1024, ILA_CMD_DEL, NLM_F_REQUEST);
232*de1e4e89SAndroid Build Coastguard Worker 
233*de1e4e89SAndroid Build Coastguard Worker 	ila_parse_opt(argc, argv, &req.n, false);
234*de1e4e89SAndroid Build Coastguard Worker 
235*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
236*de1e4e89SAndroid Build Coastguard Worker 		return -2;
237*de1e4e89SAndroid Build Coastguard Worker 
238*de1e4e89SAndroid Build Coastguard Worker 	return 0;
239*de1e4e89SAndroid Build Coastguard Worker }
240*de1e4e89SAndroid Build Coastguard Worker 
do_ipila(int argc,char ** argv)241*de1e4e89SAndroid Build Coastguard Worker int do_ipila(int argc, char **argv)
242*de1e4e89SAndroid Build Coastguard Worker {
243*de1e4e89SAndroid Build Coastguard Worker 	if (argc < 1)
244*de1e4e89SAndroid Build Coastguard Worker 		usage();
245*de1e4e89SAndroid Build Coastguard Worker 
246*de1e4e89SAndroid Build Coastguard Worker 	if (matches(*argv, "help") == 0)
247*de1e4e89SAndroid Build Coastguard Worker 		usage();
248*de1e4e89SAndroid Build Coastguard Worker 
249*de1e4e89SAndroid Build Coastguard Worker 	if (genl_init_handle(&genl_rth, ILA_GENL_NAME, &genl_family))
250*de1e4e89SAndroid Build Coastguard Worker 		exit(1);
251*de1e4e89SAndroid Build Coastguard Worker 
252*de1e4e89SAndroid Build Coastguard Worker 	if (matches(*argv, "add") == 0)
253*de1e4e89SAndroid Build Coastguard Worker 		return do_add(argc-1, argv+1);
254*de1e4e89SAndroid Build Coastguard Worker 	if (matches(*argv, "delete") == 0)
255*de1e4e89SAndroid Build Coastguard Worker 		return do_del(argc-1, argv+1);
256*de1e4e89SAndroid Build Coastguard Worker 	if (matches(*argv, "list") == 0)
257*de1e4e89SAndroid Build Coastguard Worker 		return do_list(argc-1, argv+1);
258*de1e4e89SAndroid Build Coastguard Worker 
259*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip ila help\".\n",
260*de1e4e89SAndroid Build Coastguard Worker 		*argv);
261*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
262*de1e4e89SAndroid Build Coastguard Worker }
263