xref: /aosp_15_r20/external/iproute2/ip/ipnetconf.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * ipnetconf.c		"ip netconf".
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:	Nicolas Dichtel, <[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 <string.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <sys/time.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
23*de1e4e89SAndroid Build Coastguard Worker 
24*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
25*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
26*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
27*de1e4e89SAndroid Build Coastguard Worker 
28*de1e4e89SAndroid Build Coastguard Worker static struct {
29*de1e4e89SAndroid Build Coastguard Worker 	int family;
30*de1e4e89SAndroid Build Coastguard Worker 	int ifindex;
31*de1e4e89SAndroid Build Coastguard Worker } filter;
32*de1e4e89SAndroid Build Coastguard Worker 
33*de1e4e89SAndroid Build Coastguard Worker static void usage(void) __attribute__((noreturn));
34*de1e4e89SAndroid Build Coastguard Worker 
usage(void)35*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
36*de1e4e89SAndroid Build Coastguard Worker {
37*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: ip netconf show [ dev STRING ]\n");
38*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
39*de1e4e89SAndroid Build Coastguard Worker }
40*de1e4e89SAndroid Build Coastguard Worker 
print_onoff(FILE * f,const char * flag,__u32 val)41*de1e4e89SAndroid Build Coastguard Worker static void print_onoff(FILE *f, const char *flag, __u32 val)
42*de1e4e89SAndroid Build Coastguard Worker {
43*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "%s %s ", flag, val ? "on" : "off");
44*de1e4e89SAndroid Build Coastguard Worker }
45*de1e4e89SAndroid Build Coastguard Worker 
netconf_rta(struct netconfmsg * ncm)46*de1e4e89SAndroid Build Coastguard Worker static struct rtattr *netconf_rta(struct netconfmsg *ncm)
47*de1e4e89SAndroid Build Coastguard Worker {
48*de1e4e89SAndroid Build Coastguard Worker 	return (struct rtattr *)((char *)ncm
49*de1e4e89SAndroid Build Coastguard Worker 				 + NLMSG_ALIGN(sizeof(struct netconfmsg)));
50*de1e4e89SAndroid Build Coastguard Worker }
51*de1e4e89SAndroid Build Coastguard Worker 
print_netconf(const struct sockaddr_nl * who,struct rtnl_ctrl_data * ctrl,struct nlmsghdr * n,void * arg)52*de1e4e89SAndroid Build Coastguard Worker int print_netconf(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
53*de1e4e89SAndroid Build Coastguard Worker 		  struct nlmsghdr *n, void *arg)
54*de1e4e89SAndroid Build Coastguard Worker {
55*de1e4e89SAndroid Build Coastguard Worker 	FILE *fp = (FILE *)arg;
56*de1e4e89SAndroid Build Coastguard Worker 	struct netconfmsg *ncm = NLMSG_DATA(n);
57*de1e4e89SAndroid Build Coastguard Worker 	int len = n->nlmsg_len;
58*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[NETCONFA_MAX+1];
59*de1e4e89SAndroid Build Coastguard Worker 	int ifindex = 0;
60*de1e4e89SAndroid Build Coastguard Worker 
61*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_type == NLMSG_ERROR)
62*de1e4e89SAndroid Build Coastguard Worker 		return -1;
63*de1e4e89SAndroid Build Coastguard Worker 	if (n->nlmsg_type != RTM_NEWNETCONF) {
64*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Not RTM_NEWNETCONF: %08x %08x %08x\n",
65*de1e4e89SAndroid Build Coastguard Worker 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
66*de1e4e89SAndroid Build Coastguard Worker 
67*de1e4e89SAndroid Build Coastguard Worker 		return -1;
68*de1e4e89SAndroid Build Coastguard Worker 	}
69*de1e4e89SAndroid Build Coastguard Worker 	len -= NLMSG_SPACE(sizeof(*ncm));
70*de1e4e89SAndroid Build Coastguard Worker 	if (len < 0) {
71*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
72*de1e4e89SAndroid Build Coastguard Worker 		return -1;
73*de1e4e89SAndroid Build Coastguard Worker 	}
74*de1e4e89SAndroid Build Coastguard Worker 
75*de1e4e89SAndroid Build Coastguard Worker 	if (filter.family && filter.family != ncm->ncm_family)
76*de1e4e89SAndroid Build Coastguard Worker 		return 0;
77*de1e4e89SAndroid Build Coastguard Worker 
78*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr(tb, NETCONFA_MAX, netconf_rta(ncm),
79*de1e4e89SAndroid Build Coastguard Worker 		     NLMSG_PAYLOAD(n, sizeof(*ncm)));
80*de1e4e89SAndroid Build Coastguard Worker 
81*de1e4e89SAndroid Build Coastguard Worker 	if (tb[NETCONFA_IFINDEX])
82*de1e4e89SAndroid Build Coastguard Worker 		ifindex = rta_getattr_u32(tb[NETCONFA_IFINDEX]);
83*de1e4e89SAndroid Build Coastguard Worker 
84*de1e4e89SAndroid Build Coastguard Worker 	if (filter.ifindex && filter.ifindex != ifindex)
85*de1e4e89SAndroid Build Coastguard Worker 		return 0;
86*de1e4e89SAndroid Build Coastguard Worker 
87*de1e4e89SAndroid Build Coastguard Worker 	switch (ncm->ncm_family) {
88*de1e4e89SAndroid Build Coastguard Worker 	case AF_INET:
89*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "ipv4 ");
90*de1e4e89SAndroid Build Coastguard Worker 		break;
91*de1e4e89SAndroid Build Coastguard Worker 	case AF_INET6:
92*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "ipv6 ");
93*de1e4e89SAndroid Build Coastguard Worker 		break;
94*de1e4e89SAndroid Build Coastguard Worker 	case AF_MPLS:
95*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "mpls ");
96*de1e4e89SAndroid Build Coastguard Worker 		break;
97*de1e4e89SAndroid Build Coastguard Worker 	default:
98*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "unknown ");
99*de1e4e89SAndroid Build Coastguard Worker 		break;
100*de1e4e89SAndroid Build Coastguard Worker 	}
101*de1e4e89SAndroid Build Coastguard Worker 
102*de1e4e89SAndroid Build Coastguard Worker 	if (tb[NETCONFA_IFINDEX]) {
103*de1e4e89SAndroid Build Coastguard Worker 		switch (ifindex) {
104*de1e4e89SAndroid Build Coastguard Worker 		case NETCONFA_IFINDEX_ALL:
105*de1e4e89SAndroid Build Coastguard Worker 			fprintf(fp, "all ");
106*de1e4e89SAndroid Build Coastguard Worker 			break;
107*de1e4e89SAndroid Build Coastguard Worker 		case NETCONFA_IFINDEX_DEFAULT:
108*de1e4e89SAndroid Build Coastguard Worker 			fprintf(fp, "default ");
109*de1e4e89SAndroid Build Coastguard Worker 			break;
110*de1e4e89SAndroid Build Coastguard Worker 		default:
111*de1e4e89SAndroid Build Coastguard Worker 			fprintf(fp, "dev %s ", ll_index_to_name(ifindex));
112*de1e4e89SAndroid Build Coastguard Worker 			break;
113*de1e4e89SAndroid Build Coastguard Worker 		}
114*de1e4e89SAndroid Build Coastguard Worker 	}
115*de1e4e89SAndroid Build Coastguard Worker 
116*de1e4e89SAndroid Build Coastguard Worker 	if (tb[NETCONFA_FORWARDING])
117*de1e4e89SAndroid Build Coastguard Worker 		print_onoff(fp, "forwarding",
118*de1e4e89SAndroid Build Coastguard Worker 				rta_getattr_u32(tb[NETCONFA_FORWARDING]));
119*de1e4e89SAndroid Build Coastguard Worker 	if (tb[NETCONFA_RP_FILTER]) {
120*de1e4e89SAndroid Build Coastguard Worker 		__u32 rp_filter = rta_getattr_u32(tb[NETCONFA_RP_FILTER]);
121*de1e4e89SAndroid Build Coastguard Worker 
122*de1e4e89SAndroid Build Coastguard Worker 		if (rp_filter == 0)
123*de1e4e89SAndroid Build Coastguard Worker 			fprintf(fp, "rp_filter off ");
124*de1e4e89SAndroid Build Coastguard Worker 		else if (rp_filter == 1)
125*de1e4e89SAndroid Build Coastguard Worker 			fprintf(fp, "rp_filter strict ");
126*de1e4e89SAndroid Build Coastguard Worker 		else if (rp_filter == 2)
127*de1e4e89SAndroid Build Coastguard Worker 			fprintf(fp, "rp_filter loose ");
128*de1e4e89SAndroid Build Coastguard Worker 		else
129*de1e4e89SAndroid Build Coastguard Worker 			fprintf(fp, "rp_filter unknown mode ");
130*de1e4e89SAndroid Build Coastguard Worker 	}
131*de1e4e89SAndroid Build Coastguard Worker 	if (tb[NETCONFA_MC_FORWARDING])
132*de1e4e89SAndroid Build Coastguard Worker 		print_onoff(fp, "mc_forwarding",
133*de1e4e89SAndroid Build Coastguard Worker 				rta_getattr_u32(tb[NETCONFA_MC_FORWARDING]));
134*de1e4e89SAndroid Build Coastguard Worker 
135*de1e4e89SAndroid Build Coastguard Worker 	if (tb[NETCONFA_PROXY_NEIGH])
136*de1e4e89SAndroid Build Coastguard Worker 		print_onoff(fp, "proxy_neigh",
137*de1e4e89SAndroid Build Coastguard Worker 				rta_getattr_u32(tb[NETCONFA_PROXY_NEIGH]));
138*de1e4e89SAndroid Build Coastguard Worker 
139*de1e4e89SAndroid Build Coastguard Worker 	if (tb[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN])
140*de1e4e89SAndroid Build Coastguard Worker 		print_onoff(fp, "ignore_routes_with_linkdown",
141*de1e4e89SAndroid Build Coastguard Worker 		     rta_getattr_u32(tb[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN]));
142*de1e4e89SAndroid Build Coastguard Worker 
143*de1e4e89SAndroid Build Coastguard Worker 	if (tb[NETCONFA_INPUT])
144*de1e4e89SAndroid Build Coastguard Worker 		print_onoff(fp, "input", rta_getattr_u32(tb[NETCONFA_INPUT]));
145*de1e4e89SAndroid Build Coastguard Worker 
146*de1e4e89SAndroid Build Coastguard Worker 	fprintf(fp, "\n");
147*de1e4e89SAndroid Build Coastguard Worker 	fflush(fp);
148*de1e4e89SAndroid Build Coastguard Worker 	return 0;
149*de1e4e89SAndroid Build Coastguard Worker }
150*de1e4e89SAndroid Build Coastguard Worker 
print_netconf2(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)151*de1e4e89SAndroid Build Coastguard Worker static int print_netconf2(const struct sockaddr_nl *who,
152*de1e4e89SAndroid Build Coastguard Worker 			  struct nlmsghdr *n, void *arg)
153*de1e4e89SAndroid Build Coastguard Worker {
154*de1e4e89SAndroid Build Coastguard Worker 	return print_netconf(who, NULL, n, arg);
155*de1e4e89SAndroid Build Coastguard Worker }
156*de1e4e89SAndroid Build Coastguard Worker 
ipnetconf_reset_filter(int ifindex)157*de1e4e89SAndroid Build Coastguard Worker void ipnetconf_reset_filter(int ifindex)
158*de1e4e89SAndroid Build Coastguard Worker {
159*de1e4e89SAndroid Build Coastguard Worker 	memset(&filter, 0, sizeof(filter));
160*de1e4e89SAndroid Build Coastguard Worker 	filter.ifindex = ifindex;
161*de1e4e89SAndroid Build Coastguard Worker }
162*de1e4e89SAndroid Build Coastguard Worker 
do_show(int argc,char ** argv)163*de1e4e89SAndroid Build Coastguard Worker static int do_show(int argc, char **argv)
164*de1e4e89SAndroid Build Coastguard Worker {
165*de1e4e89SAndroid Build Coastguard Worker 	struct {
166*de1e4e89SAndroid Build Coastguard Worker 		struct nlmsghdr		n;
167*de1e4e89SAndroid Build Coastguard Worker 		struct netconfmsg	ncm;
168*de1e4e89SAndroid Build Coastguard Worker 		char			buf[1024];
169*de1e4e89SAndroid Build Coastguard Worker 	} req = {
170*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct netconfmsg)),
171*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
172*de1e4e89SAndroid Build Coastguard Worker 		.n.nlmsg_type = RTM_GETNETCONF,
173*de1e4e89SAndroid Build Coastguard Worker 	};
174*de1e4e89SAndroid Build Coastguard Worker 
175*de1e4e89SAndroid Build Coastguard Worker 	ipnetconf_reset_filter(0);
176*de1e4e89SAndroid Build Coastguard Worker 	filter.family = preferred_family;
177*de1e4e89SAndroid Build Coastguard Worker 
178*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
179*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(*argv, "dev") == 0) {
180*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
181*de1e4e89SAndroid Build Coastguard Worker 			filter.ifindex = ll_name_to_index(*argv);
182*de1e4e89SAndroid Build Coastguard Worker 			if (filter.ifindex <= 0) {
183*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Device \"%s\" does not exist.\n",
184*de1e4e89SAndroid Build Coastguard Worker 					*argv);
185*de1e4e89SAndroid Build Coastguard Worker 				return -1;
186*de1e4e89SAndroid Build Coastguard Worker 			}
187*de1e4e89SAndroid Build Coastguard Worker 		}
188*de1e4e89SAndroid Build Coastguard Worker 		argv++; argc--;
189*de1e4e89SAndroid Build Coastguard Worker 	}
190*de1e4e89SAndroid Build Coastguard Worker 
191*de1e4e89SAndroid Build Coastguard Worker 	ll_init_map(&rth);
192*de1e4e89SAndroid Build Coastguard Worker 
193*de1e4e89SAndroid Build Coastguard Worker 	if (filter.ifindex && filter.family != AF_UNSPEC) {
194*de1e4e89SAndroid Build Coastguard Worker 		req.ncm.ncm_family = filter.family;
195*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(&req.n, sizeof(req), NETCONFA_IFINDEX,
196*de1e4e89SAndroid Build Coastguard Worker 			  &filter.ifindex, sizeof(filter.ifindex));
197*de1e4e89SAndroid Build Coastguard Worker 
198*de1e4e89SAndroid Build Coastguard Worker 		if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
199*de1e4e89SAndroid Build Coastguard Worker 			perror("Can not send request");
200*de1e4e89SAndroid Build Coastguard Worker 			exit(1);
201*de1e4e89SAndroid Build Coastguard Worker 		}
202*de1e4e89SAndroid Build Coastguard Worker 		rtnl_listen(&rth, print_netconf, stdout);
203*de1e4e89SAndroid Build Coastguard Worker 	} else {
204*de1e4e89SAndroid Build Coastguard Worker 		rth.flags = RTNL_HANDLE_F_SUPPRESS_NLERR;
205*de1e4e89SAndroid Build Coastguard Worker dump:
206*de1e4e89SAndroid Build Coastguard Worker 		if (rtnl_wilddump_request(&rth, filter.family, RTM_GETNETCONF) < 0) {
207*de1e4e89SAndroid Build Coastguard Worker 			perror("Cannot send dump request");
208*de1e4e89SAndroid Build Coastguard Worker 			exit(1);
209*de1e4e89SAndroid Build Coastguard Worker 		}
210*de1e4e89SAndroid Build Coastguard Worker 		if (rtnl_dump_filter(&rth, print_netconf2, stdout) < 0) {
211*de1e4e89SAndroid Build Coastguard Worker 			/* kernel does not support netconf dump on AF_UNSPEC;
212*de1e4e89SAndroid Build Coastguard Worker 			 * fall back to requesting by family
213*de1e4e89SAndroid Build Coastguard Worker 			 */
214*de1e4e89SAndroid Build Coastguard Worker 			if (errno == EOPNOTSUPP &&
215*de1e4e89SAndroid Build Coastguard Worker 			    filter.family == AF_UNSPEC) {
216*de1e4e89SAndroid Build Coastguard Worker 				filter.family = AF_INET;
217*de1e4e89SAndroid Build Coastguard Worker 				goto dump;
218*de1e4e89SAndroid Build Coastguard Worker 			}
219*de1e4e89SAndroid Build Coastguard Worker 			perror("RTNETLINK answers");
220*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Dump terminated\n");
221*de1e4e89SAndroid Build Coastguard Worker 			exit(1);
222*de1e4e89SAndroid Build Coastguard Worker 		}
223*de1e4e89SAndroid Build Coastguard Worker 		if (preferred_family == AF_UNSPEC && filter.family == AF_INET) {
224*de1e4e89SAndroid Build Coastguard Worker 			preferred_family = AF_INET6;
225*de1e4e89SAndroid Build Coastguard Worker 			filter.family = AF_INET6;
226*de1e4e89SAndroid Build Coastguard Worker 			goto dump;
227*de1e4e89SAndroid Build Coastguard Worker 		}
228*de1e4e89SAndroid Build Coastguard Worker 	}
229*de1e4e89SAndroid Build Coastguard Worker 	return 0;
230*de1e4e89SAndroid Build Coastguard Worker }
231*de1e4e89SAndroid Build Coastguard Worker 
do_ipnetconf(int argc,char ** argv)232*de1e4e89SAndroid Build Coastguard Worker int do_ipnetconf(int argc, char **argv)
233*de1e4e89SAndroid Build Coastguard Worker {
234*de1e4e89SAndroid Build Coastguard Worker 	if (argc > 0) {
235*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "show") == 0 ||
236*de1e4e89SAndroid Build Coastguard Worker 		    matches(*argv, "lst") == 0 ||
237*de1e4e89SAndroid Build Coastguard Worker 		    matches(*argv, "list") == 0)
238*de1e4e89SAndroid Build Coastguard Worker 			return do_show(argc-1, argv+1);
239*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "help") == 0)
240*de1e4e89SAndroid Build Coastguard Worker 			usage();
241*de1e4e89SAndroid Build Coastguard Worker 	} else
242*de1e4e89SAndroid Build Coastguard Worker 		return do_show(0, NULL);
243*de1e4e89SAndroid Build Coastguard Worker 
244*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip netconf help\".\n", *argv);
245*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
246*de1e4e89SAndroid Build Coastguard Worker }
247