]>
git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - net/ipv6/netfilter/nf_socket_ipv6.c
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2007-2008 BalaBit IT Ltd.
4 * Author: Krisztian Kovacs
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7 #include <linux/module.h>
8 #include <linux/skbuff.h>
13 #include <net/inet_sock.h>
14 #include <net/inet6_hashtables.h>
15 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
16 #include <net/netfilter/nf_socket.h>
17 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
18 #include <net/netfilter/nf_conntrack.h>
22 extract_icmp6_fields(const struct sk_buff
*skb
,
23 unsigned int outside_hdrlen
,
25 const struct in6_addr
**raddr
,
26 const struct in6_addr
**laddr
,
29 struct ipv6hdr
*ipv6_var
)
31 const struct ipv6hdr
*inside_iph
;
32 struct icmp6hdr
*icmph
, _icmph
;
33 __be16
*ports
, _ports
[2];
35 __be16 inside_fragoff
;
38 icmph
= skb_header_pointer(skb
, outside_hdrlen
,
39 sizeof(_icmph
), &_icmph
);
43 if (icmph
->icmp6_type
& ICMPV6_INFOMSG_MASK
)
46 inside_iph
= skb_header_pointer(skb
, outside_hdrlen
+ sizeof(_icmph
),
47 sizeof(*ipv6_var
), ipv6_var
);
48 if (inside_iph
== NULL
)
50 inside_nexthdr
= inside_iph
->nexthdr
;
52 inside_hdrlen
= ipv6_skip_exthdr(skb
, outside_hdrlen
+ sizeof(_icmph
) +
54 &inside_nexthdr
, &inside_fragoff
);
55 if (inside_hdrlen
< 0)
56 return 1; /* hjm: Packet has no/incomplete transport layer headers. */
58 if (inside_nexthdr
!= IPPROTO_TCP
&&
59 inside_nexthdr
!= IPPROTO_UDP
)
62 ports
= skb_header_pointer(skb
, inside_hdrlen
,
63 sizeof(_ports
), &_ports
);
67 /* the inside IP packet is the one quoted from our side, thus
68 * its saddr is the local address */
69 *protocol
= inside_nexthdr
;
70 *laddr
= &inside_iph
->saddr
;
72 *raddr
= &inside_iph
->daddr
;
79 nf_socket_get_sock_v6(struct net
*net
, struct sk_buff
*skb
, int doff
,
81 const struct in6_addr
*saddr
, const struct in6_addr
*daddr
,
82 const __be16 sport
, const __be16 dport
,
83 const struct net_device
*in
)
87 return inet6_lookup(net
, &tcp_hashinfo
, skb
, doff
,
88 saddr
, sport
, daddr
, dport
,
91 return udp6_lib_lookup(net
, saddr
, sport
, daddr
, dport
,
98 struct sock
*nf_sk_lookup_slow_v6(struct net
*net
, const struct sk_buff
*skb
,
99 const struct net_device
*indev
)
101 __be16
uninitialized_var(dport
), uninitialized_var(sport
);
102 const struct in6_addr
*daddr
= NULL
, *saddr
= NULL
;
103 struct ipv6hdr
*iph
= ipv6_hdr(skb
);
104 struct sk_buff
*data_skb
= NULL
;
106 int thoff
= 0, tproto
;
108 tproto
= ipv6_find_hdr(skb
, &thoff
, -1, NULL
, NULL
);
110 pr_debug("unable to find transport header in IPv6 packet, dropping\n");
114 if (tproto
== IPPROTO_UDP
|| tproto
== IPPROTO_TCP
) {
118 hp
= skb_header_pointer(skb
, thoff
, tproto
== IPPROTO_UDP
?
119 sizeof(*hp
) : sizeof(_hdr
), &_hdr
);
127 data_skb
= (struct sk_buff
*)skb
;
128 doff
= tproto
== IPPROTO_TCP
?
129 thoff
+ __tcp_hdrlen((struct tcphdr
*)hp
) :
132 } else if (tproto
== IPPROTO_ICMPV6
) {
133 struct ipv6hdr ipv6_var
;
135 if (extract_icmp6_fields(skb
, thoff
, &tproto
, &saddr
, &daddr
,
136 &sport
, &dport
, &ipv6_var
))
142 return nf_socket_get_sock_v6(net
, data_skb
, doff
, tproto
, saddr
, daddr
,
143 sport
, dport
, indev
);
145 EXPORT_SYMBOL_GPL(nf_sk_lookup_slow_v6
);
147 MODULE_LICENSE("GPL");
148 MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
149 MODULE_DESCRIPTION("Netfilter IPv6 socket lookup infrastructure");