]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - net/ipv6/netfilter/nf_socket_ipv6.c
2 * Copyright (C) 2007-2008 BalaBit IT Ltd.
3 * Author: Krisztian Kovacs
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #include <linux/module.h>
12 #include <linux/skbuff.h>
17 #include <net/inet_sock.h>
18 #include <net/inet6_hashtables.h>
19 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
20 #include <net/netfilter/nf_socket.h>
21 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
22 #include <net/netfilter/nf_conntrack.h>
26 extract_icmp6_fields(const struct sk_buff
*skb
,
27 unsigned int outside_hdrlen
,
29 const struct in6_addr
**raddr
,
30 const struct in6_addr
**laddr
,
33 struct ipv6hdr
*ipv6_var
)
35 const struct ipv6hdr
*inside_iph
;
36 struct icmp6hdr
*icmph
, _icmph
;
37 __be16
*ports
, _ports
[2];
39 __be16 inside_fragoff
;
42 icmph
= skb_header_pointer(skb
, outside_hdrlen
,
43 sizeof(_icmph
), &_icmph
);
47 if (icmph
->icmp6_type
& ICMPV6_INFOMSG_MASK
)
50 inside_iph
= skb_header_pointer(skb
, outside_hdrlen
+ sizeof(_icmph
),
51 sizeof(*ipv6_var
), ipv6_var
);
52 if (inside_iph
== NULL
)
54 inside_nexthdr
= inside_iph
->nexthdr
;
56 inside_hdrlen
= ipv6_skip_exthdr(skb
, outside_hdrlen
+ sizeof(_icmph
) +
58 &inside_nexthdr
, &inside_fragoff
);
59 if (inside_hdrlen
< 0)
60 return 1; /* hjm: Packet has no/incomplete transport layer headers. */
62 if (inside_nexthdr
!= IPPROTO_TCP
&&
63 inside_nexthdr
!= IPPROTO_UDP
)
66 ports
= skb_header_pointer(skb
, inside_hdrlen
,
67 sizeof(_ports
), &_ports
);
71 /* the inside IP packet is the one quoted from our side, thus
72 * its saddr is the local address */
73 *protocol
= inside_nexthdr
;
74 *laddr
= &inside_iph
->saddr
;
76 *raddr
= &inside_iph
->daddr
;
83 nf_socket_get_sock_v6(struct net
*net
, struct sk_buff
*skb
, int doff
,
85 const struct in6_addr
*saddr
, const struct in6_addr
*daddr
,
86 const __be16 sport
, const __be16 dport
,
87 const struct net_device
*in
)
91 return inet6_lookup(net
, &tcp_hashinfo
, skb
, doff
,
92 saddr
, sport
, daddr
, dport
,
95 return udp6_lib_lookup(net
, saddr
, sport
, daddr
, dport
,
102 struct sock
*nf_sk_lookup_slow_v6(struct net
*net
, const struct sk_buff
*skb
,
103 const struct net_device
*indev
)
105 __be16
uninitialized_var(dport
), uninitialized_var(sport
);
106 const struct in6_addr
*daddr
= NULL
, *saddr
= NULL
;
107 struct ipv6hdr
*iph
= ipv6_hdr(skb
);
108 struct sk_buff
*data_skb
= NULL
;
110 int thoff
= 0, tproto
;
112 tproto
= ipv6_find_hdr(skb
, &thoff
, -1, NULL
, NULL
);
114 pr_debug("unable to find transport header in IPv6 packet, dropping\n");
118 if (tproto
== IPPROTO_UDP
|| tproto
== IPPROTO_TCP
) {
119 struct udphdr _hdr
, *hp
;
121 hp
= skb_header_pointer(skb
, thoff
, sizeof(_hdr
), &_hdr
);
129 data_skb
= (struct sk_buff
*)skb
;
130 doff
= tproto
== IPPROTO_TCP
?
131 thoff
+ __tcp_hdrlen((struct tcphdr
*)hp
) :
134 } else if (tproto
== IPPROTO_ICMPV6
) {
135 struct ipv6hdr ipv6_var
;
137 if (extract_icmp6_fields(skb
, thoff
, &tproto
, &saddr
, &daddr
,
138 &sport
, &dport
, &ipv6_var
))
144 return nf_socket_get_sock_v6(net
, data_skb
, doff
, tproto
, saddr
, daddr
,
145 sport
, dport
, indev
);
147 EXPORT_SYMBOL_GPL(nf_sk_lookup_slow_v6
);
149 MODULE_LICENSE("GPL");
150 MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
151 MODULE_DESCRIPTION("Netfilter IPv6 socket lookup infrastructure");