xref: /linux/net/ipv4/netfilter.c (revision 606d099cdd1080bbb50ea50dc52d98252f8f10a1)
1 /* IPv4 specific functions of netfilter core */
2 #include <linux/kernel.h>
3 #include <linux/netfilter.h>
4 #include <linux/netfilter_ipv4.h>
5 #include <linux/ip.h>
6 #include <net/route.h>
7 #include <net/xfrm.h>
8 #include <net/ip.h>
9 
10 /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
11 int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
12 {
13 	struct iphdr *iph = (*pskb)->nh.iph;
14 	struct rtable *rt;
15 	struct flowi fl = {};
16 	struct dst_entry *odst;
17 	unsigned int hh_len;
18 
19 	if (addr_type == RTN_UNSPEC)
20 		addr_type = inet_addr_type(iph->saddr);
21 
22 	/* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
23 	 * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
24 	 */
25 	if (addr_type == RTN_LOCAL) {
26 		fl.nl_u.ip4_u.daddr = iph->daddr;
27 		fl.nl_u.ip4_u.saddr = iph->saddr;
28 		fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
29 		fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
30 		fl.mark = (*pskb)->mark;
31 		if (ip_route_output_key(&rt, &fl) != 0)
32 			return -1;
33 
34 		/* Drop old route. */
35 		dst_release((*pskb)->dst);
36 		(*pskb)->dst = &rt->u.dst;
37 	} else {
38 		/* non-local src, find valid iif to satisfy
39 		 * rp-filter when calling ip_route_input. */
40 		fl.nl_u.ip4_u.daddr = iph->saddr;
41 		if (ip_route_output_key(&rt, &fl) != 0)
42 			return -1;
43 
44 		odst = (*pskb)->dst;
45 		if (ip_route_input(*pskb, iph->daddr, iph->saddr,
46 				   RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
47 			dst_release(&rt->u.dst);
48 			return -1;
49 		}
50 		dst_release(&rt->u.dst);
51 		dst_release(odst);
52 	}
53 
54 	if ((*pskb)->dst->error)
55 		return -1;
56 
57 #ifdef CONFIG_XFRM
58 	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) &&
59 	    xfrm_decode_session(*pskb, &fl, AF_INET) == 0)
60 		if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0))
61 			return -1;
62 #endif
63 
64 	/* Change in oif may mean change in hh_len. */
65 	hh_len = (*pskb)->dst->dev->hard_header_len;
66 	if (skb_headroom(*pskb) < hh_len) {
67 		struct sk_buff *nskb;
68 
69 		nskb = skb_realloc_headroom(*pskb, hh_len);
70 		if (!nskb)
71 			return -1;
72 		if ((*pskb)->sk)
73 			skb_set_owner_w(nskb, (*pskb)->sk);
74 		kfree_skb(*pskb);
75 		*pskb = nskb;
76 	}
77 
78 	return 0;
79 }
80 EXPORT_SYMBOL(ip_route_me_harder);
81 
82 #ifdef CONFIG_XFRM
83 int ip_xfrm_me_harder(struct sk_buff **pskb)
84 {
85 	struct flowi fl;
86 	unsigned int hh_len;
87 	struct dst_entry *dst;
88 
89 	if (IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)
90 		return 0;
91 	if (xfrm_decode_session(*pskb, &fl, AF_INET) < 0)
92 		return -1;
93 
94 	dst = (*pskb)->dst;
95 	if (dst->xfrm)
96 		dst = ((struct xfrm_dst *)dst)->route;
97 	dst_hold(dst);
98 
99 	if (xfrm_lookup(&dst, &fl, (*pskb)->sk, 0) < 0)
100 		return -1;
101 
102 	dst_release((*pskb)->dst);
103 	(*pskb)->dst = dst;
104 
105 	/* Change in oif may mean change in hh_len. */
106 	hh_len = (*pskb)->dst->dev->hard_header_len;
107 	if (skb_headroom(*pskb) < hh_len) {
108 		struct sk_buff *nskb;
109 
110 		nskb = skb_realloc_headroom(*pskb, hh_len);
111 		if (!nskb)
112 			return -1;
113 		if ((*pskb)->sk)
114 			skb_set_owner_w(nskb, (*pskb)->sk);
115 		kfree_skb(*pskb);
116 		*pskb = nskb;
117 	}
118 	return 0;
119 }
120 EXPORT_SYMBOL(ip_xfrm_me_harder);
121 #endif
122 
123 void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
124 EXPORT_SYMBOL(ip_nat_decode_session);
125 
126 /*
127  * Extra routing may needed on local out, as the QUEUE target never
128  * returns control to the table.
129  */
130 
131 struct ip_rt_info {
132 	__be32 daddr;
133 	__be32 saddr;
134 	u_int8_t tos;
135 };
136 
137 static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
138 {
139 	struct ip_rt_info *rt_info = nf_info_reroute(info);
140 
141 	if (info->hook == NF_IP_LOCAL_OUT) {
142 		const struct iphdr *iph = skb->nh.iph;
143 
144 		rt_info->tos = iph->tos;
145 		rt_info->daddr = iph->daddr;
146 		rt_info->saddr = iph->saddr;
147 	}
148 }
149 
150 static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
151 {
152 	const struct ip_rt_info *rt_info = nf_info_reroute(info);
153 
154 	if (info->hook == NF_IP_LOCAL_OUT) {
155 		struct iphdr *iph = (*pskb)->nh.iph;
156 
157 		if (!(iph->tos == rt_info->tos
158 		      && iph->daddr == rt_info->daddr
159 		      && iph->saddr == rt_info->saddr))
160 			return ip_route_me_harder(pskb, RTN_UNSPEC);
161 	}
162 	return 0;
163 }
164 
165 __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
166 			    unsigned int dataoff, u_int8_t protocol)
167 {
168 	struct iphdr *iph = skb->nh.iph;
169 	__sum16 csum = 0;
170 
171 	switch (skb->ip_summed) {
172 	case CHECKSUM_COMPLETE:
173 		if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
174 			break;
175 		if ((protocol == 0 && !csum_fold(skb->csum)) ||
176 		    !csum_tcpudp_magic(iph->saddr, iph->daddr,
177 			    	       skb->len - dataoff, protocol,
178 				       skb->csum)) {
179 			skb->ip_summed = CHECKSUM_UNNECESSARY;
180 			break;
181 		}
182 		/* fall through */
183 	case CHECKSUM_NONE:
184 		if (protocol == 0)
185 			skb->csum = 0;
186 		else
187 			skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
188 						       skb->len - dataoff,
189 						       protocol, 0);
190 		csum = __skb_checksum_complete(skb);
191 	}
192 	return csum;
193 }
194 
195 EXPORT_SYMBOL(nf_ip_checksum);
196 
197 static struct nf_afinfo nf_ip_afinfo = {
198 	.family		= AF_INET,
199 	.checksum	= nf_ip_checksum,
200 	.saveroute	= nf_ip_saveroute,
201 	.reroute	= nf_ip_reroute,
202 	.route_key_size	= sizeof(struct ip_rt_info),
203 };
204 
205 static int ipv4_netfilter_init(void)
206 {
207 	return nf_register_afinfo(&nf_ip_afinfo);
208 }
209 
210 static void ipv4_netfilter_fini(void)
211 {
212 	nf_unregister_afinfo(&nf_ip_afinfo);
213 }
214 
215 module_init(ipv4_netfilter_init);
216 module_exit(ipv4_netfilter_fini);
217