| .. | .. |
|---|
| 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 | |
|---|