xref: /aosp_15_r20/external/libnl/lib/route/nexthop.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 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