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