^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/icmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/udp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <net/gue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <net/fou.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <net/protocol.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <net/udp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/udp_tunnel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/xfrm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <uapi/linux/fou.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <uapi/linux/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct fou {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct socket *sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u8 protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) u8 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) __be16 port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) u8 family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u16 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct rcu_head rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define FOU_F_REMCSUM_NOPARTIAL BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct fou_cfg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u16 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u8 protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u8 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct udp_port_cfg udp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static unsigned int fou_net_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct fou_net {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct list_head fou_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct mutex fou_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static inline struct fou *fou_from_sock(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return sk->sk_user_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int fou_recv_pull(struct sk_buff *skb, struct fou *fou, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Remove 'len' bytes from the packet (UDP header and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * FOU header if present).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (fou->family == AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ipv6_hdr(skb)->payload_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) htons(ntohs(ipv6_hdr(skb)->payload_len) - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) __skb_pull(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) skb_postpull_rcsum(skb, udp_hdr(skb), len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return iptunnel_pull_offloads(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct fou *fou = fou_from_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!fou)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (fou_recv_pull(skb, fou, sizeof(struct udphdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return -fou->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) void *data, size_t hdrlen, u8 ipproto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) bool nopartial)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) __be16 *pd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) size_t start = ntohs(pd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) size_t offset = ntohs(pd[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) size_t plen = sizeof(struct udphdr) + hdrlen +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) max_t(size_t, offset + sizeof(u16), start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (skb->remcsum_offload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return guehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (!pskb_may_pull(skb, plen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) guehdr = (struct guehdr *)&udp_hdr(skb)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) skb_remcsum_process(skb, (void *)guehdr + hdrlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) start, offset, nopartial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return guehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int gue_control_message(struct sk_buff *skb, struct guehdr *guehdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* No support yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct fou *fou = fou_from_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) size_t len, optlen, hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct guehdr *guehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u16 doffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) u8 proto_ctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (!fou)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) len = sizeof(struct udphdr) + sizeof(struct guehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (!pskb_may_pull(skb, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) guehdr = (struct guehdr *)&udp_hdr(skb)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) switch (guehdr->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case 0: /* Full GUE header present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case 1: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* Direct encapsulation of IPv4 or IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) switch (((struct iphdr *)guehdr)->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) prot = IPPROTO_IPIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) prot = IPPROTO_IPV6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (fou_recv_pull(skb, fou, sizeof(struct udphdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return -prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) default: /* Undefined version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) optlen = guehdr->hlen << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) len += optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (!pskb_may_pull(skb, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* guehdr may change after pull */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) guehdr = (struct guehdr *)&udp_hdr(skb)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (validate_gue_flags(guehdr, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) hdrlen = sizeof(struct guehdr) + optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (fou->family == AF_INET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ipv6_hdr(skb)->payload_len =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) htons(ntohs(ipv6_hdr(skb)->payload_len) - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* Pull csum through the guehdr now . This can be used if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * there is a remote checksum offload.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) skb_postpull_rcsum(skb, udp_hdr(skb), len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) data = &guehdr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (guehdr->flags & GUE_FLAG_PRIV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) __be32 flags = *(__be32 *)(data + doffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) doffset += GUE_LEN_PRIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (flags & GUE_PFLAG_REMCSUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) guehdr = gue_remcsum(skb, guehdr, data + doffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) hdrlen, guehdr->proto_ctype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) !!(fou->flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) FOU_F_REMCSUM_NOPARTIAL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!guehdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) data = &guehdr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) doffset += GUE_PLEN_REMCSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (unlikely(guehdr->control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return gue_control_message(skb, guehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) proto_ctype = guehdr->proto_ctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) __skb_pull(skb, sizeof(struct udphdr) + hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (iptunnel_pull_offloads(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return -proto_ctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static struct sk_buff *fou_gro_receive(struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct list_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u8 proto = fou_from_sock(sk)->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) const struct net_offload **offloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) const struct net_offload *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct sk_buff *pp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* We can clear the encap_mark for FOU as we are essentially doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * one of two possible things. We are either adding an L4 tunnel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * header to the outer L3 tunnel header, or we are simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * treating the GRE tunnel header as though it is a UDP protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * specific header such as VXLAN or GENEVE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) NAPI_GRO_CB(skb)->encap_mark = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* Flag this frame as already having an outer encap header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) NAPI_GRO_CB(skb)->is_fou = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ops = rcu_dereference(offloads[proto]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!ops || !ops->callbacks.gro_receive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static int fou_gro_complete(struct sock *sk, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int nhoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) const struct net_offload *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) u8 proto = fou_from_sock(sk)->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int err = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) const struct net_offload **offloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ops = rcu_dereference(offloads[proto]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (WARN_ON(!ops || !ops->callbacks.gro_complete))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) err = ops->callbacks.gro_complete(skb, nhoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) skb_set_inner_mac_header(skb, nhoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct guehdr *guehdr, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) size_t hdrlen, struct gro_remcsum *grc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) bool nopartial)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) __be16 *pd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) size_t start = ntohs(pd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) size_t offset = ntohs(pd[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (skb->remcsum_offload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return guehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!NAPI_GRO_CB(skb)->csum_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) guehdr = skb_gro_remcsum_process(skb, (void *)guehdr, off, hdrlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) start, offset, grc, nopartial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) skb->remcsum_offload = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return guehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static struct sk_buff *gue_gro_receive(struct sock *sk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct list_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) const struct net_offload **offloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) const struct net_offload *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct sk_buff *pp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct sk_buff *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct guehdr *guehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) size_t len, optlen, hdrlen, off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) u16 doffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int flush = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct fou *fou = fou_from_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct gro_remcsum grc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u8 proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) skb_gro_remcsum_init(&grc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) off = skb_gro_offset(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) len = off + sizeof(*guehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) guehdr = skb_gro_header_fast(skb, off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (skb_gro_header_hard(skb, len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) guehdr = skb_gro_header_slow(skb, len, off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (unlikely(!guehdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) switch (guehdr->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) switch (((struct iphdr *)guehdr)->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) proto = IPPROTO_IPIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) proto = IPPROTO_IPV6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) goto next_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) optlen = guehdr->hlen << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) len += optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (skb_gro_header_hard(skb, len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) guehdr = skb_gro_header_slow(skb, len, off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (unlikely(!guehdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (unlikely(guehdr->control) || guehdr->version != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) validate_gue_flags(guehdr, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) hdrlen = sizeof(*guehdr) + optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* Adjust NAPI_GRO_CB(skb)->csum to account for guehdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * this is needed if there is a remote checkcsum offload.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) skb_gro_postpull_rcsum(skb, guehdr, hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) data = &guehdr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (guehdr->flags & GUE_FLAG_PRIV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) __be32 flags = *(__be32 *)(data + doffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) doffset += GUE_LEN_PRIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (flags & GUE_PFLAG_REMCSUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) guehdr = gue_gro_remcsum(skb, off, guehdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) data + doffset, hdrlen, &grc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) !!(fou->flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) FOU_F_REMCSUM_NOPARTIAL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (!guehdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) data = &guehdr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) doffset += GUE_PLEN_REMCSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) skb_gro_pull(skb, hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) list_for_each_entry(p, head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) const struct guehdr *guehdr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!NAPI_GRO_CB(p)->same_flow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) guehdr2 = (struct guehdr *)(p->data + off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* Compare base GUE header to be equal (covers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * hlen, version, proto_ctype, and flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (guehdr->word != guehdr2->word) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) NAPI_GRO_CB(p)->same_flow = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* Compare optional fields are the same. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (guehdr->hlen && memcmp(&guehdr[1], &guehdr2[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) guehdr->hlen << 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) NAPI_GRO_CB(p)->same_flow = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) proto = guehdr->proto_ctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) next_proto:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /* We can clear the encap_mark for GUE as we are essentially doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * one of two possible things. We are either adding an L4 tunnel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * header to the outer L3 tunnel header, or we are simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * treating the GRE tunnel header as though it is a UDP protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * specific header such as VXLAN or GENEVE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) NAPI_GRO_CB(skb)->encap_mark = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* Flag this frame as already having an outer encap header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) NAPI_GRO_CB(skb)->is_fou = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ops = rcu_dereference(offloads[proto]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) flush = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static int gue_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) const struct net_offload **offloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct guehdr *guehdr = (struct guehdr *)(skb->data + nhoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) const struct net_offload *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) unsigned int guehlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) u8 proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) switch (guehdr->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) proto = guehdr->proto_ctype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) guehlen = sizeof(*guehdr) + (guehdr->hlen << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) switch (((struct iphdr *)guehdr)->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) proto = IPPROTO_IPIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) proto = IPPROTO_IPV6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ops = rcu_dereference(offloads[proto]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (WARN_ON(!ops || !ops->callbacks.gro_complete))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) err = ops->callbacks.gro_complete(skb, nhoff + guehlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) skb_set_inner_mac_header(skb, nhoff + guehlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static bool fou_cfg_cmp(struct fou *fou, struct fou_cfg *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct sock *sk = fou->sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct udp_port_cfg *udp_cfg = &cfg->udp_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (fou->family != udp_cfg->family ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) fou->port != udp_cfg->local_udp_port ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) sk->sk_dport != udp_cfg->peer_udp_port ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) sk->sk_bound_dev_if != udp_cfg->bind_ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (fou->family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (sk->sk_rcv_saddr != udp_cfg->local_ip.s_addr ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) sk->sk_daddr != udp_cfg->peer_ip.s_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (ipv6_addr_cmp(&sk->sk_v6_rcv_saddr, &udp_cfg->local_ip6) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ipv6_addr_cmp(&sk->sk_v6_daddr, &udp_cfg->peer_ip6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int fou_add_to_port_list(struct net *net, struct fou *fou,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct fou_cfg *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct fou_net *fn = net_generic(net, fou_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct fou *fout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) mutex_lock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) list_for_each_entry(fout, &fn->fou_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (fou_cfg_cmp(fout, cfg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) mutex_unlock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) list_add(&fou->list, &fn->fou_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mutex_unlock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static void fou_release(struct fou *fou)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct socket *sock = fou->sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) list_del(&fou->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) udp_tunnel_sock_release(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) kfree_rcu(fou, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static int fou_create(struct net *net, struct fou_cfg *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct socket **sockp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct socket *sock = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct fou *fou = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct udp_tunnel_sock_cfg tunnel_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /* Open UDP socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) err = udp_sock_create(net, &cfg->udp_config, &sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* Allocate FOU port structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) fou = kzalloc(sizeof(*fou), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (!fou) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) fou->port = cfg->udp_config.local_udp_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) fou->family = cfg->udp_config.family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) fou->flags = cfg->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) fou->type = cfg->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) fou->sock = sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) tunnel_cfg.encap_type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) tunnel_cfg.sk_user_data = fou;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) tunnel_cfg.encap_destroy = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* Initial for fou type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) switch (cfg->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) case FOU_ENCAP_DIRECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) tunnel_cfg.encap_rcv = fou_udp_recv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) tunnel_cfg.gro_receive = fou_gro_receive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) tunnel_cfg.gro_complete = fou_gro_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) fou->protocol = cfg->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case FOU_ENCAP_GUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) tunnel_cfg.encap_rcv = gue_udp_recv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) tunnel_cfg.gro_receive = gue_gro_receive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) tunnel_cfg.gro_complete = gue_gro_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) sk->sk_allocation = GFP_ATOMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) err = fou_add_to_port_list(net, fou, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (sockp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) *sockp = sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) kfree(fou);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) udp_tunnel_sock_release(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int fou_destroy(struct net *net, struct fou_cfg *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct fou_net *fn = net_generic(net, fou_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) struct fou *fou;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) mutex_lock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) list_for_each_entry(fou, &fn->fou_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (fou_cfg_cmp(fou, cfg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) fou_release(fou);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) mutex_unlock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static struct genl_family fou_nl_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static const struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) [FOU_ATTR_PORT] = { .type = NLA_U16, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) [FOU_ATTR_AF] = { .type = NLA_U8, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) [FOU_ATTR_IPPROTO] = { .type = NLA_U8, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) [FOU_ATTR_TYPE] = { .type = NLA_U8, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) [FOU_ATTR_LOCAL_V4] = { .type = NLA_U32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) [FOU_ATTR_PEER_V4] = { .type = NLA_U32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) [FOU_ATTR_LOCAL_V6] = { .len = sizeof(struct in6_addr), },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) [FOU_ATTR_PEER_V6] = { .len = sizeof(struct in6_addr), },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) [FOU_ATTR_PEER_PORT] = { .type = NLA_U16, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) [FOU_ATTR_IFINDEX] = { .type = NLA_S32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) static int parse_nl_config(struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct fou_cfg *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) bool has_local = false, has_peer = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) __be16 port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) memset(cfg, 0, sizeof(*cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) cfg->udp_config.family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (info->attrs[FOU_ATTR_AF]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) u8 family = nla_get_u8(info->attrs[FOU_ATTR_AF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) switch (family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) cfg->udp_config.ipv6_v6only = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) cfg->udp_config.family = family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (info->attrs[FOU_ATTR_PORT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) port = nla_get_be16(info->attrs[FOU_ATTR_PORT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) cfg->udp_config.local_udp_port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (info->attrs[FOU_ATTR_IPPROTO])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) cfg->protocol = nla_get_u8(info->attrs[FOU_ATTR_IPPROTO]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (info->attrs[FOU_ATTR_TYPE])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (info->attrs[FOU_ATTR_REMCSUM_NOPARTIAL])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) cfg->flags |= FOU_F_REMCSUM_NOPARTIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (cfg->udp_config.family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (info->attrs[FOU_ATTR_LOCAL_V4]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) attr = info->attrs[FOU_ATTR_LOCAL_V4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) cfg->udp_config.local_ip.s_addr = nla_get_in_addr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) has_local = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (info->attrs[FOU_ATTR_PEER_V4]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) attr = info->attrs[FOU_ATTR_PEER_V4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) cfg->udp_config.peer_ip.s_addr = nla_get_in_addr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) has_peer = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (info->attrs[FOU_ATTR_LOCAL_V6]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) attr = info->attrs[FOU_ATTR_LOCAL_V6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) cfg->udp_config.local_ip6 = nla_get_in6_addr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) has_local = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (info->attrs[FOU_ATTR_PEER_V6]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) attr = info->attrs[FOU_ATTR_PEER_V6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) cfg->udp_config.peer_ip6 = nla_get_in6_addr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) has_peer = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (has_peer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (info->attrs[FOU_ATTR_PEER_PORT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) port = nla_get_be16(info->attrs[FOU_ATTR_PEER_PORT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) cfg->udp_config.peer_udp_port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (info->attrs[FOU_ATTR_IFINDEX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (!has_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) ifindex = nla_get_s32(info->attrs[FOU_ATTR_IFINDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) cfg->udp_config.bind_ifindex = ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct net *net = genl_info_net(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct fou_cfg cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) err = parse_nl_config(info, &cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return fou_create(net, &cfg, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static int fou_nl_cmd_rm_port(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct net *net = genl_info_net(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct fou_cfg cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) err = parse_nl_config(info, &cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return fou_destroy(net, &cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static int fou_fill_info(struct fou *fou, struct sk_buff *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct sock *sk = fou->sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (nla_put_u8(msg, FOU_ATTR_AF, fou->sock->sk->sk_family) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) nla_put_be16(msg, FOU_ATTR_PORT, fou->port) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) nla_put_be16(msg, FOU_ATTR_PEER_PORT, sk->sk_dport) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) nla_put_u8(msg, FOU_ATTR_IPPROTO, fou->protocol) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) nla_put_u8(msg, FOU_ATTR_TYPE, fou->type) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) nla_put_s32(msg, FOU_ATTR_IFINDEX, sk->sk_bound_dev_if))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (fou->flags & FOU_F_REMCSUM_NOPARTIAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (nla_put_flag(msg, FOU_ATTR_REMCSUM_NOPARTIAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (fou->sock->sk->sk_family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (nla_put_in_addr(msg, FOU_ATTR_LOCAL_V4, sk->sk_rcv_saddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (nla_put_in_addr(msg, FOU_ATTR_PEER_V4, sk->sk_daddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (nla_put_in6_addr(msg, FOU_ATTR_LOCAL_V6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) &sk->sk_v6_rcv_saddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (nla_put_in6_addr(msg, FOU_ATTR_PEER_V6, &sk->sk_v6_daddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) static int fou_dump_info(struct fou *fou, u32 portid, u32 seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) u32 flags, struct sk_buff *skb, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) hdr = genlmsg_put(skb, portid, seq, &fou_nl_family, flags, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (fou_fill_info(fou, skb) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) genlmsg_end(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) genlmsg_cancel(skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static int fou_nl_cmd_get_port(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct net *net = genl_info_net(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct fou_net *fn = net_generic(net, fou_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct sk_buff *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct fou_cfg cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct fou *fout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) __be16 port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) u8 family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) ret = parse_nl_config(info, &cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) port = cfg.udp_config.local_udp_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (port == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) family = cfg.udp_config.family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (family != AF_INET && family != AF_INET6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (!msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) ret = -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) mutex_lock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) list_for_each_entry(fout, &fn->fou_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (fou_cfg_cmp(fout, &cfg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ret = fou_dump_info(fout, info->snd_portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) info->snd_seq, 0, msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) info->genlhdr->cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) mutex_unlock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return genlmsg_reply(msg, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) nlmsg_free(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int fou_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct fou_net *fn = net_generic(net, fou_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct fou *fout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int idx = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) mutex_lock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) list_for_each_entry(fout, &fn->fou_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (idx++ < cb->args[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ret = fou_dump_info(fout, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) cb->nlh->nlmsg_seq, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) skb, FOU_CMD_GET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) mutex_unlock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) cb->args[0] = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static const struct genl_small_ops fou_nl_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .cmd = FOU_CMD_ADD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) .doit = fou_nl_cmd_add_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .cmd = FOU_CMD_DEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .doit = fou_nl_cmd_rm_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .cmd = FOU_CMD_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) .doit = fou_nl_cmd_get_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) .dumpit = fou_nl_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static struct genl_family fou_nl_family __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) .hdrsize = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) .name = FOU_GENL_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) .version = FOU_GENL_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .maxattr = FOU_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .policy = fou_nl_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .netnsok = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) .small_ops = fou_nl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) .n_small_ops = ARRAY_SIZE(fou_nl_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) size_t fou_encap_hlen(struct ip_tunnel_encap *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return sizeof(struct udphdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) EXPORT_SYMBOL(fou_encap_hlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) size_t gue_encap_hlen(struct ip_tunnel_encap *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) bool need_priv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) len = sizeof(struct udphdr) + sizeof(struct guehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) len += GUE_PLEN_REMCSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) need_priv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) len += need_priv ? GUE_LEN_PRIV : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) EXPORT_SYMBOL(gue_encap_hlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) int __fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) u8 *protocol, __be16 *sport, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) err = iptunnel_handle_offloads(skb, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) *sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) skb, 0, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) EXPORT_SYMBOL(__fou_build_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) int __gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) u8 *protocol, __be16 *sport, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct guehdr *guehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) size_t hdrlen, optlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) bool need_priv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if ((e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) skb->ip_summed == CHECKSUM_PARTIAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) optlen += GUE_PLEN_REMCSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) type |= SKB_GSO_TUNNEL_REMCSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) need_priv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) optlen += need_priv ? GUE_LEN_PRIV : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) err = iptunnel_handle_offloads(skb, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) /* Get source port (based on flow hash) before skb_push */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) *sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) skb, 0, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) hdrlen = sizeof(struct guehdr) + optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) skb_push(skb, hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) guehdr = (struct guehdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) guehdr->control = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) guehdr->version = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) guehdr->hlen = optlen >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) guehdr->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) guehdr->proto_ctype = *protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) data = &guehdr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (need_priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) __be32 *flags = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) guehdr->flags |= GUE_FLAG_PRIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) *flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) data += GUE_LEN_PRIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (type & SKB_GSO_TUNNEL_REMCSUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) u16 csum_start = skb_checksum_start_offset(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) __be16 *pd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (csum_start < hdrlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) csum_start -= hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) pd[0] = htons(csum_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) pd[1] = htons(csum_start + skb->csum_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (!skb_is_gso(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) skb->ip_summed = CHECKSUM_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) skb->encapsulation = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) *flags |= GUE_PFLAG_REMCSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) data += GUE_PLEN_REMCSUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) EXPORT_SYMBOL(__gue_build_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) #ifdef CONFIG_NET_FOU_IP_TUNNELS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static void fou_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct flowi4 *fl4, u8 *protocol, __be16 sport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) struct udphdr *uh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) skb_push(skb, sizeof(struct udphdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) uh = udp_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) uh->dest = e->dport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) uh->source = sport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) uh->len = htons(skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) fl4->saddr, fl4->daddr, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) *protocol = IPPROTO_UDP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) static int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) u8 *protocol, struct flowi4 *fl4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) SKB_GSO_UDP_TUNNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) __be16 sport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) err = __fou_build_header(skb, e, protocol, &sport, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) fou_build_udp(skb, e, fl4, protocol, sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) static int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) u8 *protocol, struct flowi4 *fl4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) SKB_GSO_UDP_TUNNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) __be16 sport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) err = __gue_build_header(skb, e, protocol, &sport, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) fou_build_udp(skb, e, fl4, protocol, sport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) static int gue_err_proto_handler(int proto, struct sk_buff *skb, u32 info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) const struct net_protocol *ipprot = rcu_dereference(inet_protos[proto]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (ipprot && ipprot->err_handler) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (!ipprot->err_handler(skb, info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) static int gue_err(struct sk_buff *skb, u32 info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) int transport_offset = skb_transport_offset(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) struct guehdr *guehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) size_t len, optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) len = sizeof(struct udphdr) + sizeof(struct guehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (!pskb_may_pull(skb, transport_offset + len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) guehdr = (struct guehdr *)&udp_hdr(skb)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) switch (guehdr->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) case 0: /* Full GUE header present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) case 1: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /* Direct encapsulation of IPv4 or IPv6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) skb_set_transport_header(skb, -(int)sizeof(struct icmphdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) switch (((struct iphdr *)guehdr)->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) ret = gue_err_proto_handler(IPPROTO_IPIP, skb, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) ret = gue_err_proto_handler(IPPROTO_IPV6, skb, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) ret = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) default: /* Undefined version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (guehdr->control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) optlen = guehdr->hlen << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (!pskb_may_pull(skb, transport_offset + len + optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) guehdr = (struct guehdr *)&udp_hdr(skb)[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (validate_gue_flags(guehdr, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* Handling exceptions for direct UDP encapsulation in GUE would lead to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * recursion. Besides, this kind of encapsulation can't even be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * configured currently. Discard this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (guehdr->proto_ctype == IPPROTO_UDP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) guehdr->proto_ctype == IPPROTO_UDPLITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) skb_set_transport_header(skb, -(int)sizeof(struct icmphdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) ret = gue_err_proto_handler(guehdr->proto_ctype, skb, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) skb_set_transport_header(skb, transport_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static const struct ip_tunnel_encap_ops fou_iptun_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) .encap_hlen = fou_encap_hlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) .build_header = fou_build_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) .err_handler = gue_err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) static const struct ip_tunnel_encap_ops gue_iptun_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) .encap_hlen = gue_encap_hlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) .build_header = gue_build_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) .err_handler = gue_err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) static int ip_tunnel_encap_add_fou_ops(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) ret = ip_tunnel_encap_add_ops(&fou_iptun_ops, TUNNEL_ENCAP_FOU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) pr_err("can't add fou ops\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) ret = ip_tunnel_encap_add_ops(&gue_iptun_ops, TUNNEL_ENCAP_GUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) pr_err("can't add gue ops\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) ip_tunnel_encap_del_ops(&fou_iptun_ops, TUNNEL_ENCAP_FOU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) static void ip_tunnel_encap_del_fou_ops(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) ip_tunnel_encap_del_ops(&fou_iptun_ops, TUNNEL_ENCAP_FOU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) ip_tunnel_encap_del_ops(&gue_iptun_ops, TUNNEL_ENCAP_GUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static int ip_tunnel_encap_add_fou_ops(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) static void ip_tunnel_encap_del_fou_ops(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) static __net_init int fou_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) struct fou_net *fn = net_generic(net, fou_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) INIT_LIST_HEAD(&fn->fou_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) mutex_init(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) static __net_exit void fou_exit_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) struct fou_net *fn = net_generic(net, fou_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) struct fou *fou, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /* Close all the FOU sockets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) mutex_lock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) list_for_each_entry_safe(fou, next, &fn->fou_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) fou_release(fou);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) mutex_unlock(&fn->fou_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) static struct pernet_operations fou_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) .init = fou_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) .exit = fou_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) .id = &fou_net_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) .size = sizeof(struct fou_net),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) static int __init fou_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) ret = register_pernet_device(&fou_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) ret = genl_register_family(&fou_nl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) goto unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) ret = ip_tunnel_encap_add_fou_ops();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) genl_unregister_family(&fou_nl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) unregister_pernet_device(&fou_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) static void __exit fou_fini(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) ip_tunnel_encap_del_fou_ops();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) genl_unregister_family(&fou_nl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) unregister_pernet_device(&fou_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) module_init(fou_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) module_exit(fou_fini);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) MODULE_DESCRIPTION("Foo over UDP");