xref: /aosp_15_r20/external/libnl/lib/route/nh_encap_mpls.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 #include "nl-default.h"
4*4dc78e53SAndroid Build Coastguard Worker 
5*4dc78e53SAndroid Build Coastguard Worker #include <linux/mpls_iptunnel.h>
6*4dc78e53SAndroid Build Coastguard Worker #include <linux/lwtunnel.h>
7*4dc78e53SAndroid Build Coastguard Worker 
8*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/nexthop.h>
9*4dc78e53SAndroid Build Coastguard Worker 
10*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
11*4dc78e53SAndroid Build Coastguard Worker #include "nexthop-encap.h"
12*4dc78e53SAndroid Build Coastguard Worker 
13*4dc78e53SAndroid Build Coastguard Worker struct mpls_iptunnel_encap {
14*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *dst;
15*4dc78e53SAndroid Build Coastguard Worker 	uint8_t ttl;
16*4dc78e53SAndroid Build Coastguard Worker };
17*4dc78e53SAndroid Build Coastguard Worker 
mpls_encap_dump(void * priv,struct nl_dump_params * dp)18*4dc78e53SAndroid Build Coastguard Worker static void mpls_encap_dump(void *priv, struct nl_dump_params *dp)
19*4dc78e53SAndroid Build Coastguard Worker {
20*4dc78e53SAndroid Build Coastguard Worker 	struct mpls_iptunnel_encap *encap_info = priv;
21*4dc78e53SAndroid Build Coastguard Worker 	char buf[256];
22*4dc78e53SAndroid Build Coastguard Worker 
23*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(dp, "%s ", nl_addr2str(encap_info->dst, buf, sizeof(buf)));
24*4dc78e53SAndroid Build Coastguard Worker 
25*4dc78e53SAndroid Build Coastguard Worker 	if (encap_info->ttl)
26*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(dp, "ttl %u ", encap_info->ttl);
27*4dc78e53SAndroid Build Coastguard Worker }
28*4dc78e53SAndroid Build Coastguard Worker 
mpls_encap_build_msg(struct nl_msg * msg,void * priv)29*4dc78e53SAndroid Build Coastguard Worker static int mpls_encap_build_msg(struct nl_msg *msg, void *priv)
30*4dc78e53SAndroid Build Coastguard Worker {
31*4dc78e53SAndroid Build Coastguard Worker 	struct mpls_iptunnel_encap *encap_info = priv;
32*4dc78e53SAndroid Build Coastguard Worker 
33*4dc78e53SAndroid Build Coastguard Worker 	NLA_PUT_ADDR(msg, MPLS_IPTUNNEL_DST, encap_info->dst);
34*4dc78e53SAndroid Build Coastguard Worker 	if (encap_info->ttl)
35*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U8(msg, MPLS_IPTUNNEL_TTL, encap_info->ttl);
36*4dc78e53SAndroid Build Coastguard Worker 
37*4dc78e53SAndroid Build Coastguard Worker 	return 0;
38*4dc78e53SAndroid Build Coastguard Worker 
39*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
40*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_MSGSIZE;
41*4dc78e53SAndroid Build Coastguard Worker }
42*4dc78e53SAndroid Build Coastguard Worker 
mpls_encap_destructor(void * priv)43*4dc78e53SAndroid Build Coastguard Worker static void mpls_encap_destructor(void *priv)
44*4dc78e53SAndroid Build Coastguard Worker {
45*4dc78e53SAndroid Build Coastguard Worker 	struct mpls_iptunnel_encap *encap_info = priv;
46*4dc78e53SAndroid Build Coastguard Worker 
47*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_put(encap_info->dst);
48*4dc78e53SAndroid Build Coastguard Worker }
49*4dc78e53SAndroid Build Coastguard Worker 
50*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy mpls_encap_policy[MPLS_IPTUNNEL_MAX + 1] = {
51*4dc78e53SAndroid Build Coastguard Worker 	[MPLS_IPTUNNEL_DST]     = { .type = NLA_U32 },
52*4dc78e53SAndroid Build Coastguard Worker 	[MPLS_IPTUNNEL_TTL]     = { .type = NLA_U8 },
53*4dc78e53SAndroid Build Coastguard Worker };
54*4dc78e53SAndroid Build Coastguard Worker 
mpls_encap_parse_msg(struct nlattr * nla,struct rtnl_nexthop * nh)55*4dc78e53SAndroid Build Coastguard Worker static int mpls_encap_parse_msg(struct nlattr *nla, struct rtnl_nexthop *nh)
56*4dc78e53SAndroid Build Coastguard Worker {
57*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1];
58*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *labels;
59*4dc78e53SAndroid Build Coastguard Worker 	uint8_t ttl = 0;
60*4dc78e53SAndroid Build Coastguard Worker 	int err;
61*4dc78e53SAndroid Build Coastguard Worker 
62*4dc78e53SAndroid Build Coastguard Worker 	err = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla, mpls_encap_policy);
63*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
64*4dc78e53SAndroid Build Coastguard Worker 		return err;
65*4dc78e53SAndroid Build Coastguard Worker 
66*4dc78e53SAndroid Build Coastguard Worker 	if (!tb[MPLS_IPTUNNEL_DST])
67*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
68*4dc78e53SAndroid Build Coastguard Worker 
69*4dc78e53SAndroid Build Coastguard Worker 	labels = nl_addr_alloc_attr(tb[MPLS_IPTUNNEL_DST], AF_MPLS);
70*4dc78e53SAndroid Build Coastguard Worker 	if (!labels)
71*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
72*4dc78e53SAndroid Build Coastguard Worker 
73*4dc78e53SAndroid Build Coastguard Worker 	if (tb[MPLS_IPTUNNEL_TTL])
74*4dc78e53SAndroid Build Coastguard Worker 		ttl = nla_get_u8(tb[MPLS_IPTUNNEL_TTL]);
75*4dc78e53SAndroid Build Coastguard Worker 
76*4dc78e53SAndroid Build Coastguard Worker 	err = rtnl_route_nh_encap_mpls(nh, labels, ttl);
77*4dc78e53SAndroid Build Coastguard Worker 
78*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_put(labels);
79*4dc78e53SAndroid Build Coastguard Worker 
80*4dc78e53SAndroid Build Coastguard Worker 	return err;
81*4dc78e53SAndroid Build Coastguard Worker }
82*4dc78e53SAndroid Build Coastguard Worker 
mpls_encap_compare(void * _a,void * _b)83*4dc78e53SAndroid Build Coastguard Worker static int mpls_encap_compare(void *_a, void *_b)
84*4dc78e53SAndroid Build Coastguard Worker {
85*4dc78e53SAndroid Build Coastguard Worker 	struct mpls_iptunnel_encap *a = _a;
86*4dc78e53SAndroid Build Coastguard Worker 	struct mpls_iptunnel_encap *b = _b;
87*4dc78e53SAndroid Build Coastguard Worker 	int diff = 0;
88*4dc78e53SAndroid Build Coastguard Worker 
89*4dc78e53SAndroid Build Coastguard Worker 	diff |= (a->ttl != b->ttl);
90*4dc78e53SAndroid Build Coastguard Worker 	diff |= nl_addr_cmp(a->dst, b->dst);
91*4dc78e53SAndroid Build Coastguard Worker 
92*4dc78e53SAndroid Build Coastguard Worker 	return diff;
93*4dc78e53SAndroid Build Coastguard Worker }
94*4dc78e53SAndroid Build Coastguard Worker 
95*4dc78e53SAndroid Build Coastguard Worker struct nh_encap_ops mpls_encap_ops = {
96*4dc78e53SAndroid Build Coastguard Worker 	.encap_type	= LWTUNNEL_ENCAP_MPLS,
97*4dc78e53SAndroid Build Coastguard Worker 	.build_msg	= mpls_encap_build_msg,
98*4dc78e53SAndroid Build Coastguard Worker 	.parse_msg	= mpls_encap_parse_msg,
99*4dc78e53SAndroid Build Coastguard Worker 	.compare	= mpls_encap_compare,
100*4dc78e53SAndroid Build Coastguard Worker 	.dump		= mpls_encap_dump,
101*4dc78e53SAndroid Build Coastguard Worker 	.destructor	= mpls_encap_destructor,
102*4dc78e53SAndroid Build Coastguard Worker };
103*4dc78e53SAndroid Build Coastguard Worker 
rtnl_route_nh_encap_mpls(struct rtnl_nexthop * nh,struct nl_addr * addr,uint8_t ttl)104*4dc78e53SAndroid Build Coastguard Worker int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh,
105*4dc78e53SAndroid Build Coastguard Worker 			     struct nl_addr *addr,
106*4dc78e53SAndroid Build Coastguard Worker 			     uint8_t ttl)
107*4dc78e53SAndroid Build Coastguard Worker {
108*4dc78e53SAndroid Build Coastguard Worker 	struct mpls_iptunnel_encap *mpls_encap;
109*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_nh_encap *rtnh_encap;
110*4dc78e53SAndroid Build Coastguard Worker 
111*4dc78e53SAndroid Build Coastguard Worker 	if (!addr)
112*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
113*4dc78e53SAndroid Build Coastguard Worker 
114*4dc78e53SAndroid Build Coastguard Worker 	rtnh_encap = calloc(1, sizeof(*rtnh_encap));
115*4dc78e53SAndroid Build Coastguard Worker 	if (!rtnh_encap)
116*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
117*4dc78e53SAndroid Build Coastguard Worker 
118*4dc78e53SAndroid Build Coastguard Worker 	mpls_encap = calloc(1, sizeof(*mpls_encap));
119*4dc78e53SAndroid Build Coastguard Worker 	if (!mpls_encap) {
120*4dc78e53SAndroid Build Coastguard Worker 		free(rtnh_encap);
121*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
122*4dc78e53SAndroid Build Coastguard Worker 	}
123*4dc78e53SAndroid Build Coastguard Worker 
124*4dc78e53SAndroid Build Coastguard Worker 	mpls_encap->dst = nl_addr_get(addr);
125*4dc78e53SAndroid Build Coastguard Worker 	mpls_encap->ttl = ttl;
126*4dc78e53SAndroid Build Coastguard Worker 
127*4dc78e53SAndroid Build Coastguard Worker 	rtnh_encap->priv = mpls_encap;
128*4dc78e53SAndroid Build Coastguard Worker 	rtnh_encap->ops = &mpls_encap_ops;
129*4dc78e53SAndroid Build Coastguard Worker 
130*4dc78e53SAndroid Build Coastguard Worker 	nh_set_encap(nh, rtnh_encap);
131*4dc78e53SAndroid Build Coastguard Worker 
132*4dc78e53SAndroid Build Coastguard Worker 	return 0;
133*4dc78e53SAndroid Build Coastguard Worker }
134*4dc78e53SAndroid Build Coastguard Worker 
rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop * nh)135*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *nh)
136*4dc78e53SAndroid Build Coastguard Worker {
137*4dc78e53SAndroid Build Coastguard Worker 	struct mpls_iptunnel_encap *mpls_encap;
138*4dc78e53SAndroid Build Coastguard Worker 
139*4dc78e53SAndroid Build Coastguard Worker 	if (!nh->rtnh_encap || nh->rtnh_encap->ops->encap_type != LWTUNNEL_ENCAP_MPLS)
140*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
141*4dc78e53SAndroid Build Coastguard Worker 
142*4dc78e53SAndroid Build Coastguard Worker 	mpls_encap = (struct mpls_iptunnel_encap *)nh->rtnh_encap->priv;
143*4dc78e53SAndroid Build Coastguard Worker 	if (!mpls_encap)
144*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
145*4dc78e53SAndroid Build Coastguard Worker 
146*4dc78e53SAndroid Build Coastguard Worker 	return mpls_encap->dst;
147*4dc78e53SAndroid Build Coastguard Worker }
148*4dc78e53SAndroid Build Coastguard Worker 
rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop * nh)149*4dc78e53SAndroid Build Coastguard Worker uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *nh)
150*4dc78e53SAndroid Build Coastguard Worker {
151*4dc78e53SAndroid Build Coastguard Worker 	struct mpls_iptunnel_encap *mpls_encap;
152*4dc78e53SAndroid Build Coastguard Worker 
153*4dc78e53SAndroid Build Coastguard Worker 	if (!nh->rtnh_encap || nh->rtnh_encap->ops->encap_type != LWTUNNEL_ENCAP_MPLS)
154*4dc78e53SAndroid Build Coastguard Worker 		return 0;
155*4dc78e53SAndroid Build Coastguard Worker 
156*4dc78e53SAndroid Build Coastguard Worker 	mpls_encap = (struct mpls_iptunnel_encap *)nh->rtnh_encap->priv;
157*4dc78e53SAndroid Build Coastguard Worker 	if (!mpls_encap)
158*4dc78e53SAndroid Build Coastguard Worker 		return 0;
159*4dc78e53SAndroid Build Coastguard Worker 
160*4dc78e53SAndroid Build Coastguard Worker 	return mpls_encap->ttl;
161*4dc78e53SAndroid Build Coastguard Worker }
162