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
,
69 const struct net_offload
**offloads
)
71 const struct net_offload
*ops
;
72 struct sk_buff
**pp
= NULL
;
73 u8 proto
= NAPI_GRO_CB(skb
)->proto
;
76 ops
= rcu_dereference(offloads
[proto
]);
77 if (!ops
|| !ops
->callbacks
.gro_receive
)
80 pp
= ops
->callbacks
.gro_receive(head
, skb
);
88 static int fou_gro_complete(struct sk_buff
*skb
, int nhoff
,
89 const struct net_offload
**offloads
)
91 const struct net_offload
*ops
;
92 u8 proto
= NAPI_GRO_CB(skb
)->proto
;
96 ops
= rcu_dereference(offloads
[proto
]);
97 if (WARN_ON(!ops
|| !ops
->callbacks
.gro_complete
))
100 err
= ops
->callbacks
.gro_complete(skb
, nhoff
);
108 static struct sk_buff
**fou4_gro_receive(struct sk_buff
**head
,
111 return fou_gro_receive(head
, skb
, inet_offloads
);
114 static int fou4_gro_complete(struct sk_buff
*skb
, int nhoff
)
116 return fou_gro_complete(skb
, nhoff
, inet_offloads
);
119 static struct sk_buff
**fou6_gro_receive(struct sk_buff
**head
,
122 return fou_gro_receive(head
, skb
, inet6_offloads
);
125 static int fou6_gro_complete(struct sk_buff
*skb
, int nhoff
)
127 return fou_gro_complete(skb
, nhoff
, inet6_offloads
);
130 static int fou_add_to_port_list(struct fou
*fou
)
134 spin_lock(&fou_lock
);
135 list_for_each_entry(fout
, &fou_list
, list
) {
136 if (fou
->port
== fout
->port
) {
137 spin_unlock(&fou_lock
);
142 list_add(&fou
->list
, &fou_list
);
143 spin_unlock(&fou_lock
);
148 static void fou_release(struct fou
*fou
)
150 struct socket
*sock
= fou
->sock
;
151 struct sock
*sk
= sock
->sk
;
153 udp_del_offload(&fou
->udp_offloads
);
155 list_del(&fou
->list
);
157 /* Remove hooks into tunnel socket */
158 sk
->sk_user_data
= NULL
;
165 static int fou_create(struct net
*net
, struct fou_cfg
*cfg
,
166 struct socket
**sockp
)
168 struct fou
*fou
= NULL
;
170 struct socket
*sock
= NULL
;
173 /* Open UDP socket */
174 err
= udp_sock_create(net
, &cfg
->udp_config
, &sock
);
178 /* Allocate FOU port structure */
179 fou
= kzalloc(sizeof(*fou
), GFP_KERNEL
);
187 /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
188 fou
->protocol
= cfg
->protocol
;
189 fou
->port
= cfg
->udp_config
.local_udp_port
;
190 udp_sk(sk
)->encap_rcv
= fou_udp_recv
;
192 udp_sk(sk
)->encap_type
= 1;
195 sk
->sk_user_data
= fou
;
198 udp_set_convert_csum(sk
, true);
200 sk
->sk_allocation
= GFP_ATOMIC
;
202 switch (cfg
->udp_config
.family
) {
204 fou
->udp_offloads
.callbacks
.gro_receive
= fou4_gro_receive
;
205 fou
->udp_offloads
.callbacks
.gro_complete
= fou4_gro_complete
;
208 fou
->udp_offloads
.callbacks
.gro_receive
= fou6_gro_receive
;
209 fou
->udp_offloads
.callbacks
.gro_complete
= fou6_gro_complete
;
216 fou
->udp_offloads
.port
= cfg
->udp_config
.local_udp_port
;
217 fou
->udp_offloads
.ipproto
= cfg
->protocol
;
219 if (cfg
->udp_config
.family
== AF_INET
) {
220 err
= udp_add_offload(&fou
->udp_offloads
);
225 err
= fou_add_to_port_list(fou
);
242 static int fou_destroy(struct net
*net
, struct fou_cfg
*cfg
)
245 u16 port
= cfg
->udp_config
.local_udp_port
;
248 spin_lock(&fou_lock
);
249 list_for_each_entry(fou
, &fou_list
, list
) {
250 if (fou
->port
== port
) {
251 udp_del_offload(&fou
->udp_offloads
);
257 spin_unlock(&fou_lock
);
262 static struct genl_family fou_nl_family
= {
263 .id
= GENL_ID_GENERATE
,
265 .name
= FOU_GENL_NAME
,
266 .version
= FOU_GENL_VERSION
,
267 .maxattr
= FOU_ATTR_MAX
,
271 static struct nla_policy fou_nl_policy
[FOU_ATTR_MAX
+ 1] = {
272 [FOU_ATTR_PORT
] = { .type
= NLA_U16
, },
273 [FOU_ATTR_AF
] = { .type
= NLA_U8
, },
274 [FOU_ATTR_IPPROTO
] = { .type
= NLA_U8
, },
277 static int parse_nl_config(struct genl_info
*info
,
280 memset(cfg
, 0, sizeof(*cfg
));
282 cfg
->udp_config
.family
= AF_INET
;
284 if (info
->attrs
[FOU_ATTR_AF
]) {
285 u8 family
= nla_get_u8(info
->attrs
[FOU_ATTR_AF
]);
287 if (family
!= AF_INET
&& family
!= AF_INET6
)
290 cfg
->udp_config
.family
= family
;
293 if (info
->attrs
[FOU_ATTR_PORT
]) {
294 u16 port
= nla_get_u16(info
->attrs
[FOU_ATTR_PORT
]);
296 cfg
->udp_config
.local_udp_port
= port
;
299 if (info
->attrs
[FOU_ATTR_IPPROTO
])
300 cfg
->protocol
= nla_get_u8(info
->attrs
[FOU_ATTR_IPPROTO
]);
305 static int fou_nl_cmd_add_port(struct sk_buff
*skb
, struct genl_info
*info
)
310 err
= parse_nl_config(info
, &cfg
);
314 return fou_create(&init_net
, &cfg
, NULL
);
317 static int fou_nl_cmd_rm_port(struct sk_buff
*skb
, struct genl_info
*info
)
321 parse_nl_config(info
, &cfg
);
323 return fou_destroy(&init_net
, &cfg
);
326 static const struct genl_ops fou_nl_ops
[] = {
329 .doit
= fou_nl_cmd_add_port
,
330 .policy
= fou_nl_policy
,
331 .flags
= GENL_ADMIN_PERM
,
335 .doit
= fou_nl_cmd_rm_port
,
336 .policy
= fou_nl_policy
,
337 .flags
= GENL_ADMIN_PERM
,
341 static int __init
fou_init(void)
345 ret
= genl_register_family_with_ops(&fou_nl_family
,
351 static void __exit
fou_fini(void)
353 struct fou
*fou
, *next
;
355 genl_unregister_family(&fou_nl_family
);
357 /* Close all the FOU sockets */
359 spin_lock(&fou_lock
);
360 list_for_each_entry_safe(fou
, next
, &fou_list
, list
)
362 spin_unlock(&fou_lock
);
365 module_init(fou_init
);
366 module_exit(fou_fini
);
367 MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
368 MODULE_LICENSE("GPL");