]>
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/nf_socket.h>
16 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
17 #include <net/netfilter/nf_conntrack.h>
21 extract_icmp6_fields(const struct sk_buff
*skb
,
22 unsigned int outside_hdrlen
,
24 const struct in6_addr
**raddr
,
25 const struct in6_addr
**laddr
,
28 struct ipv6hdr
*ipv6_var
)
30 const struct ipv6hdr
*inside_iph
;
31 struct icmp6hdr
*icmph
, _icmph
;
32 __be16
*ports
, _ports
[2];
34 __be16 inside_fragoff
;
37 icmph
= skb_header_pointer(skb
, outside_hdrlen
,
38 sizeof(_icmph
), &_icmph
);
42 if (icmph
->icmp6_type
& ICMPV6_INFOMSG_MASK
)
45 inside_iph
= skb_header_pointer(skb
, outside_hdrlen
+ sizeof(_icmph
),
46 sizeof(*ipv6_var
), ipv6_var
);
47 if (inside_iph
== NULL
)
49 inside_nexthdr
= inside_iph
->nexthdr
;
51 inside_hdrlen
= ipv6_skip_exthdr(skb
, outside_hdrlen
+ sizeof(_icmph
) +
53 &inside_nexthdr
, &inside_fragoff
);
54 if (inside_hdrlen
< 0)
55 return 1; /* hjm: Packet has no/incomplete transport layer headers. */
57 if (inside_nexthdr
!= IPPROTO_TCP
&&
58 inside_nexthdr
!= IPPROTO_UDP
)
61 ports
= skb_header_pointer(skb
, inside_hdrlen
,
62 sizeof(_ports
), &_ports
);
66 /* the inside IP packet is the one quoted from our side, thus
67 * its saddr is the local address */
68 *protocol
= inside_nexthdr
;
69 *laddr
= &inside_iph
->saddr
;
71 *raddr
= &inside_iph
->daddr
;
78 nf_socket_get_sock_v6(struct net
*net
, struct sk_buff
*skb
, int doff
,
80 const struct in6_addr
*saddr
, const struct in6_addr
*daddr
,
81 const __be16 sport
, const __be16 dport
,
82 const struct net_device
*in
)
86 return inet6_lookup(net
, &tcp_hashinfo
, skb
, doff
,
87 saddr
, sport
, daddr
, dport
,
90 return udp6_lib_lookup(net
, saddr
, sport
, daddr
, dport
,
97 struct sock
*nf_sk_lookup_slow_v6(struct net
*net
, const struct sk_buff
*skb
,
98 const struct net_device
*indev
)
100 __be16
uninitialized_var(dport
), uninitialized_var(sport
);
101 const struct in6_addr
*daddr
= NULL
, *saddr
= NULL
;
102 struct ipv6hdr
*iph
= ipv6_hdr(skb
);
103 struct sk_buff
*data_skb
= NULL
;
105 int thoff
= 0, tproto
;
107 tproto
= ipv6_find_hdr(skb
, &thoff
, -1, NULL
, NULL
);
109 pr_debug("unable to find transport header in IPv6 packet, dropping\n");
113 if (tproto
== IPPROTO_UDP
|| tproto
== IPPROTO_TCP
) {
117 hp
= skb_header_pointer(skb
, thoff
, tproto
== IPPROTO_UDP
?
118 sizeof(*hp
) : sizeof(_hdr
), &_hdr
);
126 data_skb
= (struct sk_buff
*)skb
;
127 doff
= tproto
== IPPROTO_TCP
?
128 thoff
+ __tcp_hdrlen((struct tcphdr
*)hp
) :
131 } else if (tproto
== IPPROTO_ICMPV6
) {
132 struct ipv6hdr ipv6_var
;
134 if (extract_icmp6_fields(skb
, thoff
, &tproto
, &saddr
, &daddr
,
135 &sport
, &dport
, &ipv6_var
))
141 return nf_socket_get_sock_v6(net
, data_skb
, doff
, tproto
, saddr
, daddr
,
142 sport
, dport
, indev
);
144 EXPORT_SYMBOL_GPL(nf_sk_lookup_slow_v6
);
146 MODULE_LICENSE("GPL");
147 MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
148 MODULE_DESCRIPTION("Netfilter IPv6 socket lookup infrastructure");