xref: /aosp_15_r20/external/iproute2/ip/iptoken.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * iptoken.c    "ip token"
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:     Daniel Borkmann, <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker  */
11*de1e4e89SAndroid Build Coastguard Worker 
12*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <stdbool.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 <string.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <netinet/ip.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <linux/types.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <linux/if.h>
25*de1e4e89SAndroid Build Coastguard Worker 
26*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
27*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
28*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
29*de1e4e89SAndroid Build Coastguard Worker 
30*de1e4e89SAndroid Build Coastguard Worker extern struct rtnl_handle rth;
31*de1e4e89SAndroid Build Coastguard Worker 
32*de1e4e89SAndroid Build Coastguard Worker struct rtnl_dump_args {
33*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp;
34*de1e4e89SAndroid Build Coastguard Worker 	int ifindex;
35*de1e4e89SAndroid Build Coastguard Worker };
36*de1e4e89SAndroid Build Coastguard Worker 
37*de1e4e89SAndroid Build Coastguard Worker static void usage(void) __attribute__((noreturn));
38*de1e4e89SAndroid Build Coastguard Worker 
usage(void)39*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
40*de1e4e89SAndroid Build Coastguard Worker {
41*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: ip token [ list | set | del | get ] [ TOKEN ] [ dev DEV ]\n");
42*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
43*de1e4e89SAndroid Build Coastguard Worker }
44*de1e4e89SAndroid Build Coastguard Worker 
print_token(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)45*de1e4e89SAndroid Build Coastguard Worker static int print_token(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
46*de1e4e89SAndroid Build Coastguard Worker {
47*de1e4e89SAndroid Build Coastguard Worker 	struct rtnl_dump_args *args = arg;
48*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp = args->fp;
49*de1e4e89SAndroid Build Coastguard Worker 	int ifindex = args->ifindex;
50*de1e4e89SAndroid Build Coastguard Worker 	struct ifinfomsg *ifi = NLMSG_DATA(n);
51*de1e4e89SAndroid Build Coastguard Worker 	int len = n->nlmsg_len;
52*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[IFLA_MAX + 1];
53*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *ltb[IFLA_INET6_MAX + 1];
54*de1e4e89SAndroid Build Coastguard Worker 
55*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_type != RTM_NEWLINK)
56*de1e4e89SAndroid Build Coastguard Worker 		return -1;
57*de1e4e89SAndroid Build Coastguard Worker 
58*de1e4e89SAndroid Build Coastguard Worker 	len -= NLMSG_LENGTH(sizeof(*ifi));
59*de1e4e89SAndroid Build Coastguard Worker 	if (len < 0)
60*de1e4e89SAndroid Build Coastguard Worker 		return -1;
61*de1e4e89SAndroid Build Coastguard Worker 
62*de1e4e89SAndroid Build Coastguard Worker 	if (ifi->ifi_family != AF_INET6)
63*de1e4e89SAndroid Build Coastguard Worker 		return -1;
64*de1e4e89SAndroid Build Coastguard Worker 	if (ifi->ifi_index == 0)
65*de1e4e89SAndroid Build Coastguard Worker 		return -1;
66*de1e4e89SAndroid Build Coastguard Worker 	if (ifindex > 0 && ifi->ifi_index != ifindex)
67*de1e4e89SAndroid Build Coastguard Worker 		return 0;
68*de1e4e89SAndroid Build Coastguard Worker 	if (ifi->ifi_flags & (IFF_LOOPBACK | IFF_NOARP))
69*de1e4e89SAndroid Build Coastguard Worker 		return 0;
70*de1e4e89SAndroid Build Coastguard Worker 
71*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
72*de1e4e89SAndroid Build Coastguard Worker 	if (!tb[IFLA_PROTINFO])
73*de1e4e89SAndroid Build Coastguard Worker 		return -1;
74*de1e4e89SAndroid Build Coastguard Worker 
75*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(ltb, IFLA_INET6_MAX, tb[IFLA_PROTINFO]);
76*de1e4e89SAndroid Build Coastguard Worker 	if (!ltb[IFLA_INET6_TOKEN]) {
77*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Seems there's no support for IPv6 token!\n");
78*de1e4e89SAndroid Build Coastguard Worker 		return -1;
79*de1e4e89SAndroid Build Coastguard Worker 	}
80*de1e4e89SAndroid Build Coastguard Worker 
81*de1e4e89SAndroid Build Coastguard Worker 	fprintf(fp, "token %s dev %s\n",
82*de1e4e89SAndroid Build Coastguard Worker 	        format_host_rta(ifi->ifi_family, ltb[IFLA_INET6_TOKEN]),
83*de1e4e89SAndroid Build Coastguard Worker 	        ll_index_to_name(ifi->ifi_index));
84*de1e4e89SAndroid Build Coastguard Worker 	fflush(fp);
85*de1e4e89SAndroid Build Coastguard Worker 
86*de1e4e89SAndroid Build Coastguard Worker 	return 0;
87*de1e4e89SAndroid Build Coastguard Worker }
88*de1e4e89SAndroid Build Coastguard Worker 
iptoken_list(int argc,char ** argv)89*de1e4e89SAndroid Build Coastguard Worker static int iptoken_list(int argc, char **argv)
90*de1e4e89SAndroid Build Coastguard Worker {
91*de1e4e89SAndroid Build Coastguard Worker 	int af = AF_INET6;
92*de1e4e89SAndroid Build Coastguard Worker 	struct rtnl_dump_args da = { .fp = stdout };
93*de1e4e89SAndroid Build Coastguard Worker 
94*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
95*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(*argv, "dev") == 0) {
96*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
97*de1e4e89SAndroid Build Coastguard Worker 			if ((da.ifindex = ll_name_to_index(*argv)) == 0)
98*de1e4e89SAndroid Build Coastguard Worker 				invarg("dev is invalid\n", *argv);
99*de1e4e89SAndroid Build Coastguard Worker 			break;
100*de1e4e89SAndroid Build Coastguard Worker 		}
101*de1e4e89SAndroid Build Coastguard Worker 		argc--; argv++;
102*de1e4e89SAndroid Build Coastguard Worker 	}
103*de1e4e89SAndroid Build Coastguard Worker 
104*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_wilddump_request(&rth, af, RTM_GETLINK) < 0) {
105*de1e4e89SAndroid Build Coastguard Worker 		perror("Cannot send dump request");
106*de1e4e89SAndroid Build Coastguard Worker 		return -1;
107*de1e4e89SAndroid Build Coastguard Worker 	}
108*de1e4e89SAndroid Build Coastguard Worker 
109*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_dump_filter(&rth, print_token, &da) < 0) {
110*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Dump terminated\n");
111*de1e4e89SAndroid Build Coastguard Worker 		return -1;
112*de1e4e89SAndroid Build Coastguard Worker 	}
113*de1e4e89SAndroid Build Coastguard Worker 
114*de1e4e89SAndroid Build Coastguard Worker 	return 0;
115*de1e4e89SAndroid Build Coastguard Worker }
116*de1e4e89SAndroid Build Coastguard Worker 
iptoken_set(int argc,char ** argv,bool delete)117*de1e4e89SAndroid Build Coastguard Worker static int iptoken_set(int argc, char **argv, bool delete)
118*de1e4e89SAndroid Build Coastguard Worker {
119*de1e4e89SAndroid Build Coastguard Worker 	struct {
120*de1e4e89SAndroid Build Coastguard Worker 		struct nlmsghdr n;
121*de1e4e89SAndroid Build Coastguard Worker 		struct ifinfomsg ifi;
122*de1e4e89SAndroid Build Coastguard Worker 		char buf[512];
123*de1e4e89SAndroid Build Coastguard Worker 	} req = {
124*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
125*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_flags = NLM_F_REQUEST,
126*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_type = RTM_SETLINK,
127*de1e4e89SAndroid Build Coastguard Worker 		.ifi.ifi_family = AF_INET6,
128*de1e4e89SAndroid Build Coastguard Worker 	};
129*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *afs, *afs6;
130*de1e4e89SAndroid Build Coastguard Worker 	bool have_token = delete, have_dev = false;
131*de1e4e89SAndroid Build Coastguard Worker 	inet_prefix addr = { .bytelen = 16, };
132*de1e4e89SAndroid Build Coastguard Worker 
133*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
134*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(*argv, "dev") == 0) {
135*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
136*de1e4e89SAndroid Build Coastguard Worker 			if (!have_dev) {
137*de1e4e89SAndroid Build Coastguard Worker 				if ((req.ifi.ifi_index =
138*de1e4e89SAndroid Build Coastguard Worker 				     ll_name_to_index(*argv)) == 0)
139*de1e4e89SAndroid Build Coastguard Worker 					invarg("dev is invalid\n", *argv);
140*de1e4e89SAndroid Build Coastguard Worker 				have_dev = true;
141*de1e4e89SAndroid Build Coastguard Worker 			}
142*de1e4e89SAndroid Build Coastguard Worker 		} else {
143*de1e4e89SAndroid Build Coastguard Worker 			if (matches(*argv, "help") == 0)
144*de1e4e89SAndroid Build Coastguard Worker 				usage();
145*de1e4e89SAndroid Build Coastguard Worker 			if (!have_token) {
146*de1e4e89SAndroid Build Coastguard Worker 				get_prefix(&addr, *argv, req.ifi.ifi_family);
147*de1e4e89SAndroid Build Coastguard Worker 				have_token = true;
148*de1e4e89SAndroid Build Coastguard Worker 			}
149*de1e4e89SAndroid Build Coastguard Worker 		}
150*de1e4e89SAndroid Build Coastguard Worker 		argc--; argv++;
151*de1e4e89SAndroid Build Coastguard Worker 	}
152*de1e4e89SAndroid Build Coastguard Worker 
153*de1e4e89SAndroid Build Coastguard Worker 	if (!have_token) {
154*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Not enough information: token is required.\n");
155*de1e4e89SAndroid Build Coastguard Worker 		return -1;
156*de1e4e89SAndroid Build Coastguard Worker 	}
157*de1e4e89SAndroid Build Coastguard Worker 	if (!have_dev) {
158*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Not enough information: \"dev\" argument is required.\n");
159*de1e4e89SAndroid Build Coastguard Worker 		return -1;
160*de1e4e89SAndroid Build Coastguard Worker 	}
161*de1e4e89SAndroid Build Coastguard Worker 
162*de1e4e89SAndroid Build Coastguard Worker 	afs = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
163*de1e4e89SAndroid Build Coastguard Worker 	afs6 = addattr_nest(&req.n, sizeof(req), AF_INET6);
164*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(&req.n, sizeof(req), IFLA_INET6_TOKEN,
165*de1e4e89SAndroid Build Coastguard Worker 		  &addr.data, addr.bytelen);
166*de1e4e89SAndroid Build Coastguard Worker 	addattr_nest_end(&req.n, afs6);
167*de1e4e89SAndroid Build Coastguard Worker 	addattr_nest_end(&req.n, afs);
168*de1e4e89SAndroid Build Coastguard Worker 
169*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
170*de1e4e89SAndroid Build Coastguard Worker 		return -2;
171*de1e4e89SAndroid Build Coastguard Worker 
172*de1e4e89SAndroid Build Coastguard Worker 	return 0;
173*de1e4e89SAndroid Build Coastguard Worker }
174*de1e4e89SAndroid Build Coastguard Worker 
do_iptoken(int argc,char ** argv)175*de1e4e89SAndroid Build Coastguard Worker int do_iptoken(int argc, char **argv)
176*de1e4e89SAndroid Build Coastguard Worker {
177*de1e4e89SAndroid Build Coastguard Worker 	ll_init_map(&rth);
178*de1e4e89SAndroid Build Coastguard Worker 
179*de1e4e89SAndroid Build Coastguard Worker 	if (argc < 1) {
180*de1e4e89SAndroid Build Coastguard Worker 		return iptoken_list(0, NULL);
181*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "list") == 0 ||
182*de1e4e89SAndroid Build Coastguard Worker 		   matches(argv[0], "lst") == 0 ||
183*de1e4e89SAndroid Build Coastguard Worker 		   matches(argv[0], "show") == 0) {
184*de1e4e89SAndroid Build Coastguard Worker 		return iptoken_list(argc - 1, argv + 1);
185*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "set") == 0 ||
186*de1e4e89SAndroid Build Coastguard Worker 		   matches(argv[0], "add") == 0) {
187*de1e4e89SAndroid Build Coastguard Worker 		return iptoken_set(argc - 1, argv + 1, false);
188*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "delete") == 0) {
189*de1e4e89SAndroid Build Coastguard Worker 		return iptoken_set(argc - 1, argv + 1, true);
190*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "get") == 0) {
191*de1e4e89SAndroid Build Coastguard Worker 		return iptoken_list(argc - 1, argv + 1);
192*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "help") == 0)
193*de1e4e89SAndroid Build Coastguard Worker 		usage();
194*de1e4e89SAndroid Build Coastguard Worker 
195*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip token help\".\n", *argv);
196*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
197*de1e4e89SAndroid Build Coastguard Worker }
198