19 #include <netlink-local.h>
20 #include <netlink/netlink.h>
21 #include <netlink/cache.h>
22 #include <netlink/utils.h>
23 #include <netlink/data.h>
24 #include <netlink/route/rtnl.h>
25 #include <netlink/route/route.h>
26 #include <netlink/route/link.h>
30 static struct nla_policy route_policy[RTA_MAX+1] = {
32 .maxlen = IFNAMSIZ, },
33 [RTA_OIF] = { .type =
NLA_U32 },
34 [RTA_PRIORITY] = { .type =
NLA_U32 },
35 [RTA_FLOW] = { .type =
NLA_U32 },
36 [RTA_MP_ALGO] = { .type =
NLA_U32 },
37 [RTA_CACHEINFO] = { .minlen =
sizeof(
struct rta_cacheinfo) },
42 static void copy_cacheinfo_into_route(
struct rta_cacheinfo *ci,
43 struct rtnl_route *route)
46 .rtci_clntref = ci->rta_clntref,
47 .rtci_last_use = ci->rta_lastuse,
48 .rtci_expires = ci->rta_expires,
49 .rtci_error = ci->rta_error,
50 .rtci_used = ci->rta_used,
51 .rtci_id = ci->rta_id,
52 .rtci_ts = ci->rta_ts,
53 .rtci_tsage = ci->rta_tsage,
56 rtnl_route_set_cacheinfo(route, &nci);
63 struct rtnl_route *route;
64 struct nlattr *tb[RTA_MAX + 1];
65 struct nl_addr *src = NULL, *dst = NULL, *addr;
68 route = rtnl_route_alloc();
70 err = nl_errno(ENOMEM);
76 err =
nlmsg_parse(nlh,
sizeof(
struct rtmsg), tb, RTA_MAX,
82 rtnl_route_set_family(route, rtm->rtm_family);
83 rtnl_route_set_tos(route, rtm->rtm_tos);
84 rtnl_route_set_table(route, rtm->rtm_table);
85 rtnl_route_set_type(route, rtm->rtm_type);
86 rtnl_route_set_scope(route, rtm->rtm_scope);
87 rtnl_route_set_protocol(route, rtm->rtm_protocol);
88 rtnl_route_set_flags(route, rtm->rtm_flags);
96 nl_addr_set_family(dst, rtm->rtm_family);
99 nl_addr_set_prefixlen(dst, rtm->rtm_dst_len);
100 err = rtnl_route_set_dst(route, dst);
110 }
else if (rtm->rtm_src_len)
114 nl_addr_set_prefixlen(src, rtm->rtm_src_len);
115 rtnl_route_set_src(route, src);
123 rtnl_route_set_oif(route,
nla_get_u32(tb[RTA_OIF]));
125 if (tb[RTA_GATEWAY]) {
129 rtnl_route_set_gateway(route, addr);
133 if (tb[RTA_PRIORITY])
134 rtnl_route_set_prio(route,
nla_get_u32(tb[RTA_PRIORITY]));
136 if (tb[RTA_PREFSRC]) {
140 rtnl_route_set_pref_src(route, addr);
144 if (tb[RTA_METRICS]) {
145 struct nlattr *mtb[RTAX_MAX + 1];
152 for (i = 1; i <= RTAX_MAX; i++) {
153 if (mtb[i] &&
nla_len(mtb[i]) >=
sizeof(uint32_t)) {
155 if (rtnl_route_set_metric(route, i, m) < 0)
161 if (tb[RTA_MULTIPATH]) {
162 struct rtnl_nexthop *nh;
163 struct rtnexthop *rtnh =
nla_data(tb[RTA_MULTIPATH]);
164 size_t tlen =
nla_len(tb[RTA_MULTIPATH]);
166 while (tlen >=
sizeof(*rtnh) && tlen >= rtnh->rtnh_len) {
167 nh = rtnl_route_nh_alloc();
171 rtnl_route_nh_set_weight(nh, rtnh->rtnh_hops);
172 rtnl_route_nh_set_ifindex(nh, rtnh->rtnh_ifindex);
173 rtnl_route_nh_set_flags(nh, rtnh->rtnh_flags);
175 if (rtnh->rtnh_len >
sizeof(*rtnh)) {
176 struct nlattr *ntb[RTA_MAX + 1];
177 nla_parse(ntb, RTA_MAX, (
struct nlattr *)
179 rtnh->rtnh_len -
sizeof(*rtnh),
182 if (ntb[RTA_GATEWAY]) {
186 nh->rtnh_mask = NEXTHOP_HAS_GATEWAY;
190 rtnl_route_add_nexthop(route, nh);
191 tlen -= RTNH_ALIGN(rtnh->rtnh_len);
192 rtnh = RTNH_NEXT(rtnh);
197 rtnl_route_set_realms(route,
nla_get_u32(tb[RTA_FLOW]));
199 if (tb[RTA_CACHEINFO])
200 copy_cacheinfo_into_route(
nla_data(tb[RTA_CACHEINFO]), route);
203 rtnl_route_set_mp_algo(route,
nla_get_u32(tb[RTA_MP_ALGO]));
205 err = pp->pp_cb((
struct nl_object *) route, pp);
212 rtnl_route_put(route);
216 err = nl_get_errno();
220 static int route_request_update(
struct nl_cache *c,
struct nl_handle *h)
243 struct nl_cache *cache;
264 static struct nl_msg *build_route_msg(
struct rtnl_route *tmpl,
int cmd,
268 struct nl_addr *addr;
269 int scope, i, oif, nmetrics = 0;
270 struct nlattr *metrics;
271 struct rtmsg rtmsg = {
272 .rtm_family = rtnl_route_get_family(tmpl),
273 .rtm_dst_len = rtnl_route_get_dst_len(tmpl),
274 .rtm_src_len = rtnl_route_get_src_len(tmpl),
275 .rtm_tos = rtnl_route_get_tos(tmpl),
276 .rtm_table = rtnl_route_get_table(tmpl),
277 .rtm_type = rtnl_route_get_type(tmpl),
278 .rtm_protocol = rtnl_route_get_protocol(tmpl),
279 .rtm_flags = rtnl_route_get_flags(tmpl),
282 if (rtmsg.rtm_family == AF_UNSPEC) {
283 nl_error(EINVAL,
"Cannot build route message, address " \
284 "family is unknown.");
288 scope = rtnl_route_get_scope(tmpl);
289 if (scope == RT_SCOPE_NOWHERE) {
290 if (rtmsg.rtm_type == RTN_LOCAL)
291 scope = RT_SCOPE_HOST;
294 scope = RT_SCOPE_LINK;
298 rtmsg.rtm_scope = scope;
304 if (
nlmsg_append(msg, &rtmsg,
sizeof(rtmsg), NLMSG_ALIGNTO) < 0)
305 goto nla_put_failure;
307 addr = rtnl_route_get_dst(tmpl);
311 addr = rtnl_route_get_src(tmpl);
315 addr = rtnl_route_get_gateway(tmpl);
319 addr = rtnl_route_get_pref_src(tmpl);
323 NLA_PUT_U32(msg, RTA_PRIORITY, rtnl_route_get_prio(tmpl));
325 oif = rtnl_route_get_oif(tmpl);
329 for (i = 1; i <= RTAX_MAX; i++)
330 if (rtnl_route_get_metric(tmpl, i) != UINT_MAX)
338 goto nla_put_failure;
340 for (i = 1; i <= RTAX_MAX; i++) {
341 val = rtnl_route_get_metric(tmpl, i);
366 struct nl_msg *rtnl_route_build_add_request(
struct rtnl_route *tmpl,
int flags)
368 return build_route_msg(tmpl, RTM_NEWROUTE,
NLM_F_CREATE | flags);
371 int rtnl_route_add(
struct nl_handle *handle,
struct rtnl_route *route,
377 msg = rtnl_route_build_add_request(route, flags);
379 return nl_get_errno();
389 struct nl_msg *rtnl_route_build_del_request(
struct rtnl_route *tmpl,
int flags)
391 return build_route_msg(tmpl, RTM_DELROUTE, flags);
394 int rtnl_route_del(
struct nl_handle *handle,
struct rtnl_route *route,
400 msg = rtnl_route_build_del_request(route, flags);
402 return nl_get_errno();
415 { AF_INET, RTNLGRP_IPV4_ROUTE },
416 { AF_INET6, RTNLGRP_IPV6_ROUTE },
417 { AF_DECnet, RTNLGRP_DECnet_ROUTE },
418 { END_OF_GROUP_LIST },
422 .co_name =
"route/route",
423 .co_hdrsize =
sizeof(
struct rtmsg),
425 { RTM_NEWROUTE, NL_ACT_NEW,
"new" },
426 { RTM_DELROUTE, NL_ACT_DEL,
"del" },
427 { RTM_GETROUTE, NL_ACT_GET,
"get" },
428 END_OF_MSGTYPES_LIST,
430 .co_protocol = NETLINK_ROUTE,
431 .co_groups = route_groups,
432 .co_request_update = route_request_update,
433 .co_msg_parser = route_msg_parser,
434 .co_obj_ops = &route_obj_ops,
437 static void __init route_init(
void)
442 static void __exit route_exit(
void)