1 #include <linux/module.h>
2 #include <linux/errno.h>
3 #include <linux/socket.h>
4 #include <linux/skbuff.h>
7 #include <linux/types.h>
8 #include <linux/kernel.h>
9 #include <net/genetlink.h>
11 #include <net/protocol.h>
13 #include <net/udp_tunnel.h>
15 #include <uapi/linux/fou.h>
16 #include <uapi/linux/genetlink.h>
18 static DEFINE_SPINLOCK(fou_lock
);
19 static LIST_HEAD(fou_list
);
25 struct udp_offload udp_offloads
;
26 struct list_head list
;
31 struct udp_port_cfg udp_config
;
34 static inline struct fou
*fou_from_sock(struct sock
*sk
)
36 return sk
->sk_user_data
;
39 static int fou_udp_encap_recv_deliver(struct sk_buff
*skb
,
40 u8 protocol
, size_t len
)
42 struct iphdr
*iph
= ip_hdr(skb
);
44 /* Remove 'len' bytes from the packet (UDP header and
45 * FOU header if present), modify the protocol to the one
46 * we found, and then call rcv_encap.
48 iph
->tot_len
= htons(ntohs(iph
->tot_len
) - len
);
50 skb_postpull_rcsum(skb
, udp_hdr(skb
), len
);
51 skb_reset_transport_header(skb
);
56 static int fou_udp_recv(struct sock
*sk
, struct sk_buff
*skb
)
58 struct fou
*fou
= fou_from_sock(sk
);
63 return fou_udp_encap_recv_deliver(skb
, fou
->protocol
,
64 sizeof(struct udphdr
));
67 static struct sk_buff
**fou_gro_receive(struct sk_buff
**head
,
70 const struct net_offload
*ops
;
71 struct sk_buff
**pp
= NULL
;
72 u8 proto
= NAPI_GRO_CB(skb
)->proto
;
73 const struct net_offload
**offloads
;
76 offloads
= NAPI_GRO_CB(skb
)->is_ipv6
? inet6_offloads
: inet_offloads
;
77 ops
= rcu_dereference(offloads
[proto
]);
78 if (!ops
|| !ops
->callbacks
.gro_receive
)
81 pp
= ops
->callbacks
.gro_receive(head
, skb
);
89 static int fou_gro_complete(struct sk_buff
*skb
, int nhoff
)
91 const struct net_offload
*ops
;
92 u8 proto
= NAPI_GRO_CB(skb
)->proto
;
94 const struct net_offload
**offloads
;
97 offloads
= NAPI_GRO_CB(skb
)->is_ipv6
? inet6_offloads
: inet_offloads
;
98 ops
= rcu_dereference(offloads
[proto
]);
99 if (WARN_ON(!ops
|| !ops
->callbacks
.gro_complete
))
102 err
= ops
->callbacks
.gro_complete(skb
, nhoff
);
110 static int fou_add_to_port_list(struct fou
*fou
)
114 spin_lock(&fou_lock
);
115 list_for_each_entry(fout
, &fou_list
, list
) {
116 if (fou
->port
== fout
->port
) {
117 spin_unlock(&fou_lock
);
122 list_add(&fou
->list
, &fou_list
);
123 spin_unlock(&fou_lock
);
128 static void fou_release(struct fou
*fou
)
130 struct socket
*sock
= fou
->sock
;
131 struct sock
*sk
= sock
->sk
;
133 udp_del_offload(&fou
->udp_offloads
);
135 list_del(&fou
->list
);
137 /* Remove hooks into tunnel socket */
138 sk
->sk_user_data
= NULL
;
145 static int fou_create(struct net
*net
, struct fou_cfg
*cfg
,
146 struct socket
**sockp
)
148 struct fou
*fou
= NULL
;
150 struct socket
*sock
= NULL
;
153 /* Open UDP socket */
154 err
= udp_sock_create(net
, &cfg
->udp_config
, &sock
);
158 /* Allocate FOU port structure */
159 fou
= kzalloc(sizeof(*fou
), GFP_KERNEL
);
167 /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
168 fou
->protocol
= cfg
->protocol
;
169 fou
->port
= cfg
->udp_config
.local_udp_port
;
170 udp_sk(sk
)->encap_rcv
= fou_udp_recv
;
172 udp_sk(sk
)->encap_type
= 1;
175 sk
->sk_user_data
= fou
;
178 udp_set_convert_csum(sk
, true);
180 sk
->sk_allocation
= GFP_ATOMIC
;
182 fou
->udp_offloads
.callbacks
.gro_receive
= fou_gro_receive
;
183 fou
->udp_offloads
.callbacks
.gro_complete
= fou_gro_complete
;
184 fou
->udp_offloads
.port
= cfg
->udp_config
.local_udp_port
;
185 fou
->udp_offloads
.ipproto
= cfg
->protocol
;
187 if (cfg
->udp_config
.family
== AF_INET
) {
188 err
= udp_add_offload(&fou
->udp_offloads
);
193 err
= fou_add_to_port_list(fou
);
210 static int fou_destroy(struct net
*net
, struct fou_cfg
*cfg
)
213 u16 port
= cfg
->udp_config
.local_udp_port
;
216 spin_lock(&fou_lock
);
217 list_for_each_entry(fou
, &fou_list
, list
) {
218 if (fou
->port
== port
) {
219 udp_del_offload(&fou
->udp_offloads
);
225 spin_unlock(&fou_lock
);
230 static struct genl_family fou_nl_family
= {
231 .id
= GENL_ID_GENERATE
,
233 .name
= FOU_GENL_NAME
,
234 .version
= FOU_GENL_VERSION
,
235 .maxattr
= FOU_ATTR_MAX
,
239 static struct nla_policy fou_nl_policy
[FOU_ATTR_MAX
+ 1] = {
240 [FOU_ATTR_PORT
] = { .type
= NLA_U16
, },
241 [FOU_ATTR_AF
] = { .type
= NLA_U8
, },
242 [FOU_ATTR_IPPROTO
] = { .type
= NLA_U8
, },
245 static int parse_nl_config(struct genl_info
*info
,
248 memset(cfg
, 0, sizeof(*cfg
));
250 cfg
->udp_config
.family
= AF_INET
;
252 if (info
->attrs
[FOU_ATTR_AF
]) {
253 u8 family
= nla_get_u8(info
->attrs
[FOU_ATTR_AF
]);
255 if (family
!= AF_INET
&& family
!= AF_INET6
)
258 cfg
->udp_config
.family
= family
;
261 if (info
->attrs
[FOU_ATTR_PORT
]) {
262 u16 port
= nla_get_u16(info
->attrs
[FOU_ATTR_PORT
]);
264 cfg
->udp_config
.local_udp_port
= port
;
267 if (info
->attrs
[FOU_ATTR_IPPROTO
])
268 cfg
->protocol
= nla_get_u8(info
->attrs
[FOU_ATTR_IPPROTO
]);
273 static int fou_nl_cmd_add_port(struct sk_buff
*skb
, struct genl_info
*info
)
278 err
= parse_nl_config(info
, &cfg
);
282 return fou_create(&init_net
, &cfg
, NULL
);
285 static int fou_nl_cmd_rm_port(struct sk_buff
*skb
, struct genl_info
*info
)
289 parse_nl_config(info
, &cfg
);
291 return fou_destroy(&init_net
, &cfg
);
294 static const struct genl_ops fou_nl_ops
[] = {
297 .doit
= fou_nl_cmd_add_port
,
298 .policy
= fou_nl_policy
,
299 .flags
= GENL_ADMIN_PERM
,
303 .doit
= fou_nl_cmd_rm_port
,
304 .policy
= fou_nl_policy
,
305 .flags
= GENL_ADMIN_PERM
,
309 static int __init
fou_init(void)
313 ret
= genl_register_family_with_ops(&fou_nl_family
,
319 static void __exit
fou_fini(void)
321 struct fou
*fou
, *next
;
323 genl_unregister_family(&fou_nl_family
);
325 /* Close all the FOU sockets */
327 spin_lock(&fou_lock
);
328 list_for_each_entry_safe(fou
, next
, &fou_list
, list
)
330 spin_unlock(&fou_lock
);
333 module_init(fou_init
);
334 module_exit(fou_fini
);
335 MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
336 MODULE_LICENSE("GPL");