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 route_obj
8*4dc78e53SAndroid Build Coastguard Worker * @defgroup nexthop Nexthop
9*4dc78e53SAndroid Build Coastguard Worker * @{
10*4dc78e53SAndroid Build Coastguard Worker */
11*4dc78e53SAndroid Build Coastguard Worker
12*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
13*4dc78e53SAndroid Build Coastguard Worker
14*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
15*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
16*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/rtnl.h>
17*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/route.h>
18*4dc78e53SAndroid Build Coastguard Worker
19*4dc78e53SAndroid Build Coastguard Worker #include "nexthop-encap.h"
20*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
21*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
22*4dc78e53SAndroid Build Coastguard Worker
23*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
24*4dc78e53SAndroid Build Coastguard Worker #define NH_ATTR_FLAGS 0x000001
25*4dc78e53SAndroid Build Coastguard Worker #define NH_ATTR_WEIGHT 0x000002
26*4dc78e53SAndroid Build Coastguard Worker #define NH_ATTR_IFINDEX 0x000004
27*4dc78e53SAndroid Build Coastguard Worker #define NH_ATTR_GATEWAY 0x000008
28*4dc78e53SAndroid Build Coastguard Worker #define NH_ATTR_REALMS 0x000010
29*4dc78e53SAndroid Build Coastguard Worker #define NH_ATTR_NEWDST 0x000020
30*4dc78e53SAndroid Build Coastguard Worker #define NH_ATTR_VIA 0x000040
31*4dc78e53SAndroid Build Coastguard Worker #define NH_ATTR_ENCAP 0x000080
32*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
33*4dc78e53SAndroid Build Coastguard Worker
34*4dc78e53SAndroid Build Coastguard Worker /**
35*4dc78e53SAndroid Build Coastguard Worker * @name Allocation/Freeing
36*4dc78e53SAndroid Build Coastguard Worker * @{
37*4dc78e53SAndroid Build Coastguard Worker */
38*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_alloc(void)39*4dc78e53SAndroid Build Coastguard Worker struct rtnl_nexthop *rtnl_route_nh_alloc(void)
40*4dc78e53SAndroid Build Coastguard Worker {
41*4dc78e53SAndroid Build Coastguard Worker struct rtnl_nexthop *nh;
42*4dc78e53SAndroid Build Coastguard Worker
43*4dc78e53SAndroid Build Coastguard Worker nh = calloc(1, sizeof(*nh));
44*4dc78e53SAndroid Build Coastguard Worker if (!nh)
45*4dc78e53SAndroid Build Coastguard Worker return NULL;
46*4dc78e53SAndroid Build Coastguard Worker
47*4dc78e53SAndroid Build Coastguard Worker nl_init_list_head(&nh->rtnh_list);
48*4dc78e53SAndroid Build Coastguard Worker
49*4dc78e53SAndroid Build Coastguard Worker return nh;
50*4dc78e53SAndroid Build Coastguard Worker }
51*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_clone(struct rtnl_nexthop * src)52*4dc78e53SAndroid Build Coastguard Worker struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src)
53*4dc78e53SAndroid Build Coastguard Worker {
54*4dc78e53SAndroid Build Coastguard Worker struct rtnl_nexthop *nh;
55*4dc78e53SAndroid Build Coastguard Worker
56*4dc78e53SAndroid Build Coastguard Worker nh = rtnl_route_nh_alloc();
57*4dc78e53SAndroid Build Coastguard Worker if (!nh)
58*4dc78e53SAndroid Build Coastguard Worker return NULL;
59*4dc78e53SAndroid Build Coastguard Worker
60*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_flags = src->rtnh_flags;
61*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_flag_mask = src->rtnh_flag_mask;
62*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_weight = src->rtnh_weight;
63*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_ifindex = src->rtnh_ifindex;
64*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask = src->ce_mask;
65*4dc78e53SAndroid Build Coastguard Worker
66*4dc78e53SAndroid Build Coastguard Worker if (src->rtnh_gateway) {
67*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_gateway = nl_addr_clone(src->rtnh_gateway);
68*4dc78e53SAndroid Build Coastguard Worker if (!nh->rtnh_gateway) {
69*4dc78e53SAndroid Build Coastguard Worker free(nh);
70*4dc78e53SAndroid Build Coastguard Worker return NULL;
71*4dc78e53SAndroid Build Coastguard Worker }
72*4dc78e53SAndroid Build Coastguard Worker }
73*4dc78e53SAndroid Build Coastguard Worker
74*4dc78e53SAndroid Build Coastguard Worker if (src->rtnh_newdst) {
75*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_newdst = nl_addr_clone(src->rtnh_newdst);
76*4dc78e53SAndroid Build Coastguard Worker if (!nh->rtnh_newdst) {
77*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(nh->rtnh_gateway);
78*4dc78e53SAndroid Build Coastguard Worker free(nh);
79*4dc78e53SAndroid Build Coastguard Worker return NULL;
80*4dc78e53SAndroid Build Coastguard Worker }
81*4dc78e53SAndroid Build Coastguard Worker }
82*4dc78e53SAndroid Build Coastguard Worker
83*4dc78e53SAndroid Build Coastguard Worker if (src->rtnh_via) {
84*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_via = nl_addr_clone(src->rtnh_via);
85*4dc78e53SAndroid Build Coastguard Worker if (!nh->rtnh_via) {
86*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(nh->rtnh_gateway);
87*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(nh->rtnh_newdst);
88*4dc78e53SAndroid Build Coastguard Worker free(nh);
89*4dc78e53SAndroid Build Coastguard Worker return NULL;
90*4dc78e53SAndroid Build Coastguard Worker }
91*4dc78e53SAndroid Build Coastguard Worker }
92*4dc78e53SAndroid Build Coastguard Worker
93*4dc78e53SAndroid Build Coastguard Worker return nh;
94*4dc78e53SAndroid Build Coastguard Worker }
95*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_free(struct rtnl_nexthop * nh)96*4dc78e53SAndroid Build Coastguard Worker void rtnl_route_nh_free(struct rtnl_nexthop *nh)
97*4dc78e53SAndroid Build Coastguard Worker {
98*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(nh->rtnh_gateway);
99*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(nh->rtnh_newdst);
100*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(nh->rtnh_via);
101*4dc78e53SAndroid Build Coastguard Worker if (nh->rtnh_encap) {
102*4dc78e53SAndroid Build Coastguard Worker if (nh->rtnh_encap->ops && nh->rtnh_encap->ops->destructor)
103*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_encap->ops->destructor(nh->rtnh_encap->priv);
104*4dc78e53SAndroid Build Coastguard Worker free(nh->rtnh_encap->priv);
105*4dc78e53SAndroid Build Coastguard Worker free(nh->rtnh_encap);
106*4dc78e53SAndroid Build Coastguard Worker }
107*4dc78e53SAndroid Build Coastguard Worker free(nh);
108*4dc78e53SAndroid Build Coastguard Worker }
109*4dc78e53SAndroid Build Coastguard Worker
110*4dc78e53SAndroid Build Coastguard Worker /** @} */
111*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_compare(struct rtnl_nexthop * a,struct rtnl_nexthop * b,uint32_t attrs,int loose)112*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b,
113*4dc78e53SAndroid Build Coastguard Worker uint32_t attrs, int loose)
114*4dc78e53SAndroid Build Coastguard Worker {
115*4dc78e53SAndroid Build Coastguard Worker uint32_t diff = 0;
116*4dc78e53SAndroid Build Coastguard Worker
117*4dc78e53SAndroid Build Coastguard Worker #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
118*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
119*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_WEIGHT, a->rtnh_weight != b->rtnh_weight);
120*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_REALMS, a->rtnh_realms != b->rtnh_realms);
121*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_GATEWAY,
122*4dc78e53SAndroid Build Coastguard Worker nl_addr_cmp(a->rtnh_gateway, b->rtnh_gateway));
123*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_NEWDST,
124*4dc78e53SAndroid Build Coastguard Worker nl_addr_cmp(a->rtnh_newdst, b->rtnh_newdst));
125*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_VIA, nl_addr_cmp(a->rtnh_via, b->rtnh_via));
126*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_ENCAP,
127*4dc78e53SAndroid Build Coastguard Worker nh_encap_compare(a->rtnh_encap, b->rtnh_encap));
128*4dc78e53SAndroid Build Coastguard Worker
129*4dc78e53SAndroid Build Coastguard Worker if (loose)
130*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_FLAGS, (a->rtnh_flags ^ b->rtnh_flags) &
131*4dc78e53SAndroid Build Coastguard Worker b->rtnh_flag_mask);
132*4dc78e53SAndroid Build Coastguard Worker else
133*4dc78e53SAndroid Build Coastguard Worker diff |= _DIFF(NH_ATTR_FLAGS, a->rtnh_flags != b->rtnh_flags);
134*4dc78e53SAndroid Build Coastguard Worker #undef _DIFF
135*4dc78e53SAndroid Build Coastguard Worker
136*4dc78e53SAndroid Build Coastguard Worker return diff;
137*4dc78e53SAndroid Build Coastguard Worker }
138*4dc78e53SAndroid Build Coastguard Worker
139*4dc78e53SAndroid Build Coastguard Worker /**
140*4dc78e53SAndroid Build Coastguard Worker * Check if the fixed attributes of two nexthops are identical, and may
141*4dc78e53SAndroid Build Coastguard Worker * only differ in flags or weight.
142*4dc78e53SAndroid Build Coastguard Worker *
143*4dc78e53SAndroid Build Coastguard Worker * @arg a a nexthop
144*4dc78e53SAndroid Build Coastguard Worker * @arg b another nexthop
145*4dc78e53SAndroid Build Coastguard Worker *
146*4dc78e53SAndroid Build Coastguard Worker * @return true if both nexthop have equal attributes, otherwise false.
147*4dc78e53SAndroid Build Coastguard Worker */
rtnl_route_nh_identical(struct rtnl_nexthop * a,struct rtnl_nexthop * b)148*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_nh_identical(struct rtnl_nexthop *a, struct rtnl_nexthop *b)
149*4dc78e53SAndroid Build Coastguard Worker {
150*4dc78e53SAndroid Build Coastguard Worker return !rtnl_route_nh_compare(a, b,
151*4dc78e53SAndroid Build Coastguard Worker NH_ATTR_IFINDEX | NH_ATTR_REALMS |
152*4dc78e53SAndroid Build Coastguard Worker NH_ATTR_GATEWAY | NH_ATTR_NEWDST |
153*4dc78e53SAndroid Build Coastguard Worker NH_ATTR_VIA | NH_ATTR_ENCAP, 0);
154*4dc78e53SAndroid Build Coastguard Worker }
155*4dc78e53SAndroid Build Coastguard Worker
nh_dump_line(struct rtnl_nexthop * nh,struct nl_dump_params * dp)156*4dc78e53SAndroid Build Coastguard Worker static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
157*4dc78e53SAndroid Build Coastguard Worker {
158*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *link_cache;
159*4dc78e53SAndroid Build Coastguard Worker char buf[128];
160*4dc78e53SAndroid Build Coastguard Worker
161*4dc78e53SAndroid Build Coastguard Worker link_cache = nl_cache_mngt_require_safe("route/link");
162*4dc78e53SAndroid Build Coastguard Worker
163*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_ENCAP)
164*4dc78e53SAndroid Build Coastguard Worker nh_encap_dump(nh->rtnh_encap, dp);
165*4dc78e53SAndroid Build Coastguard Worker
166*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_NEWDST)
167*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, "as to %s ",
168*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(nh->rtnh_newdst, buf, sizeof(buf)));
169*4dc78e53SAndroid Build Coastguard Worker
170*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, "via");
171*4dc78e53SAndroid Build Coastguard Worker
172*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_VIA)
173*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " %s",
174*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(nh->rtnh_via, buf, sizeof(buf)));
175*4dc78e53SAndroid Build Coastguard Worker
176*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_GATEWAY)
177*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " %s", nl_addr2str(nh->rtnh_gateway,
178*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
179*4dc78e53SAndroid Build Coastguard Worker
180*4dc78e53SAndroid Build Coastguard Worker if(nh->ce_mask & NH_ATTR_IFINDEX) {
181*4dc78e53SAndroid Build Coastguard Worker if (link_cache) {
182*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " dev %s",
183*4dc78e53SAndroid Build Coastguard Worker rtnl_link_i2name(link_cache,
184*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_ifindex,
185*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
186*4dc78e53SAndroid Build Coastguard Worker } else
187*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " dev %d", nh->rtnh_ifindex);
188*4dc78e53SAndroid Build Coastguard Worker }
189*4dc78e53SAndroid Build Coastguard Worker
190*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " ");
191*4dc78e53SAndroid Build Coastguard Worker
192*4dc78e53SAndroid Build Coastguard Worker if (link_cache)
193*4dc78e53SAndroid Build Coastguard Worker nl_cache_put(link_cache);
194*4dc78e53SAndroid Build Coastguard Worker }
195*4dc78e53SAndroid Build Coastguard Worker
nh_dump_details(struct rtnl_nexthop * nh,struct nl_dump_params * dp)196*4dc78e53SAndroid Build Coastguard Worker static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
197*4dc78e53SAndroid Build Coastguard Worker {
198*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *link_cache;
199*4dc78e53SAndroid Build Coastguard Worker char buf[128];
200*4dc78e53SAndroid Build Coastguard Worker
201*4dc78e53SAndroid Build Coastguard Worker link_cache = nl_cache_mngt_require_safe("route/link");
202*4dc78e53SAndroid Build Coastguard Worker
203*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, "nexthop");
204*4dc78e53SAndroid Build Coastguard Worker
205*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_ENCAP)
206*4dc78e53SAndroid Build Coastguard Worker nh_encap_dump(nh->rtnh_encap, dp);
207*4dc78e53SAndroid Build Coastguard Worker
208*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_NEWDST)
209*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " as to %s",
210*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(nh->rtnh_newdst, buf, sizeof(buf)));
211*4dc78e53SAndroid Build Coastguard Worker
212*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_VIA)
213*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " via %s",
214*4dc78e53SAndroid Build Coastguard Worker nl_addr2str(nh->rtnh_via, buf, sizeof(buf)));
215*4dc78e53SAndroid Build Coastguard Worker
216*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_GATEWAY)
217*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway,
218*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
219*4dc78e53SAndroid Build Coastguard Worker
220*4dc78e53SAndroid Build Coastguard Worker if(nh->ce_mask & NH_ATTR_IFINDEX) {
221*4dc78e53SAndroid Build Coastguard Worker if (link_cache) {
222*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " dev %s",
223*4dc78e53SAndroid Build Coastguard Worker rtnl_link_i2name(link_cache,
224*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_ifindex,
225*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
226*4dc78e53SAndroid Build Coastguard Worker } else
227*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " dev %d", nh->rtnh_ifindex);
228*4dc78e53SAndroid Build Coastguard Worker }
229*4dc78e53SAndroid Build Coastguard Worker
230*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_WEIGHT)
231*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " weight %u", nh->rtnh_weight);
232*4dc78e53SAndroid Build Coastguard Worker
233*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_REALMS)
234*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " realm %04x:%04x",
235*4dc78e53SAndroid Build Coastguard Worker RTNL_REALM_FROM(nh->rtnh_realms),
236*4dc78e53SAndroid Build Coastguard Worker RTNL_REALM_TO(nh->rtnh_realms));
237*4dc78e53SAndroid Build Coastguard Worker
238*4dc78e53SAndroid Build Coastguard Worker if (nh->ce_mask & NH_ATTR_FLAGS)
239*4dc78e53SAndroid Build Coastguard Worker nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags,
240*4dc78e53SAndroid Build Coastguard Worker buf, sizeof(buf)));
241*4dc78e53SAndroid Build Coastguard Worker
242*4dc78e53SAndroid Build Coastguard Worker if (link_cache)
243*4dc78e53SAndroid Build Coastguard Worker nl_cache_put(link_cache);
244*4dc78e53SAndroid Build Coastguard Worker }
245*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_dump(struct rtnl_nexthop * nh,struct nl_dump_params * dp)246*4dc78e53SAndroid Build Coastguard Worker void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
247*4dc78e53SAndroid Build Coastguard Worker {
248*4dc78e53SAndroid Build Coastguard Worker switch (dp->dp_type) {
249*4dc78e53SAndroid Build Coastguard Worker case NL_DUMP_LINE:
250*4dc78e53SAndroid Build Coastguard Worker nh_dump_line(nh, dp);
251*4dc78e53SAndroid Build Coastguard Worker break;
252*4dc78e53SAndroid Build Coastguard Worker
253*4dc78e53SAndroid Build Coastguard Worker case NL_DUMP_DETAILS:
254*4dc78e53SAndroid Build Coastguard Worker case NL_DUMP_STATS:
255*4dc78e53SAndroid Build Coastguard Worker if (dp->dp_ivar == NH_DUMP_FROM_DETAILS)
256*4dc78e53SAndroid Build Coastguard Worker nh_dump_details(nh, dp);
257*4dc78e53SAndroid Build Coastguard Worker break;
258*4dc78e53SAndroid Build Coastguard Worker
259*4dc78e53SAndroid Build Coastguard Worker default:
260*4dc78e53SAndroid Build Coastguard Worker break;
261*4dc78e53SAndroid Build Coastguard Worker }
262*4dc78e53SAndroid Build Coastguard Worker }
263*4dc78e53SAndroid Build Coastguard Worker
nh_set_encap(struct rtnl_nexthop * nh,struct rtnl_nh_encap * rtnh_encap)264*4dc78e53SAndroid Build Coastguard Worker void nh_set_encap(struct rtnl_nexthop *nh, struct rtnl_nh_encap *rtnh_encap)
265*4dc78e53SAndroid Build Coastguard Worker {
266*4dc78e53SAndroid Build Coastguard Worker if (nh->rtnh_encap) {
267*4dc78e53SAndroid Build Coastguard Worker if (nh->rtnh_encap->ops && nh->rtnh_encap->ops->destructor)
268*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_encap->ops->destructor(nh->rtnh_encap->priv);
269*4dc78e53SAndroid Build Coastguard Worker free(nh->rtnh_encap->priv);
270*4dc78e53SAndroid Build Coastguard Worker free(nh->rtnh_encap);
271*4dc78e53SAndroid Build Coastguard Worker }
272*4dc78e53SAndroid Build Coastguard Worker
273*4dc78e53SAndroid Build Coastguard Worker if (rtnh_encap) {
274*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_encap = rtnh_encap;
275*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_ENCAP;
276*4dc78e53SAndroid Build Coastguard Worker } else {
277*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_encap = NULL;
278*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask &= ~NH_ATTR_ENCAP;
279*4dc78e53SAndroid Build Coastguard Worker }
280*4dc78e53SAndroid Build Coastguard Worker }
281*4dc78e53SAndroid Build Coastguard Worker
282*4dc78e53SAndroid Build Coastguard Worker /**
283*4dc78e53SAndroid Build Coastguard Worker * @name Attributes
284*4dc78e53SAndroid Build Coastguard Worker * @{
285*4dc78e53SAndroid Build Coastguard Worker */
286*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_set_weight(struct rtnl_nexthop * nh,uint8_t weight)287*4dc78e53SAndroid Build Coastguard Worker void rtnl_route_nh_set_weight(struct rtnl_nexthop *nh, uint8_t weight)
288*4dc78e53SAndroid Build Coastguard Worker {
289*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_weight = weight;
290*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_WEIGHT;
291*4dc78e53SAndroid Build Coastguard Worker }
292*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_get_weight(struct rtnl_nexthop * nh)293*4dc78e53SAndroid Build Coastguard Worker uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *nh)
294*4dc78e53SAndroid Build Coastguard Worker {
295*4dc78e53SAndroid Build Coastguard Worker return nh->rtnh_weight;
296*4dc78e53SAndroid Build Coastguard Worker }
297*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_set_ifindex(struct rtnl_nexthop * nh,int ifindex)298*4dc78e53SAndroid Build Coastguard Worker void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *nh, int ifindex)
299*4dc78e53SAndroid Build Coastguard Worker {
300*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_ifindex = ifindex;
301*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_IFINDEX;
302*4dc78e53SAndroid Build Coastguard Worker }
303*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_get_ifindex(struct rtnl_nexthop * nh)304*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *nh)
305*4dc78e53SAndroid Build Coastguard Worker {
306*4dc78e53SAndroid Build Coastguard Worker return nh->rtnh_ifindex;
307*4dc78e53SAndroid Build Coastguard Worker }
308*4dc78e53SAndroid Build Coastguard Worker
309*4dc78e53SAndroid Build Coastguard Worker /* FIXME: Convert to return an int */
rtnl_route_nh_set_gateway(struct rtnl_nexthop * nh,struct nl_addr * addr)310*4dc78e53SAndroid Build Coastguard Worker void rtnl_route_nh_set_gateway(struct rtnl_nexthop *nh, struct nl_addr *addr)
311*4dc78e53SAndroid Build Coastguard Worker {
312*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *old = nh->rtnh_gateway;
313*4dc78e53SAndroid Build Coastguard Worker
314*4dc78e53SAndroid Build Coastguard Worker if (addr) {
315*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_gateway = nl_addr_get(addr);
316*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_GATEWAY;
317*4dc78e53SAndroid Build Coastguard Worker } else {
318*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask &= ~NH_ATTR_GATEWAY;
319*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_gateway = NULL;
320*4dc78e53SAndroid Build Coastguard Worker }
321*4dc78e53SAndroid Build Coastguard Worker
322*4dc78e53SAndroid Build Coastguard Worker if (old)
323*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(old);
324*4dc78e53SAndroid Build Coastguard Worker }
325*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_get_gateway(struct rtnl_nexthop * nh)326*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_route_nh_get_gateway(struct rtnl_nexthop *nh)
327*4dc78e53SAndroid Build Coastguard Worker {
328*4dc78e53SAndroid Build Coastguard Worker return nh->rtnh_gateway;
329*4dc78e53SAndroid Build Coastguard Worker }
330*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_set_flags(struct rtnl_nexthop * nh,unsigned int flags)331*4dc78e53SAndroid Build Coastguard Worker void rtnl_route_nh_set_flags(struct rtnl_nexthop *nh, unsigned int flags)
332*4dc78e53SAndroid Build Coastguard Worker {
333*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_flag_mask |= flags;
334*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_flags |= flags;
335*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_FLAGS;
336*4dc78e53SAndroid Build Coastguard Worker }
337*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_unset_flags(struct rtnl_nexthop * nh,unsigned int flags)338*4dc78e53SAndroid Build Coastguard Worker void rtnl_route_nh_unset_flags(struct rtnl_nexthop *nh, unsigned int flags)
339*4dc78e53SAndroid Build Coastguard Worker {
340*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_flag_mask |= flags;
341*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_flags &= ~flags;
342*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_FLAGS;
343*4dc78e53SAndroid Build Coastguard Worker }
344*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_get_flags(struct rtnl_nexthop * nh)345*4dc78e53SAndroid Build Coastguard Worker unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *nh)
346*4dc78e53SAndroid Build Coastguard Worker {
347*4dc78e53SAndroid Build Coastguard Worker return nh->rtnh_flags;
348*4dc78e53SAndroid Build Coastguard Worker }
349*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_set_realms(struct rtnl_nexthop * nh,uint32_t realms)350*4dc78e53SAndroid Build Coastguard Worker void rtnl_route_nh_set_realms(struct rtnl_nexthop *nh, uint32_t realms)
351*4dc78e53SAndroid Build Coastguard Worker {
352*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_realms = realms;
353*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_REALMS;
354*4dc78e53SAndroid Build Coastguard Worker }
355*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_get_realms(struct rtnl_nexthop * nh)356*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh)
357*4dc78e53SAndroid Build Coastguard Worker {
358*4dc78e53SAndroid Build Coastguard Worker return nh->rtnh_realms;
359*4dc78e53SAndroid Build Coastguard Worker }
360*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_set_newdst(struct rtnl_nexthop * nh,struct nl_addr * addr)361*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_nh_set_newdst(struct rtnl_nexthop *nh, struct nl_addr *addr)
362*4dc78e53SAndroid Build Coastguard Worker {
363*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *old = nh->rtnh_newdst;
364*4dc78e53SAndroid Build Coastguard Worker
365*4dc78e53SAndroid Build Coastguard Worker if (addr) {
366*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_newdst = nl_addr_get(addr);
367*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_NEWDST;
368*4dc78e53SAndroid Build Coastguard Worker } else {
369*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask &= ~NH_ATTR_NEWDST;
370*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_newdst = NULL;
371*4dc78e53SAndroid Build Coastguard Worker }
372*4dc78e53SAndroid Build Coastguard Worker
373*4dc78e53SAndroid Build Coastguard Worker if (old)
374*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(old);
375*4dc78e53SAndroid Build Coastguard Worker
376*4dc78e53SAndroid Build Coastguard Worker return 0;
377*4dc78e53SAndroid Build Coastguard Worker }
378*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_get_newdst(struct rtnl_nexthop * nh)379*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_route_nh_get_newdst(struct rtnl_nexthop *nh)
380*4dc78e53SAndroid Build Coastguard Worker {
381*4dc78e53SAndroid Build Coastguard Worker return nh->rtnh_newdst;
382*4dc78e53SAndroid Build Coastguard Worker }
383*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_set_via(struct rtnl_nexthop * nh,struct nl_addr * addr)384*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_nh_set_via(struct rtnl_nexthop *nh, struct nl_addr *addr)
385*4dc78e53SAndroid Build Coastguard Worker {
386*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *old = nh->rtnh_via;
387*4dc78e53SAndroid Build Coastguard Worker
388*4dc78e53SAndroid Build Coastguard Worker if (addr) {
389*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_via = nl_addr_get(addr);
390*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask |= NH_ATTR_VIA;
391*4dc78e53SAndroid Build Coastguard Worker } else {
392*4dc78e53SAndroid Build Coastguard Worker nh->ce_mask &= ~NH_ATTR_VIA;
393*4dc78e53SAndroid Build Coastguard Worker nh->rtnh_via= NULL;
394*4dc78e53SAndroid Build Coastguard Worker }
395*4dc78e53SAndroid Build Coastguard Worker
396*4dc78e53SAndroid Build Coastguard Worker if (old)
397*4dc78e53SAndroid Build Coastguard Worker nl_addr_put(old);
398*4dc78e53SAndroid Build Coastguard Worker
399*4dc78e53SAndroid Build Coastguard Worker return 0;
400*4dc78e53SAndroid Build Coastguard Worker }
401*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_get_via(struct rtnl_nexthop * nh)402*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_route_nh_get_via(struct rtnl_nexthop *nh)
403*4dc78e53SAndroid Build Coastguard Worker {
404*4dc78e53SAndroid Build Coastguard Worker return nh->rtnh_via;
405*4dc78e53SAndroid Build Coastguard Worker }
406*4dc78e53SAndroid Build Coastguard Worker
407*4dc78e53SAndroid Build Coastguard Worker /** @} */
408*4dc78e53SAndroid Build Coastguard Worker
409*4dc78e53SAndroid Build Coastguard Worker /**
410*4dc78e53SAndroid Build Coastguard Worker * @name Nexthop Flags Translations
411*4dc78e53SAndroid Build Coastguard Worker * @{
412*4dc78e53SAndroid Build Coastguard Worker */
413*4dc78e53SAndroid Build Coastguard Worker
414*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl nh_flags[] = {
415*4dc78e53SAndroid Build Coastguard Worker __ADD(RTNH_F_DEAD, dead),
416*4dc78e53SAndroid Build Coastguard Worker __ADD(RTNH_F_PERVASIVE, pervasive),
417*4dc78e53SAndroid Build Coastguard Worker __ADD(RTNH_F_ONLINK, onlink),
418*4dc78e53SAndroid Build Coastguard Worker };
419*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_flags2str(int flags,char * buf,size_t len)420*4dc78e53SAndroid Build Coastguard Worker char *rtnl_route_nh_flags2str(int flags, char *buf, size_t len)
421*4dc78e53SAndroid Build Coastguard Worker {
422*4dc78e53SAndroid Build Coastguard Worker return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
423*4dc78e53SAndroid Build Coastguard Worker }
424*4dc78e53SAndroid Build Coastguard Worker
rtnl_route_nh_str2flags(const char * name)425*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_nh_str2flags(const char *name)
426*4dc78e53SAndroid Build Coastguard Worker {
427*4dc78e53SAndroid Build Coastguard Worker return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags));
428*4dc78e53SAndroid Build Coastguard Worker }
429*4dc78e53SAndroid Build Coastguard Worker
430*4dc78e53SAndroid Build Coastguard Worker /** @} */
431*4dc78e53SAndroid Build Coastguard Worker
432*4dc78e53SAndroid Build Coastguard Worker /** @} */
433