xref: /aosp_15_r20/external/iproute2/ip/ipaddrlabel.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * ipaddrlabel.c	"ip addrlabel"
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  * Copyright (C)2007 USAGI/WIDE Project
5*de1e4e89SAndroid Build Coastguard Worker  *
6*de1e4e89SAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
7*de1e4e89SAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
8*de1e4e89SAndroid Build Coastguard Worker  * the Free Software Foundation; either version 2 of the License, or
9*de1e4e89SAndroid Build Coastguard Worker  * (at your option) any later version.
10*de1e4e89SAndroid Build Coastguard Worker  *
11*de1e4e89SAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
12*de1e4e89SAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*de1e4e89SAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*de1e4e89SAndroid Build Coastguard Worker  * GNU General Public License for more details.
15*de1e4e89SAndroid Build Coastguard Worker  *
16*de1e4e89SAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
17*de1e4e89SAndroid Build Coastguard Worker  * along with this program; if not, see <http://www.gnu.org/licenses>.
18*de1e4e89SAndroid Build Coastguard Worker  *
19*de1e4e89SAndroid Build Coastguard Worker  *
20*de1e4e89SAndroid Build Coastguard Worker  * Based on iprule.c.
21*de1e4e89SAndroid Build Coastguard Worker  *
22*de1e4e89SAndroid Build Coastguard Worker  * Authors:	YOSHIFUJI Hideaki <[email protected]>
23*de1e4e89SAndroid Build Coastguard Worker  *
24*de1e4e89SAndroid Build Coastguard Worker  */
25*de1e4e89SAndroid Build Coastguard Worker 
26*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
27*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
30*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
31*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
32*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
33*de1e4e89SAndroid Build Coastguard Worker #include <netinet/ip.h>
34*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
35*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
36*de1e4e89SAndroid Build Coastguard Worker #include <linux/types.h>
37*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_addrlabel.h>
38*de1e4e89SAndroid Build Coastguard Worker 
39*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
40*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
41*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
42*de1e4e89SAndroid Build Coastguard Worker 
43*de1e4e89SAndroid Build Coastguard Worker #define IFAL_RTA(r)	((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrlblmsg))))
44*de1e4e89SAndroid Build Coastguard Worker #define IFAL_PAYLOAD(n)	NLMSG_PAYLOAD(n, sizeof(struct ifaddrlblmsg))
45*de1e4e89SAndroid Build Coastguard Worker 
46*de1e4e89SAndroid Build Coastguard Worker extern struct rtnl_handle rth;
47*de1e4e89SAndroid Build Coastguard Worker 
48*de1e4e89SAndroid Build Coastguard Worker static void usage(void) __attribute__((noreturn));
49*de1e4e89SAndroid Build Coastguard Worker 
usage(void)50*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
51*de1e4e89SAndroid Build Coastguard Worker {
52*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: ip addrlabel { add | del } prefix PREFIX [ dev DEV ] [ label LABEL ]\n");
53*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "       ip addrlabel [ list | flush | help ]\n");
54*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
55*de1e4e89SAndroid Build Coastguard Worker }
56*de1e4e89SAndroid Build Coastguard Worker 
print_addrlabel(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)57*de1e4e89SAndroid Build Coastguard Worker int print_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
58*de1e4e89SAndroid Build Coastguard Worker {
59*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp = (FILE *)arg;
60*de1e4e89SAndroid Build Coastguard Worker 	struct ifaddrlblmsg *ifal = NLMSG_DATA(n);
61*de1e4e89SAndroid Build Coastguard Worker 	int len = n->nlmsg_len;
62*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[IFAL_MAX+1];
63*de1e4e89SAndroid Build Coastguard Worker 
64*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_type != RTM_NEWADDRLABEL && n->nlmsg_type != RTM_DELADDRLABEL)
65*de1e4e89SAndroid Build Coastguard Worker 		return 0;
66*de1e4e89SAndroid Build Coastguard Worker 
67*de1e4e89SAndroid Build Coastguard Worker 	len -= NLMSG_LENGTH(sizeof(*ifal));
68*de1e4e89SAndroid Build Coastguard Worker 	if (len < 0)
69*de1e4e89SAndroid Build Coastguard Worker 		return -1;
70*de1e4e89SAndroid Build Coastguard Worker 
71*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr(tb, IFAL_MAX, IFAL_RTA(ifal), len);
72*de1e4e89SAndroid Build Coastguard Worker 
73*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_type == RTM_DELADDRLABEL)
74*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "Deleted ");
75*de1e4e89SAndroid Build Coastguard Worker 
76*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFAL_ADDRESS]) {
77*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "prefix %s/%u ",
78*de1e4e89SAndroid Build Coastguard Worker 			format_host_rta(ifal->ifal_family,
79*de1e4e89SAndroid Build Coastguard Worker 		                        tb[IFAL_ADDRESS]),
80*de1e4e89SAndroid Build Coastguard Worker 			ifal->ifal_prefixlen);
81*de1e4e89SAndroid Build Coastguard Worker 	}
82*de1e4e89SAndroid Build Coastguard Worker 
83*de1e4e89SAndroid Build Coastguard Worker 	if (ifal->ifal_index)
84*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "dev %s ", ll_index_to_name(ifal->ifal_index));
85*de1e4e89SAndroid Build Coastguard Worker 
86*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFAL_LABEL] && RTA_PAYLOAD(tb[IFAL_LABEL]) == sizeof(uint32_t)) {
87*de1e4e89SAndroid Build Coastguard Worker 		uint32_t label;
88*de1e4e89SAndroid Build Coastguard Worker 
89*de1e4e89SAndroid Build Coastguard Worker 		memcpy(&label, RTA_DATA(tb[IFAL_LABEL]), sizeof(label));
90*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "label %u ", label);
91*de1e4e89SAndroid Build Coastguard Worker 	}
92*de1e4e89SAndroid Build Coastguard Worker 
93*de1e4e89SAndroid Build Coastguard Worker 	fprintf(fp, "\n");
94*de1e4e89SAndroid Build Coastguard Worker 	fflush(fp);
95*de1e4e89SAndroid Build Coastguard Worker 	return 0;
96*de1e4e89SAndroid Build Coastguard Worker }
97*de1e4e89SAndroid Build Coastguard Worker 
ipaddrlabel_list(int argc,char ** argv)98*de1e4e89SAndroid Build Coastguard Worker static int ipaddrlabel_list(int argc, char **argv)
99*de1e4e89SAndroid Build Coastguard Worker {
100*de1e4e89SAndroid Build Coastguard Worker 	int af = preferred_family;
101*de1e4e89SAndroid Build Coastguard Worker 
102*de1e4e89SAndroid Build Coastguard Worker 	if (af == AF_UNSPEC)
103*de1e4e89SAndroid Build Coastguard Worker 		af = AF_INET6;
104*de1e4e89SAndroid Build Coastguard Worker 
105*de1e4e89SAndroid Build Coastguard Worker 	if (argc > 0) {
106*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "\"ip addrlabel show\" does not take any arguments.\n");
107*de1e4e89SAndroid Build Coastguard Worker 		return -1;
108*de1e4e89SAndroid Build Coastguard Worker 	}
109*de1e4e89SAndroid Build Coastguard Worker 
110*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) {
111*de1e4e89SAndroid Build Coastguard Worker 		perror("Cannot send dump request");
112*de1e4e89SAndroid Build Coastguard Worker 		return 1;
113*de1e4e89SAndroid Build Coastguard Worker 	}
114*de1e4e89SAndroid Build Coastguard Worker 
115*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_dump_filter(&rth, print_addrlabel, stdout) < 0) {
116*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Dump terminated\n");
117*de1e4e89SAndroid Build Coastguard Worker 		return 1;
118*de1e4e89SAndroid Build Coastguard Worker 	}
119*de1e4e89SAndroid Build Coastguard Worker 
120*de1e4e89SAndroid Build Coastguard Worker 	return 0;
121*de1e4e89SAndroid Build Coastguard Worker }
122*de1e4e89SAndroid Build Coastguard Worker 
123*de1e4e89SAndroid Build Coastguard Worker 
ipaddrlabel_modify(int cmd,int argc,char ** argv)124*de1e4e89SAndroid Build Coastguard Worker static int ipaddrlabel_modify(int cmd, int argc, char **argv)
125*de1e4e89SAndroid Build Coastguard Worker {
126*de1e4e89SAndroid Build Coastguard Worker 	struct {
127*de1e4e89SAndroid Build Coastguard Worker 		struct nlmsghdr	n;
128*de1e4e89SAndroid Build Coastguard Worker 		struct ifaddrlblmsg	ifal;
129*de1e4e89SAndroid Build Coastguard Worker 		char			buf[1024];
130*de1e4e89SAndroid Build Coastguard Worker 	} req = {
131*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_type = cmd,
132*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrlblmsg)),
133*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_flags = NLM_F_REQUEST,
134*de1e4e89SAndroid Build Coastguard Worker 		.ifal.ifal_family = preferred_family,
135*de1e4e89SAndroid Build Coastguard Worker 	};
136*de1e4e89SAndroid Build Coastguard Worker 
137*de1e4e89SAndroid Build Coastguard Worker 	inet_prefix prefix = {};
138*de1e4e89SAndroid Build Coastguard Worker 	uint32_t label = 0xffffffffUL;
139*de1e4e89SAndroid Build Coastguard Worker 	char *p = NULL;
140*de1e4e89SAndroid Build Coastguard Worker 	char *l = NULL;
141*de1e4e89SAndroid Build Coastguard Worker 
142*de1e4e89SAndroid Build Coastguard Worker 	if (cmd == RTM_NEWADDRLABEL) {
143*de1e4e89SAndroid Build Coastguard Worker 		req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
144*de1e4e89SAndroid Build Coastguard Worker 	}
145*de1e4e89SAndroid Build Coastguard Worker 
146*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
147*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(*argv, "prefix") == 0) {
148*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
149*de1e4e89SAndroid Build Coastguard Worker 			p = *argv;
150*de1e4e89SAndroid Build Coastguard Worker 			get_prefix(&prefix, *argv, preferred_family);
151*de1e4e89SAndroid Build Coastguard Worker 		} else if (strcmp(*argv, "dev") == 0) {
152*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
153*de1e4e89SAndroid Build Coastguard Worker 			if ((req.ifal.ifal_index = ll_name_to_index(*argv)) == 0)
154*de1e4e89SAndroid Build Coastguard Worker 				invarg("dev is invalid\n", *argv);
155*de1e4e89SAndroid Build Coastguard Worker 		} else if (strcmp(*argv, "label") == 0) {
156*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
157*de1e4e89SAndroid Build Coastguard Worker 			l = *argv;
158*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&label, *argv, 0) || label == 0xffffffffUL)
159*de1e4e89SAndroid Build Coastguard Worker 				invarg("label is invalid\n", *argv);
160*de1e4e89SAndroid Build Coastguard Worker 		}
161*de1e4e89SAndroid Build Coastguard Worker 		argc--;
162*de1e4e89SAndroid Build Coastguard Worker 		argv++;
163*de1e4e89SAndroid Build Coastguard Worker 	}
164*de1e4e89SAndroid Build Coastguard Worker 	if (p == NULL) {
165*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Not enough information: \"prefix\" argument is required.\n");
166*de1e4e89SAndroid Build Coastguard Worker 		return -1;
167*de1e4e89SAndroid Build Coastguard Worker 	}
168*de1e4e89SAndroid Build Coastguard Worker 	if (l == NULL) {
169*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Not enough information: \"label\" argument is required.\n");
170*de1e4e89SAndroid Build Coastguard Worker 		return -1;
171*de1e4e89SAndroid Build Coastguard Worker 	}
172*de1e4e89SAndroid Build Coastguard Worker 	addattr32(&req.n, sizeof(req), IFAL_LABEL, label);
173*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(&req.n, sizeof(req), IFAL_ADDRESS, &prefix.data, prefix.bytelen);
174*de1e4e89SAndroid Build Coastguard Worker 	req.ifal.ifal_prefixlen = prefix.bitlen;
175*de1e4e89SAndroid Build Coastguard Worker 
176*de1e4e89SAndroid Build Coastguard Worker 	if (req.ifal.ifal_family == AF_UNSPEC)
177*de1e4e89SAndroid Build Coastguard Worker 		req.ifal.ifal_family = AF_INET6;
178*de1e4e89SAndroid Build Coastguard Worker 
179*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
180*de1e4e89SAndroid Build Coastguard Worker 		return -2;
181*de1e4e89SAndroid Build Coastguard Worker 
182*de1e4e89SAndroid Build Coastguard Worker 	return 0;
183*de1e4e89SAndroid Build Coastguard Worker }
184*de1e4e89SAndroid Build Coastguard Worker 
185*de1e4e89SAndroid Build Coastguard Worker 
flush_addrlabel(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)186*de1e4e89SAndroid Build Coastguard Worker static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
187*de1e4e89SAndroid Build Coastguard Worker {
188*de1e4e89SAndroid Build Coastguard Worker 	struct rtnl_handle rth2;
189*de1e4e89SAndroid Build Coastguard Worker 	struct rtmsg *r = NLMSG_DATA(n);
190*de1e4e89SAndroid Build Coastguard Worker 	int len = n->nlmsg_len;
191*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[IFAL_MAX+1];
192*de1e4e89SAndroid Build Coastguard Worker 
193*de1e4e89SAndroid Build Coastguard Worker 	len -= NLMSG_LENGTH(sizeof(*r));
194*de1e4e89SAndroid Build Coastguard Worker 	if (len < 0)
195*de1e4e89SAndroid Build Coastguard Worker 		return -1;
196*de1e4e89SAndroid Build Coastguard Worker 
197*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr(tb, IFAL_MAX, RTM_RTA(r), len);
198*de1e4e89SAndroid Build Coastguard Worker 
199*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFAL_ADDRESS]) {
200*de1e4e89SAndroid Build Coastguard Worker 		n->nlmsg_type = RTM_DELADDRLABEL;
201*de1e4e89SAndroid Build Coastguard Worker 		n->nlmsg_flags = NLM_F_REQUEST;
202*de1e4e89SAndroid Build Coastguard Worker 
203*de1e4e89SAndroid Build Coastguard Worker 		if (rtnl_open(&rth2, 0) < 0)
204*de1e4e89SAndroid Build Coastguard Worker 			return -1;
205*de1e4e89SAndroid Build Coastguard Worker 
206*de1e4e89SAndroid Build Coastguard Worker 		if (rtnl_talk(&rth2, n, NULL, 0) < 0)
207*de1e4e89SAndroid Build Coastguard Worker 			return -2;
208*de1e4e89SAndroid Build Coastguard Worker 
209*de1e4e89SAndroid Build Coastguard Worker 		rtnl_close(&rth2);
210*de1e4e89SAndroid Build Coastguard Worker 	}
211*de1e4e89SAndroid Build Coastguard Worker 
212*de1e4e89SAndroid Build Coastguard Worker 	return 0;
213*de1e4e89SAndroid Build Coastguard Worker }
214*de1e4e89SAndroid Build Coastguard Worker 
ipaddrlabel_flush(int argc,char ** argv)215*de1e4e89SAndroid Build Coastguard Worker static int ipaddrlabel_flush(int argc, char **argv)
216*de1e4e89SAndroid Build Coastguard Worker {
217*de1e4e89SAndroid Build Coastguard Worker 	int af = preferred_family;
218*de1e4e89SAndroid Build Coastguard Worker 
219*de1e4e89SAndroid Build Coastguard Worker 	if (af == AF_UNSPEC)
220*de1e4e89SAndroid Build Coastguard Worker 		af = AF_INET6;
221*de1e4e89SAndroid Build Coastguard Worker 
222*de1e4e89SAndroid Build Coastguard Worker 	if (argc > 0) {
223*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "\"ip addrlabel flush\" does not allow extra arguments\n");
224*de1e4e89SAndroid Build Coastguard Worker 		return -1;
225*de1e4e89SAndroid Build Coastguard Worker 	}
226*de1e4e89SAndroid Build Coastguard Worker 
227*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) {
228*de1e4e89SAndroid Build Coastguard Worker 		perror("Cannot send dump request");
229*de1e4e89SAndroid Build Coastguard Worker 		return -1;
230*de1e4e89SAndroid Build Coastguard Worker 	}
231*de1e4e89SAndroid Build Coastguard Worker 
232*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_dump_filter(&rth, flush_addrlabel, NULL) < 0) {
233*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Flush terminated\n");
234*de1e4e89SAndroid Build Coastguard Worker 		return -1;
235*de1e4e89SAndroid Build Coastguard Worker 	}
236*de1e4e89SAndroid Build Coastguard Worker 
237*de1e4e89SAndroid Build Coastguard Worker 	return 0;
238*de1e4e89SAndroid Build Coastguard Worker }
239*de1e4e89SAndroid Build Coastguard Worker 
do_ipaddrlabel(int argc,char ** argv)240*de1e4e89SAndroid Build Coastguard Worker int do_ipaddrlabel(int argc, char **argv)
241*de1e4e89SAndroid Build Coastguard Worker {
242*de1e4e89SAndroid Build Coastguard Worker 	if (argc < 1) {
243*de1e4e89SAndroid Build Coastguard Worker 		return ipaddrlabel_list(0, NULL);
244*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "list") == 0 ||
245*de1e4e89SAndroid Build Coastguard Worker 		   matches(argv[0], "lst") == 0 ||
246*de1e4e89SAndroid Build Coastguard Worker 		   matches(argv[0], "show") == 0) {
247*de1e4e89SAndroid Build Coastguard Worker 		return ipaddrlabel_list(argc-1, argv+1);
248*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "add") == 0) {
249*de1e4e89SAndroid Build Coastguard Worker 		return ipaddrlabel_modify(RTM_NEWADDRLABEL, argc-1, argv+1);
250*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "delete") == 0) {
251*de1e4e89SAndroid Build Coastguard Worker 		return ipaddrlabel_modify(RTM_DELADDRLABEL, argc-1, argv+1);
252*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "flush") == 0) {
253*de1e4e89SAndroid Build Coastguard Worker 		return ipaddrlabel_flush(argc-1, argv+1);
254*de1e4e89SAndroid Build Coastguard Worker 	} else if (matches(argv[0], "help") == 0)
255*de1e4e89SAndroid Build Coastguard Worker 		usage();
256*de1e4e89SAndroid Build Coastguard Worker 
257*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip addrlabel help\".\n", *argv);
258*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
259*de1e4e89SAndroid Build Coastguard Worker }
260