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