xref: /aosp_15_r20/external/libnl/lib/route/route.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2003-2008 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @ingroup rtnl
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup route Routing
9*4dc78e53SAndroid Build Coastguard Worker  * @brief
10*4dc78e53SAndroid Build Coastguard Worker  * @{
11*4dc78e53SAndroid Build Coastguard Worker  */
12*4dc78e53SAndroid Build Coastguard Worker 
13*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
14*4dc78e53SAndroid Build Coastguard Worker 
15*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
16*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cache.h>
17*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
18*4dc78e53SAndroid Build Coastguard Worker #include <netlink/data.h>
19*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/rtnl.h>
20*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/route.h>
21*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
22*4dc78e53SAndroid Build Coastguard Worker 
23*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
24*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
25*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/cache-api.h"
26*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-route/nl-route.h"
27*4dc78e53SAndroid Build Coastguard Worker 
28*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_route_ops;
29*4dc78e53SAndroid Build Coastguard Worker 
route_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)30*4dc78e53SAndroid Build Coastguard Worker static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
31*4dc78e53SAndroid Build Coastguard Worker 			    struct nlmsghdr *nlh, struct nl_parser_param *pp)
32*4dc78e53SAndroid Build Coastguard Worker {
33*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_route *route;
34*4dc78e53SAndroid Build Coastguard Worker 	int err;
35*4dc78e53SAndroid Build Coastguard Worker 
36*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_route_parse(nlh, &route)) < 0)
37*4dc78e53SAndroid Build Coastguard Worker 		return err;
38*4dc78e53SAndroid Build Coastguard Worker 
39*4dc78e53SAndroid Build Coastguard Worker 	err = pp->pp_cb((struct nl_object *) route, pp);
40*4dc78e53SAndroid Build Coastguard Worker 
41*4dc78e53SAndroid Build Coastguard Worker 	rtnl_route_put(route);
42*4dc78e53SAndroid Build Coastguard Worker 	return err;
43*4dc78e53SAndroid Build Coastguard Worker }
44*4dc78e53SAndroid Build Coastguard Worker 
route_request_update(struct nl_cache * c,struct nl_sock * h)45*4dc78e53SAndroid Build Coastguard Worker static int route_request_update(struct nl_cache *c, struct nl_sock *h)
46*4dc78e53SAndroid Build Coastguard Worker {
47*4dc78e53SAndroid Build Coastguard Worker 	struct rtmsg rhdr = {
48*4dc78e53SAndroid Build Coastguard Worker 		.rtm_family = c->c_iarg1,
49*4dc78e53SAndroid Build Coastguard Worker 	};
50*4dc78e53SAndroid Build Coastguard Worker 
51*4dc78e53SAndroid Build Coastguard Worker 	if (c->c_iarg2 & ROUTE_CACHE_CONTENT)
52*4dc78e53SAndroid Build Coastguard Worker 		rhdr.rtm_flags |= RTM_F_CLONED;
53*4dc78e53SAndroid Build Coastguard Worker 
54*4dc78e53SAndroid Build Coastguard Worker 	return nl_send_simple(h, RTM_GETROUTE, NLM_F_DUMP, &rhdr, sizeof(rhdr));
55*4dc78e53SAndroid Build Coastguard Worker }
56*4dc78e53SAndroid Build Coastguard Worker 
57*4dc78e53SAndroid Build Coastguard Worker /**
58*4dc78e53SAndroid Build Coastguard Worker  * @name Cache Management
59*4dc78e53SAndroid Build Coastguard Worker  * @{
60*4dc78e53SAndroid Build Coastguard Worker  */
61*4dc78e53SAndroid Build Coastguard Worker 
62*4dc78e53SAndroid Build Coastguard Worker /**
63*4dc78e53SAndroid Build Coastguard Worker  * Build a route cache holding all routes currently configured in the kernel
64*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
65*4dc78e53SAndroid Build Coastguard Worker  * @arg family		Address family of routes to cover or AF_UNSPEC
66*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Flags
67*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Result pointer
68*4dc78e53SAndroid Build Coastguard Worker  *
69*4dc78e53SAndroid Build Coastguard Worker  * Allocates a new cache, initializes it properly and updates it to
70*4dc78e53SAndroid Build Coastguard Worker  * contain all routes currently configured in the kernel.
71*4dc78e53SAndroid Build Coastguard Worker  *
72*4dc78e53SAndroid Build Coastguard Worker  * Valid flags:
73*4dc78e53SAndroid Build Coastguard Worker  *   * ROUTE_CACHE_CONTENT - Cache will contain contents of routing cache
74*4dc78e53SAndroid Build Coastguard Worker  *                           instead of actual routes.
75*4dc78e53SAndroid Build Coastguard Worker  *
76*4dc78e53SAndroid Build Coastguard Worker  * @note The caller is responsible for destroying and freeing the
77*4dc78e53SAndroid Build Coastguard Worker  *       cache after using it.
78*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
79*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_route_alloc_cache(struct nl_sock * sk,int family,int flags,struct nl_cache ** result)80*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_alloc_cache(struct nl_sock *sk, int family, int flags,
81*4dc78e53SAndroid Build Coastguard Worker 			   struct nl_cache **result)
82*4dc78e53SAndroid Build Coastguard Worker {
83*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache;
84*4dc78e53SAndroid Build Coastguard Worker 	int err;
85*4dc78e53SAndroid Build Coastguard Worker 
86*4dc78e53SAndroid Build Coastguard Worker 	if (!(cache = nl_cache_alloc(&rtnl_route_ops)))
87*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
88*4dc78e53SAndroid Build Coastguard Worker 
89*4dc78e53SAndroid Build Coastguard Worker 	cache->c_iarg1 = family;
90*4dc78e53SAndroid Build Coastguard Worker 	cache->c_iarg2 = flags;
91*4dc78e53SAndroid Build Coastguard Worker 
92*4dc78e53SAndroid Build Coastguard Worker 	if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
93*4dc78e53SAndroid Build Coastguard Worker 		free(cache);
94*4dc78e53SAndroid Build Coastguard Worker 		return err;
95*4dc78e53SAndroid Build Coastguard Worker 	}
96*4dc78e53SAndroid Build Coastguard Worker 
97*4dc78e53SAndroid Build Coastguard Worker 	*result = cache;
98*4dc78e53SAndroid Build Coastguard Worker 	return 0;
99*4dc78e53SAndroid Build Coastguard Worker }
100*4dc78e53SAndroid Build Coastguard Worker 
101*4dc78e53SAndroid Build Coastguard Worker /** @} */
102*4dc78e53SAndroid Build Coastguard Worker 
103*4dc78e53SAndroid Build Coastguard Worker /**
104*4dc78e53SAndroid Build Coastguard Worker  * @name Route Addition
105*4dc78e53SAndroid Build Coastguard Worker  * @{
106*4dc78e53SAndroid Build Coastguard Worker  */
107*4dc78e53SAndroid Build Coastguard Worker 
build_route_msg(struct rtnl_route * tmpl,int cmd,int flags,struct nl_msg ** result)108*4dc78e53SAndroid Build Coastguard Worker static int build_route_msg(struct rtnl_route *tmpl, int cmd, int flags,
109*4dc78e53SAndroid Build Coastguard Worker 			   struct nl_msg **result)
110*4dc78e53SAndroid Build Coastguard Worker {
111*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
112*4dc78e53SAndroid Build Coastguard Worker 	int err;
113*4dc78e53SAndroid Build Coastguard Worker 
114*4dc78e53SAndroid Build Coastguard Worker 	if (!(msg = nlmsg_alloc_simple(cmd, flags)))
115*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
116*4dc78e53SAndroid Build Coastguard Worker 
117*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_route_build_msg(msg, tmpl)) < 0) {
118*4dc78e53SAndroid Build Coastguard Worker 		nlmsg_free(msg);
119*4dc78e53SAndroid Build Coastguard Worker 		return err;
120*4dc78e53SAndroid Build Coastguard Worker 	}
121*4dc78e53SAndroid Build Coastguard Worker 
122*4dc78e53SAndroid Build Coastguard Worker 	*result = msg;
123*4dc78e53SAndroid Build Coastguard Worker 	return 0;
124*4dc78e53SAndroid Build Coastguard Worker }
125*4dc78e53SAndroid Build Coastguard Worker 
rtnl_route_build_add_request(struct rtnl_route * tmpl,int flags,struct nl_msg ** result)126*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags,
127*4dc78e53SAndroid Build Coastguard Worker 				 struct nl_msg **result)
128*4dc78e53SAndroid Build Coastguard Worker {
129*4dc78e53SAndroid Build Coastguard Worker 	return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags,
130*4dc78e53SAndroid Build Coastguard Worker 			       result);
131*4dc78e53SAndroid Build Coastguard Worker }
132*4dc78e53SAndroid Build Coastguard Worker 
rtnl_route_lookup(struct nl_sock * sk,struct nl_addr * dst,struct rtnl_route ** result)133*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_lookup(struct nl_sock *sk, struct nl_addr *dst,
134*4dc78e53SAndroid Build Coastguard Worker                       struct rtnl_route **result)
135*4dc78e53SAndroid Build Coastguard Worker {
136*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_msg struct nl_msg *msg = NULL;
137*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_route struct rtnl_route *tmpl = NULL;
138*4dc78e53SAndroid Build Coastguard Worker 	struct nl_object *obj;
139*4dc78e53SAndroid Build Coastguard Worker 	int err;
140*4dc78e53SAndroid Build Coastguard Worker 
141*4dc78e53SAndroid Build Coastguard Worker 	tmpl = rtnl_route_alloc();
142*4dc78e53SAndroid Build Coastguard Worker 	rtnl_route_set_dst(tmpl, dst);
143*4dc78e53SAndroid Build Coastguard Worker 	err = build_route_msg(tmpl, RTM_GETROUTE, 0, &msg);
144*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
145*4dc78e53SAndroid Build Coastguard Worker 		return err;
146*4dc78e53SAndroid Build Coastguard Worker 
147*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto(sk, msg);
148*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
149*4dc78e53SAndroid Build Coastguard Worker 		return err;
150*4dc78e53SAndroid Build Coastguard Worker 
151*4dc78e53SAndroid Build Coastguard Worker 	if ((err = nl_pickup(sk, route_msg_parser, &obj)) < 0)
152*4dc78e53SAndroid Build Coastguard Worker 		return err;
153*4dc78e53SAndroid Build Coastguard Worker 
154*4dc78e53SAndroid Build Coastguard Worker 	*result = (struct rtnl_route *)obj;
155*4dc78e53SAndroid Build Coastguard Worker 	wait_for_ack(sk);
156*4dc78e53SAndroid Build Coastguard Worker 	return 0;
157*4dc78e53SAndroid Build Coastguard Worker }
158*4dc78e53SAndroid Build Coastguard Worker 
rtnl_route_add(struct nl_sock * sk,struct rtnl_route * route,int flags)159*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_add(struct nl_sock *sk, struct rtnl_route *route, int flags)
160*4dc78e53SAndroid Build Coastguard Worker {
161*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
162*4dc78e53SAndroid Build Coastguard Worker 	int err;
163*4dc78e53SAndroid Build Coastguard Worker 
164*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_route_build_add_request(route, flags, &msg)) < 0)
165*4dc78e53SAndroid Build Coastguard Worker 		return err;
166*4dc78e53SAndroid Build Coastguard Worker 
167*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto_complete(sk, msg);
168*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
169*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
170*4dc78e53SAndroid Build Coastguard Worker 		return err;
171*4dc78e53SAndroid Build Coastguard Worker 
172*4dc78e53SAndroid Build Coastguard Worker 	return wait_for_ack(sk);
173*4dc78e53SAndroid Build Coastguard Worker }
174*4dc78e53SAndroid Build Coastguard Worker 
rtnl_route_build_del_request(struct rtnl_route * tmpl,int flags,struct nl_msg ** result)175*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags,
176*4dc78e53SAndroid Build Coastguard Worker 				 struct nl_msg **result)
177*4dc78e53SAndroid Build Coastguard Worker {
178*4dc78e53SAndroid Build Coastguard Worker 	return build_route_msg(tmpl, RTM_DELROUTE, flags, result);
179*4dc78e53SAndroid Build Coastguard Worker }
180*4dc78e53SAndroid Build Coastguard Worker 
rtnl_route_delete(struct nl_sock * sk,struct rtnl_route * route,int flags)181*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_delete(struct nl_sock *sk, struct rtnl_route *route, int flags)
182*4dc78e53SAndroid Build Coastguard Worker {
183*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
184*4dc78e53SAndroid Build Coastguard Worker 	int err;
185*4dc78e53SAndroid Build Coastguard Worker 
186*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_route_build_del_request(route, flags, &msg)) < 0)
187*4dc78e53SAndroid Build Coastguard Worker 		return err;
188*4dc78e53SAndroid Build Coastguard Worker 
189*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto_complete(sk, msg);
190*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
191*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
192*4dc78e53SAndroid Build Coastguard Worker 		return err;
193*4dc78e53SAndroid Build Coastguard Worker 
194*4dc78e53SAndroid Build Coastguard Worker 	return wait_for_ack(sk);
195*4dc78e53SAndroid Build Coastguard Worker }
196*4dc78e53SAndroid Build Coastguard Worker 
197*4dc78e53SAndroid Build Coastguard Worker /** @} */
198*4dc78e53SAndroid Build Coastguard Worker 
199*4dc78e53SAndroid Build Coastguard Worker static struct nl_af_group route_groups[] = {
200*4dc78e53SAndroid Build Coastguard Worker 	{ AF_INET,	RTNLGRP_IPV4_ROUTE },
201*4dc78e53SAndroid Build Coastguard Worker 	{ AF_INET6,	RTNLGRP_IPV6_ROUTE },
202*4dc78e53SAndroid Build Coastguard Worker 	{ AF_MPLS,	RTNLGRP_MPLS_ROUTE },
203*4dc78e53SAndroid Build Coastguard Worker 	{ AF_DECnet,	RTNLGRP_DECnet_ROUTE },
204*4dc78e53SAndroid Build Coastguard Worker 	{ END_OF_GROUP_LIST },
205*4dc78e53SAndroid Build Coastguard Worker };
206*4dc78e53SAndroid Build Coastguard Worker 
207*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_route_ops = {
208*4dc78e53SAndroid Build Coastguard Worker 	.co_name		= "route/route",
209*4dc78e53SAndroid Build Coastguard Worker 	.co_hdrsize		= sizeof(struct rtmsg),
210*4dc78e53SAndroid Build Coastguard Worker 	.co_msgtypes		= {
211*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_NEWROUTE, NL_ACT_NEW, "new" },
212*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_DELROUTE, NL_ACT_DEL, "del" },
213*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_GETROUTE, NL_ACT_GET, "get" },
214*4dc78e53SAndroid Build Coastguard Worker 					END_OF_MSGTYPES_LIST,
215*4dc78e53SAndroid Build Coastguard Worker 				  },
216*4dc78e53SAndroid Build Coastguard Worker 	.co_protocol		= NETLINK_ROUTE,
217*4dc78e53SAndroid Build Coastguard Worker 	.co_groups		= route_groups,
218*4dc78e53SAndroid Build Coastguard Worker 	.co_request_update	= route_request_update,
219*4dc78e53SAndroid Build Coastguard Worker 	.co_msg_parser		= route_msg_parser,
220*4dc78e53SAndroid Build Coastguard Worker 	.co_obj_ops		= &route_obj_ops,
221*4dc78e53SAndroid Build Coastguard Worker };
222*4dc78e53SAndroid Build Coastguard Worker 
route_init(void)223*4dc78e53SAndroid Build Coastguard Worker static void _nl_init route_init(void)
224*4dc78e53SAndroid Build Coastguard Worker {
225*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_register(&rtnl_route_ops);
226*4dc78e53SAndroid Build Coastguard Worker }
227*4dc78e53SAndroid Build Coastguard Worker 
route_exit(void)228*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit route_exit(void)
229*4dc78e53SAndroid Build Coastguard Worker {
230*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_unregister(&rtnl_route_ops);
231*4dc78e53SAndroid Build Coastguard Worker }
232*4dc78e53SAndroid Build Coastguard Worker 
233*4dc78e53SAndroid Build Coastguard Worker /** @} */
234