.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * lwtunnel Infrastructure for light weight tunnels like mpls |
---|
3 | 4 | * |
---|
4 | 5 | * Authors: Roopa Prabhu, <roopa@cumulusnetworks.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of the GNU General Public License |
---|
8 | | - * as published by the Free Software Foundation; either version |
---|
9 | | - * 2 of the License, or (at your option) any later version. |
---|
10 | | - * |
---|
11 | 6 | */ |
---|
12 | 7 | |
---|
13 | 8 | #include <linux/capability.h> |
---|
.. | .. |
---|
26 | 21 | #include <net/lwtunnel.h> |
---|
27 | 22 | #include <net/rtnetlink.h> |
---|
28 | 23 | #include <net/ip6_fib.h> |
---|
29 | | -#include <net/nexthop.h> |
---|
| 24 | +#include <net/rtnh.h> |
---|
30 | 25 | |
---|
31 | 26 | #ifdef CONFIG_MODULES |
---|
32 | 27 | |
---|
.. | .. |
---|
46 | 41 | return "BPF"; |
---|
47 | 42 | case LWTUNNEL_ENCAP_SEG6_LOCAL: |
---|
48 | 43 | return "SEG6LOCAL"; |
---|
| 44 | + case LWTUNNEL_ENCAP_RPL: |
---|
| 45 | + return "RPL"; |
---|
49 | 46 | case LWTUNNEL_ENCAP_IP6: |
---|
50 | 47 | case LWTUNNEL_ENCAP_IP: |
---|
51 | 48 | case LWTUNNEL_ENCAP_NONE: |
---|
.. | .. |
---|
103 | 100 | } |
---|
104 | 101 | EXPORT_SYMBOL_GPL(lwtunnel_encap_del_ops); |
---|
105 | 102 | |
---|
106 | | -int lwtunnel_build_state(u16 encap_type, |
---|
| 103 | +int lwtunnel_build_state(struct net *net, u16 encap_type, |
---|
107 | 104 | struct nlattr *encap, unsigned int family, |
---|
108 | 105 | const void *cfg, struct lwtunnel_state **lws, |
---|
109 | 106 | struct netlink_ext_ack *extack) |
---|
.. | .. |
---|
122 | 119 | ret = -EOPNOTSUPP; |
---|
123 | 120 | rcu_read_lock(); |
---|
124 | 121 | ops = rcu_dereference(lwtun_encaps[encap_type]); |
---|
125 | | - if (likely(ops && ops->build_state && try_module_get(ops->owner))) { |
---|
| 122 | + if (likely(ops && ops->build_state && try_module_get(ops->owner))) |
---|
126 | 123 | found = true; |
---|
127 | | - ret = ops->build_state(encap, family, cfg, lws, extack); |
---|
128 | | - if (ret) |
---|
129 | | - module_put(ops->owner); |
---|
130 | | - } |
---|
131 | 124 | rcu_read_unlock(); |
---|
132 | 125 | |
---|
133 | | - /* don't rely on -EOPNOTSUPP to detect match as build_state |
---|
134 | | - * handlers could return it |
---|
135 | | - */ |
---|
136 | | - if (!found) { |
---|
| 126 | + if (found) { |
---|
| 127 | + ret = ops->build_state(net, encap, family, cfg, lws, extack); |
---|
| 128 | + if (ret) |
---|
| 129 | + module_put(ops->owner); |
---|
| 130 | + } else { |
---|
| 131 | + /* don't rely on -EOPNOTSUPP to detect match as build_state |
---|
| 132 | + * handlers could return it |
---|
| 133 | + */ |
---|
137 | 134 | NL_SET_ERR_MSG_ATTR(extack, encap, |
---|
138 | 135 | "LWT encapsulation type not supported"); |
---|
139 | 136 | } |
---|
.. | .. |
---|
195 | 192 | nla_entype = nla_find(attrs, attrlen, RTA_ENCAP_TYPE); |
---|
196 | 193 | |
---|
197 | 194 | if (nla_entype) { |
---|
| 195 | + if (nla_len(nla_entype) < sizeof(u16)) { |
---|
| 196 | + NL_SET_ERR_MSG(extack, "Invalid RTA_ENCAP_TYPE"); |
---|
| 197 | + return -EINVAL; |
---|
| 198 | + } |
---|
198 | 199 | encap_type = nla_get_u16(nla_entype); |
---|
199 | 200 | |
---|
200 | 201 | if (lwtunnel_valid_encap_type(encap_type, |
---|
.. | .. |
---|
223 | 224 | } |
---|
224 | 225 | EXPORT_SYMBOL_GPL(lwtstate_free); |
---|
225 | 226 | |
---|
226 | | -int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate) |
---|
| 227 | +int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate, |
---|
| 228 | + int encap_attr, int encap_type_attr) |
---|
227 | 229 | { |
---|
228 | 230 | const struct lwtunnel_encap_ops *ops; |
---|
229 | 231 | struct nlattr *nest; |
---|
.. | .. |
---|
236 | 238 | lwtstate->type > LWTUNNEL_ENCAP_MAX) |
---|
237 | 239 | return 0; |
---|
238 | 240 | |
---|
239 | | - nest = nla_nest_start(skb, RTA_ENCAP); |
---|
| 241 | + nest = nla_nest_start_noflag(skb, encap_attr); |
---|
240 | 242 | if (!nest) |
---|
241 | 243 | return -EMSGSIZE; |
---|
242 | 244 | |
---|
.. | .. |
---|
250 | 252 | if (ret) |
---|
251 | 253 | goto nla_put_failure; |
---|
252 | 254 | nla_nest_end(skb, nest); |
---|
253 | | - ret = nla_put_u16(skb, RTA_ENCAP_TYPE, lwtstate->type); |
---|
| 255 | + ret = nla_put_u16(skb, encap_type_attr, lwtstate->type); |
---|
254 | 256 | if (ret) |
---|
255 | 257 | goto nla_put_failure; |
---|
256 | 258 | |
---|