Blame view
net/ipv4/ip_fragment.c
20.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * * The IP fragmentation functionality. |
e905a9eda [NET] IPV4: Fix w... |
7 |
* |
1da177e4c Linux-2.6.12-rc2 |
8 |
* Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG> |
113aa838e net: Rationalise ... |
9 |
* Alan Cox <alan@lxorguk.ukuu.org.uk> |
1da177e4c Linux-2.6.12-rc2 |
10 11 12 13 14 15 16 17 18 19 20 21 |
* * Fixes: * Alan Cox : Split from ip.c , see ip_input.c for history. * David S. Miller : Begin massive cleanup... * Andi Kleen : Add sysctls. * xxxx : Overlapfrag bug. * Ultima : ip_expire() kernel panic. * Bill Hawes : Frag accounting and evictor fixes. * John McDonald : 0 length frag bug. * Alexey Kuznetsov: SMP races, threading, cleanup. * Patrick McHardy : LRU queue of frag heads for evictor. */ |
89cee8b1c [IPV4]: Safer rea... |
22 |
#include <linux/compiler.h> |
1da177e4c Linux-2.6.12-rc2 |
23 24 25 26 27 28 29 30 31 32 33 |
#include <linux/module.h> #include <linux/types.h> #include <linux/mm.h> #include <linux/jiffies.h> #include <linux/skbuff.h> #include <linux/list.h> #include <linux/ip.h> #include <linux/icmp.h> #include <linux/netdevice.h> #include <linux/jhash.h> #include <linux/random.h> |
5a0e3ad6a include cleanup: ... |
34 |
#include <linux/slab.h> |
e9017b551 IP: Send an ICMP ... |
35 36 |
#include <net/route.h> #include <net/dst.h> |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 40 |
#include <net/sock.h> #include <net/ip.h> #include <net/icmp.h> #include <net/checksum.h> |
89cee8b1c [IPV4]: Safer rea... |
41 |
#include <net/inetpeer.h> |
5ab11c98d [INET]: Move comm... |
42 |
#include <net/inet_frag.h> |
1da177e4c Linux-2.6.12-rc2 |
43 44 45 46 |
#include <linux/tcp.h> #include <linux/udp.h> #include <linux/inet.h> #include <linux/netfilter_ipv4.h> |
6623e3b24 ipv4: IP defragme... |
47 |
#include <net/inet_ecn.h> |
1da177e4c Linux-2.6.12-rc2 |
48 49 50 51 52 |
/* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6 * code now. If you change something here, _PLEASE_ update ipv6/reassembly.c * as well. Or notify me, at least. --ANK */ |
8d8354d2f [NETNS][FRAGS]: M... |
53 |
static int sysctl_ipfrag_max_dist __read_mostly = 64; |
89cee8b1c [IPV4]: Safer rea... |
54 |
|
1da177e4c Linux-2.6.12-rc2 |
55 56 57 58 59 |
struct ipfrag_skb_cb { struct inet_skb_parm h; int offset; }; |
fd3f8c4cb net: clean up net... |
60 |
#define FRAG_CB(skb) ((struct ipfrag_skb_cb *)((skb)->cb)) |
1da177e4c Linux-2.6.12-rc2 |
61 62 63 |
/* Describe an entry in the "incomplete datagrams" queue. */ struct ipq { |
5ab11c98d [INET]: Move comm... |
64 |
struct inet_frag_queue q; |
1da177e4c Linux-2.6.12-rc2 |
65 |
u32 user; |
182777700 [IPV4]: ip_fragme... |
66 67 68 |
__be32 saddr; __be32 daddr; __be16 id; |
1da177e4c Linux-2.6.12-rc2 |
69 |
u8 protocol; |
6623e3b24 ipv4: IP defragme... |
70 |
u8 ecn; /* RFC3168 support */ |
89cee8b1c [IPV4]: Safer rea... |
71 72 73 |
int iif; unsigned int rid; struct inet_peer *peer; |
1da177e4c Linux-2.6.12-rc2 |
74 |
}; |
5173cc057 ipv4: more compli... |
75 76 77 78 |
/* RFC 3168 support : * We want to check ECN values of all fragments, do detect invalid combinations. * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value. */ |
1d1652cbd ipv4: Don't use e... |
79 80 81 82 |
#define IPFRAG_ECN_NOT_ECT 0x01 /* one frag had ECN_NOT_ECT */ #define IPFRAG_ECN_ECT_1 0x02 /* one frag had ECN_ECT_1 */ #define IPFRAG_ECN_ECT_0 0x04 /* one frag had ECN_ECT_0 */ #define IPFRAG_ECN_CE 0x08 /* one frag had ECN_CE */ |
6623e3b24 ipv4: IP defragme... |
83 84 85 |
static inline u8 ip4_frag_ecn(u8 tos) { |
5173cc057 ipv4: more compli... |
86 |
return 1 << (tos & INET_ECN_MASK); |
6623e3b24 ipv4: IP defragme... |
87 |
} |
5173cc057 ipv4: more compli... |
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
/* Given the OR values of all fragments, apply RFC 3168 5.3 requirements * Value : 0xff if frame should be dropped. * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field */ static const u8 ip4_frag_ecn_table[16] = { /* at least one fragment had CE, and others ECT_0 or ECT_1 */ [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = INET_ECN_CE, [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = INET_ECN_CE, [IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = INET_ECN_CE, /* invalid combinations : drop frame */ [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE] = 0xff, [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0] = 0xff, [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_1] = 0xff, [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff, [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0] = 0xff, [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1] = 0xff, [IPFRAG_ECN_NOT_ECT | IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1] = 0xff, }; |
7eb95156d [INET]: Collect f... |
107 |
static struct inet_frags ip4_frags; |
1da177e4c Linux-2.6.12-rc2 |
108 |
|
e5a2bb842 [NETNS][FRAGS]: M... |
109 |
int ip_frag_nqueues(struct net *net) |
7eb95156d [INET]: Collect f... |
110 |
{ |
e5a2bb842 [NETNS][FRAGS]: M... |
111 |
return net->ipv4.frags.nqueues; |
7eb95156d [INET]: Collect f... |
112 |
} |
1da177e4c Linux-2.6.12-rc2 |
113 |
|
6ddc08222 [NETNS][FRAGS]: M... |
114 |
int ip_frag_mem(struct net *net) |
7eb95156d [INET]: Collect f... |
115 |
{ |
6ddc08222 [NETNS][FRAGS]: M... |
116 |
return atomic_read(&net->ipv4.frags.mem); |
7eb95156d [INET]: Collect f... |
117 |
} |
1da177e4c Linux-2.6.12-rc2 |
118 |
|
1706d5876 [IPV4]: Make ip_d... |
119 120 |
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, struct net_device *dev); |
c6fda2822 [INET]: Consolida... |
121 122 123 124 |
struct ip4_create_arg { struct iphdr *iph; u32 user; }; |
182777700 [IPV4]: ip_fragme... |
125 |
static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) |
1da177e4c Linux-2.6.12-rc2 |
126 |
{ |
182777700 [IPV4]: ip_fragme... |
127 128 |
return jhash_3words((__force u32)id << 16 | prot, (__force u32)saddr, (__force u32)daddr, |
7eb95156d [INET]: Collect f... |
129 |
ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1); |
1da177e4c Linux-2.6.12-rc2 |
130 |
} |
321a3a99e [INET]: Consolida... |
131 |
static unsigned int ip4_hashfn(struct inet_frag_queue *q) |
1da177e4c Linux-2.6.12-rc2 |
132 |
{ |
321a3a99e [INET]: Consolida... |
133 |
struct ipq *ipq; |
1da177e4c Linux-2.6.12-rc2 |
134 |
|
321a3a99e [INET]: Consolida... |
135 136 |
ipq = container_of(q, struct ipq, q); return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol); |
1da177e4c Linux-2.6.12-rc2 |
137 |
} |
abd6523d1 [INET]: Consolida... |
138 139 140 141 142 143 |
static int ip4_frag_match(struct inet_frag_queue *q, void *a) { struct ipq *qp; struct ip4_create_arg *arg = a; qp = container_of(q, struct ipq, q); |
a02cec215 net: return opera... |
144 |
return qp->id == arg->iph->id && |
abd6523d1 [INET]: Consolida... |
145 146 147 |
qp->saddr == arg->iph->saddr && qp->daddr == arg->iph->daddr && qp->protocol == arg->iph->protocol && |
a02cec215 net: return opera... |
148 |
qp->user == arg->user; |
abd6523d1 [INET]: Consolida... |
149 |
} |
1da177e4c Linux-2.6.12-rc2 |
150 |
/* Memory Tracking Functions. */ |
a95d8c88b ipfrag : frag_kfr... |
151 |
static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
152 |
{ |
6ddc08222 [NETNS][FRAGS]: M... |
153 |
atomic_sub(skb->truesize, &nf->mem); |
1da177e4c Linux-2.6.12-rc2 |
154 155 |
kfree_skb(skb); } |
c6fda2822 [INET]: Consolida... |
156 157 158 159 160 161 162 |
static void ip4_frag_init(struct inet_frag_queue *q, void *a) { struct ipq *qp = container_of(q, struct ipq, q); struct ip4_create_arg *arg = a; qp->protocol = arg->iph->protocol; qp->id = arg->iph->id; |
6623e3b24 ipv4: IP defragme... |
163 |
qp->ecn = ip4_frag_ecn(arg->iph->tos); |
c6fda2822 [INET]: Consolida... |
164 165 166 167 |
qp->saddr = arg->iph->saddr; qp->daddr = arg->iph->daddr; qp->user = arg->user; qp->peer = sysctl_ipfrag_max_dist ? |
b534ecf1c inetpeer: Make in... |
168 |
inet_getpeer_v4(arg->iph->saddr, 1) : NULL; |
c6fda2822 [INET]: Consolida... |
169 |
} |
1e4b82873 [INET]: Consolida... |
170 |
static __inline__ void ip4_frag_free(struct inet_frag_queue *q) |
1da177e4c Linux-2.6.12-rc2 |
171 |
{ |
1e4b82873 [INET]: Consolida... |
172 173 174 175 176 |
struct ipq *qp; qp = container_of(q, struct ipq, q); if (qp->peer) inet_putpeer(qp->peer); |
1da177e4c Linux-2.6.12-rc2 |
177 |
} |
1da177e4c Linux-2.6.12-rc2 |
178 179 |
/* Destruction primitives. */ |
4b6cb5d8e [INET]: Small cle... |
180 |
static __inline__ void ipq_put(struct ipq *ipq) |
1da177e4c Linux-2.6.12-rc2 |
181 |
{ |
762cc4080 [INET]: Consolida... |
182 |
inet_frag_put(&ipq->q, &ip4_frags); |
1da177e4c Linux-2.6.12-rc2 |
183 184 185 186 187 188 189 |
} /* Kill ipq entry. It is not destroyed immediately, * because caller (and someone more) holds reference count. */ static void ipq_kill(struct ipq *ipq) { |
277e650dd [INET]: Consolida... |
190 |
inet_frag_kill(&ipq->q, &ip4_frags); |
1da177e4c Linux-2.6.12-rc2 |
191 |
} |
e905a9eda [NET] IPV4: Fix w... |
192 |
/* Memory limiting on fragments. Evictor trashes the oldest |
1da177e4c Linux-2.6.12-rc2 |
193 194 |
* fragment queue until we are back under the threshold. */ |
6ddc08222 [NETNS][FRAGS]: M... |
195 |
static void ip_evictor(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
196 |
{ |
8e7999c44 [INET]: Consolida... |
197 |
int evicted; |
6ddc08222 [NETNS][FRAGS]: M... |
198 |
evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags); |
8e7999c44 [INET]: Consolida... |
199 |
if (evicted) |
c5346fe39 mib: add net to I... |
200 |
IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted); |
1da177e4c Linux-2.6.12-rc2 |
201 202 203 204 205 206 207 |
} /* * Oops, a fragment queue timed out. Kill it and send an ICMP reply. */ static void ip_expire(unsigned long arg) { |
e521db9d7 [INET]: Consolida... |
208 |
struct ipq *qp; |
84a3aa000 ipv4: prepare net... |
209 |
struct net *net; |
e521db9d7 [INET]: Consolida... |
210 211 |
qp = container_of((struct inet_frag_queue *) arg, struct ipq, q); |
84a3aa000 ipv4: prepare net... |
212 |
net = container_of(qp->q.net, struct net, ipv4.frags); |
1da177e4c Linux-2.6.12-rc2 |
213 |
|
5ab11c98d [INET]: Move comm... |
214 |
spin_lock(&qp->q.lock); |
1da177e4c Linux-2.6.12-rc2 |
215 |
|
bc578a54f [NET]: Rename ine... |
216 |
if (qp->q.last_in & INET_FRAG_COMPLETE) |
1da177e4c Linux-2.6.12-rc2 |
217 218 219 |
goto out; ipq_kill(qp); |
7c73a6faf mib: add net to I... |
220 221 |
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT); IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); |
1da177e4c Linux-2.6.12-rc2 |
222 |
|
bc578a54f [NET]: Rename ine... |
223 |
if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { |
5ab11c98d [INET]: Move comm... |
224 |
struct sk_buff *head = qp->q.fragments; |
64f3b9e20 net: ip_expire() ... |
225 226 |
const struct iphdr *iph; int err; |
cb84663e4 [NETNS]: Process ... |
227 |
|
69df9d599 ip_frag: dont tou... |
228 229 |
rcu_read_lock(); head->dev = dev_get_by_index_rcu(net, qp->iif); |
e9017b551 IP: Send an ICMP ... |
230 231 |
if (!head->dev) goto out_rcu_unlock; |
64f3b9e20 net: ip_expire() ... |
232 233 234 235 236 237 238 |
/* skb dst is stale, drop it, and perform route lookup again */ skb_dst_drop(head); iph = ip_hdr(head); err = ip_route_input_noref(head, iph->daddr, iph->saddr, iph->tos, head->dev); if (err) goto out_rcu_unlock; |
e9017b551 IP: Send an ICMP ... |
239 |
/* |
64f3b9e20 net: ip_expire() ... |
240 241 |
* Only an end host needs to send an ICMP * "Fragment Reassembly Timeout" message, per RFC792. |
e9017b551 IP: Send an ICMP ... |
242 |
*/ |
595fc71ba ipv4: Add ip_defr... |
243 244 245 |
if (qp->user == IP_DEFRAG_AF_PACKET || (qp->user == IP_DEFRAG_CONNTRACK_IN && skb_rtable(head)->rt_type != RTN_LOCAL)) |
64f3b9e20 net: ip_expire() ... |
246 |
goto out_rcu_unlock; |
e9017b551 IP: Send an ICMP ... |
247 248 249 |
/* Send an ICMP "Fragment Reassembly Timeout" message. */ icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
e9017b551 IP: Send an ICMP ... |
250 |
out_rcu_unlock: |
d1c9ae6d1 ipv4: ip_fragment... |
251 252 |
rcu_read_unlock(); } |
1da177e4c Linux-2.6.12-rc2 |
253 |
out: |
5ab11c98d [INET]: Move comm... |
254 |
spin_unlock(&qp->q.lock); |
4b6cb5d8e [INET]: Small cle... |
255 |
ipq_put(qp); |
1da177e4c Linux-2.6.12-rc2 |
256 |
} |
abd6523d1 [INET]: Consolida... |
257 258 259 |
/* Find the correct entry in the "incomplete datagrams" queue for * this IP datagram, and create new one, if nothing is found. */ |
ac18e7509 [NETNS][FRAGS]: M... |
260 |
static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) |
1da177e4c Linux-2.6.12-rc2 |
261 |
{ |
c6fda2822 [INET]: Consolida... |
262 263 |
struct inet_frag_queue *q; struct ip4_create_arg arg; |
abd6523d1 [INET]: Consolida... |
264 |
unsigned int hash; |
1da177e4c Linux-2.6.12-rc2 |
265 |
|
c6fda2822 [INET]: Consolida... |
266 267 |
arg.iph = iph; arg.user = user; |
9a375803f inet fragments: f... |
268 269 |
read_lock(&ip4_frags.lock); |
abd6523d1 [INET]: Consolida... |
270 |
hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); |
1da177e4c Linux-2.6.12-rc2 |
271 |
|
ac18e7509 [NETNS][FRAGS]: M... |
272 |
q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); |
c6fda2822 [INET]: Consolida... |
273 274 |
if (q == NULL) goto out_nomem; |
1da177e4c Linux-2.6.12-rc2 |
275 |
|
c6fda2822 [INET]: Consolida... |
276 |
return container_of(q, struct ipq, q); |
1da177e4c Linux-2.6.12-rc2 |
277 278 |
out_nomem: |
64ce20730 [NET]: Make NETDE... |
279 280 |
LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left ! "); |
1da177e4c Linux-2.6.12-rc2 |
281 282 |
return NULL; } |
89cee8b1c [IPV4]: Safer rea... |
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
/* Is the fragment too far ahead to be part of ipq? */ static inline int ip_frag_too_far(struct ipq *qp) { struct inet_peer *peer = qp->peer; unsigned int max = sysctl_ipfrag_max_dist; unsigned int start, end; int rc; if (!peer || !max) return 0; start = qp->rid; end = atomic_inc_return(&peer->rid); qp->rid = end; |
5ab11c98d [INET]: Move comm... |
298 |
rc = qp->q.fragments && (end - start) > max; |
89cee8b1c [IPV4]: Safer rea... |
299 300 |
if (rc) { |
7c73a6faf mib: add net to I... |
301 302 303 304 |
struct net *net; net = container_of(qp->q.net, struct net, ipv4.frags); IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); |
89cee8b1c [IPV4]: Safer rea... |
305 306 307 308 309 310 311 312 |
} return rc; } static int ip_frag_reinit(struct ipq *qp) { struct sk_buff *fp; |
b2fd5321d [NETNS][FRAGS]: M... |
313 |
if (!mod_timer(&qp->q.timer, jiffies + qp->q.net->timeout)) { |
5ab11c98d [INET]: Move comm... |
314 |
atomic_inc(&qp->q.refcnt); |
89cee8b1c [IPV4]: Safer rea... |
315 316 |
return -ETIMEDOUT; } |
5ab11c98d [INET]: Move comm... |
317 |
fp = qp->q.fragments; |
89cee8b1c [IPV4]: Safer rea... |
318 319 |
do { struct sk_buff *xp = fp->next; |
a95d8c88b ipfrag : frag_kfr... |
320 |
frag_kfree_skb(qp->q.net, fp); |
89cee8b1c [IPV4]: Safer rea... |
321 322 |
fp = xp; } while (fp); |
5ab11c98d [INET]: Move comm... |
323 324 325 326 |
qp->q.last_in = 0; qp->q.len = 0; qp->q.meat = 0; qp->q.fragments = NULL; |
d6bebca92 fragment: add fas... |
327 |
qp->q.fragments_tail = NULL; |
89cee8b1c [IPV4]: Safer rea... |
328 |
qp->iif = 0; |
6623e3b24 ipv4: IP defragme... |
329 |
qp->ecn = 0; |
89cee8b1c [IPV4]: Safer rea... |
330 331 332 |
return 0; } |
1da177e4c Linux-2.6.12-rc2 |
333 |
/* Add new segment to existing queue. */ |
1706d5876 [IPV4]: Make ip_d... |
334 |
static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
335 336 |
{ struct sk_buff *prev, *next; |
1706d5876 [IPV4]: Make ip_d... |
337 |
struct net_device *dev; |
1da177e4c Linux-2.6.12-rc2 |
338 339 |
int flags, offset; int ihl, end; |
1706d5876 [IPV4]: Make ip_d... |
340 |
int err = -ENOENT; |
6623e3b24 ipv4: IP defragme... |
341 |
u8 ecn; |
1da177e4c Linux-2.6.12-rc2 |
342 |
|
bc578a54f [NET]: Rename ine... |
343 |
if (qp->q.last_in & INET_FRAG_COMPLETE) |
1da177e4c Linux-2.6.12-rc2 |
344 |
goto err; |
89cee8b1c [IPV4]: Safer rea... |
345 |
if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && |
1706d5876 [IPV4]: Make ip_d... |
346 347 |
unlikely(ip_frag_too_far(qp)) && unlikely(err = ip_frag_reinit(qp))) { |
89cee8b1c [IPV4]: Safer rea... |
348 349 350 |
ipq_kill(qp); goto err; } |
6623e3b24 ipv4: IP defragme... |
351 |
ecn = ip4_frag_ecn(ip_hdr(skb)->tos); |
eddc9ec53 [SK_BUFF]: Introd... |
352 |
offset = ntohs(ip_hdr(skb)->frag_off); |
1da177e4c Linux-2.6.12-rc2 |
353 354 355 |
flags = offset & ~IP_OFFSET; offset &= IP_OFFSET; offset <<= 3; /* offset is in 8-byte chunks */ |
c9bdd4b52 [IP]: Introduce i... |
356 |
ihl = ip_hdrlen(skb); |
1da177e4c Linux-2.6.12-rc2 |
357 358 |
/* Determine the position of this fragment. */ |
e905a9eda [NET] IPV4: Fix w... |
359 |
end = offset + skb->len - ihl; |
1706d5876 [IPV4]: Make ip_d... |
360 |
err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
361 362 363 364 |
/* Is this the final fragment? */ if ((flags & IP_MF) == 0) { /* If we already have some bits beyond end |
42b2aa86c treewide: Fix typ... |
365 |
* or have different end, the segment is corrupted. |
1da177e4c Linux-2.6.12-rc2 |
366 |
*/ |
5ab11c98d [INET]: Move comm... |
367 |
if (end < qp->q.len || |
bc578a54f [NET]: Rename ine... |
368 |
((qp->q.last_in & INET_FRAG_LAST_IN) && end != qp->q.len)) |
1da177e4c Linux-2.6.12-rc2 |
369 |
goto err; |
bc578a54f [NET]: Rename ine... |
370 |
qp->q.last_in |= INET_FRAG_LAST_IN; |
5ab11c98d [INET]: Move comm... |
371 |
qp->q.len = end; |
1da177e4c Linux-2.6.12-rc2 |
372 373 374 375 376 377 |
} else { if (end&7) { end &= ~7; if (skb->ip_summed != CHECKSUM_UNNECESSARY) skb->ip_summed = CHECKSUM_NONE; } |
5ab11c98d [INET]: Move comm... |
378 |
if (end > qp->q.len) { |
1da177e4c Linux-2.6.12-rc2 |
379 |
/* Some bits beyond end -> corruption. */ |
bc578a54f [NET]: Rename ine... |
380 |
if (qp->q.last_in & INET_FRAG_LAST_IN) |
1da177e4c Linux-2.6.12-rc2 |
381 |
goto err; |
5ab11c98d [INET]: Move comm... |
382 |
qp->q.len = end; |
1da177e4c Linux-2.6.12-rc2 |
383 384 385 386 |
} } if (end == offset) goto err; |
1706d5876 [IPV4]: Make ip_d... |
387 |
err = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
388 389 |
if (pskb_pull(skb, ihl) == NULL) goto err; |
1706d5876 [IPV4]: Make ip_d... |
390 391 392 |
err = pskb_trim_rcsum(skb, end - offset); if (err) |
1da177e4c Linux-2.6.12-rc2 |
393 394 395 396 397 398 |
goto err; /* Find out which fragments are in front and at the back of us * in the chain of fragments so far. We must know where to put * this fragment, right? */ |
d6bebca92 fragment: add fas... |
399 400 401 402 403 |
prev = qp->q.fragments_tail; if (!prev || FRAG_CB(prev)->offset < offset) { next = NULL; goto found; } |
1da177e4c Linux-2.6.12-rc2 |
404 |
prev = NULL; |
5ab11c98d [INET]: Move comm... |
405 |
for (next = qp->q.fragments; next != NULL; next = next->next) { |
1da177e4c Linux-2.6.12-rc2 |
406 407 408 409 |
if (FRAG_CB(next)->offset >= offset) break; /* bingo! */ prev = next; } |
d6bebca92 fragment: add fas... |
410 |
found: |
1da177e4c Linux-2.6.12-rc2 |
411 412 413 414 415 416 417 418 419 |
/* We found where to put this one. Check for overlap with * preceding fragment, and, if needed, align things so that * any overlaps are eliminated. */ if (prev) { int i = (FRAG_CB(prev)->offset + prev->len) - offset; if (i > 0) { offset += i; |
1706d5876 [IPV4]: Make ip_d... |
420 |
err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
421 422 |
if (end <= offset) goto err; |
1706d5876 [IPV4]: Make ip_d... |
423 |
err = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
424 425 426 427 428 429 |
if (!pskb_pull(skb, i)) goto err; if (skb->ip_summed != CHECKSUM_UNNECESSARY) skb->ip_summed = CHECKSUM_NONE; } } |
1706d5876 [IPV4]: Make ip_d... |
430 |
err = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
431 432 433 434 435 436 437 438 439 440 |
while (next && FRAG_CB(next)->offset < end) { int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */ if (i < next->len) { /* Eat head of the next overlapped fragment * and leave the loop. The next ones cannot overlap. */ if (!pskb_pull(next, i)) goto err; FRAG_CB(next)->offset += i; |
5ab11c98d [INET]: Move comm... |
441 |
qp->q.meat -= i; |
1da177e4c Linux-2.6.12-rc2 |
442 443 444 445 446 |
if (next->ip_summed != CHECKSUM_UNNECESSARY) next->ip_summed = CHECKSUM_NONE; break; } else { struct sk_buff *free_it = next; |
47c6bf776 fix typo in net/i... |
447 |
/* Old fragment is completely overridden with |
1da177e4c Linux-2.6.12-rc2 |
448 449 450 451 452 453 454 |
* new one drop it. */ next = next->next; if (prev) prev->next = next; else |
5ab11c98d [INET]: Move comm... |
455 |
qp->q.fragments = next; |
1da177e4c Linux-2.6.12-rc2 |
456 |
|
5ab11c98d [INET]: Move comm... |
457 |
qp->q.meat -= free_it->len; |
a95d8c88b ipfrag : frag_kfr... |
458 |
frag_kfree_skb(qp->q.net, free_it); |
1da177e4c Linux-2.6.12-rc2 |
459 460 461 462 463 464 465 |
} } FRAG_CB(skb)->offset = offset; /* Insert this fragment in the chain of fragments. */ skb->next = next; |
d6bebca92 fragment: add fas... |
466 467 |
if (!next) qp->q.fragments_tail = skb; |
1da177e4c Linux-2.6.12-rc2 |
468 469 470 |
if (prev) prev->next = skb; else |
5ab11c98d [INET]: Move comm... |
471 |
qp->q.fragments = skb; |
1da177e4c Linux-2.6.12-rc2 |
472 |
|
1706d5876 [IPV4]: Make ip_d... |
473 474 475 476 477 |
dev = skb->dev; if (dev) { qp->iif = dev->ifindex; skb->dev = NULL; } |
5ab11c98d [INET]: Move comm... |
478 479 |
qp->q.stamp = skb->tstamp; qp->q.meat += skb->len; |
6623e3b24 ipv4: IP defragme... |
480 |
qp->ecn |= ecn; |
6ddc08222 [NETNS][FRAGS]: M... |
481 |
atomic_add(skb->truesize, &qp->q.net->mem); |
1da177e4c Linux-2.6.12-rc2 |
482 |
if (offset == 0) |
bc578a54f [NET]: Rename ine... |
483 |
qp->q.last_in |= INET_FRAG_FIRST_IN; |
1da177e4c Linux-2.6.12-rc2 |
484 |
|
bc578a54f [NET]: Rename ine... |
485 486 |
if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && qp->q.meat == qp->q.len) |
1706d5876 [IPV4]: Make ip_d... |
487 |
return ip_frag_reasm(qp, prev, dev); |
7eb95156d [INET]: Collect f... |
488 |
write_lock(&ip4_frags.lock); |
3140c25c8 [NETNS][FRAGS]: M... |
489 |
list_move_tail(&qp->q.lru_list, &qp->q.net->lru_list); |
7eb95156d [INET]: Collect f... |
490 |
write_unlock(&ip4_frags.lock); |
1706d5876 [IPV4]: Make ip_d... |
491 |
return -EINPROGRESS; |
1da177e4c Linux-2.6.12-rc2 |
492 493 494 |
err: kfree_skb(skb); |
1706d5876 [IPV4]: Make ip_d... |
495 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
496 497 498 499 |
} /* Build a new IP datagram from all its fragments. */ |
1706d5876 [IPV4]: Make ip_d... |
500 501 |
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
502 |
{ |
2bad35b7c netns: oops in ip... |
503 |
struct net *net = container_of(qp->q.net, struct net, ipv4.frags); |
1da177e4c Linux-2.6.12-rc2 |
504 |
struct iphdr *iph; |
5ab11c98d [INET]: Move comm... |
505 |
struct sk_buff *fp, *head = qp->q.fragments; |
1da177e4c Linux-2.6.12-rc2 |
506 507 |
int len; int ihlen; |
1706d5876 [IPV4]: Make ip_d... |
508 |
int err; |
5173cc057 ipv4: more compli... |
509 |
u8 ecn; |
1da177e4c Linux-2.6.12-rc2 |
510 511 |
ipq_kill(qp); |
5173cc057 ipv4: more compli... |
512 513 514 515 516 |
ecn = ip4_frag_ecn_table[qp->ecn]; if (unlikely(ecn == 0xff)) { err = -EINVAL; goto out_fail; } |
1706d5876 [IPV4]: Make ip_d... |
517 518 519 520 |
/* Make the one we just received the head. */ if (prev) { head = prev->next; fp = skb_clone(head, GFP_ATOMIC); |
1706d5876 [IPV4]: Make ip_d... |
521 522 523 524 |
if (!fp) goto out_nomem; fp->next = head->next; |
d6bebca92 fragment: add fas... |
525 526 |
if (!fp->next) qp->q.fragments_tail = fp; |
1706d5876 [IPV4]: Make ip_d... |
527 |
prev->next = fp; |
5ab11c98d [INET]: Move comm... |
528 529 |
skb_morph(head, qp->q.fragments); head->next = qp->q.fragments->next; |
1706d5876 [IPV4]: Make ip_d... |
530 |
|
5ab11c98d [INET]: Move comm... |
531 532 |
kfree_skb(qp->q.fragments); qp->q.fragments = head; |
1706d5876 [IPV4]: Make ip_d... |
533 |
} |
547b792ca net: convert BUG_... |
534 535 |
WARN_ON(head == NULL); WARN_ON(FRAG_CB(head)->offset != 0); |
1da177e4c Linux-2.6.12-rc2 |
536 537 |
/* Allocate a new buffer for the datagram. */ |
c9bdd4b52 [IP]: Introduce i... |
538 |
ihlen = ip_hdrlen(head); |
5ab11c98d [INET]: Move comm... |
539 |
len = ihlen + qp->q.len; |
1da177e4c Linux-2.6.12-rc2 |
540 |
|
1706d5876 [IPV4]: Make ip_d... |
541 |
err = -E2BIG; |
132adf546 [IPV4]: cleanup |
542 |
if (len > 65535) |
1da177e4c Linux-2.6.12-rc2 |
543 544 545 546 547 548 549 550 551 |
goto out_oversize; /* Head of list must not be cloned. */ if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) goto out_nomem; /* If the first fragment is fragmented itself, we split * it to two chunks: the first with data and paged part * and the second, holding only fragments. */ |
21dc33015 net: Rename skb_h... |
552 |
if (skb_has_frag_list(head)) { |
1da177e4c Linux-2.6.12-rc2 |
553 554 555 556 557 558 559 560 |
struct sk_buff *clone; int i, plen = 0; if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL) goto out_nomem; clone->next = head->next; head->next = clone; skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; |
d7fcf1a5c ipv4: Use frag li... |
561 |
skb_frag_list_init(head); |
9e903e085 net: add skb frag... |
562 563 |
for (i = 0; i < skb_shinfo(head)->nr_frags; i++) plen += skb_frag_size(&skb_shinfo(head)->frags[i]); |
1da177e4c Linux-2.6.12-rc2 |
564 565 566 567 568 |
clone->len = clone->data_len = head->data_len - plen; head->data_len -= clone->len; head->len -= clone->len; clone->csum = 0; clone->ip_summed = head->ip_summed; |
6ddc08222 [NETNS][FRAGS]: M... |
569 |
atomic_add(clone->truesize, &qp->q.net->mem); |
1da177e4c Linux-2.6.12-rc2 |
570 571 572 |
} skb_shinfo(head)->frag_list = head->next; |
d56f90a7c [SK_BUFF]: Introd... |
573 |
skb_push(head, head->data - skb_network_header(head)); |
1da177e4c Linux-2.6.12-rc2 |
574 575 576 577 578 579 |
for (fp=head->next; fp; fp = fp->next) { head->data_len += fp->len; head->len += fp->len; if (head->ip_summed != fp->ip_summed) head->ip_summed = CHECKSUM_NONE; |
84fa7933a [NET]: Replace CH... |
580 |
else if (head->ip_summed == CHECKSUM_COMPLETE) |
1da177e4c Linux-2.6.12-rc2 |
581 582 |
head->csum = csum_add(head->csum, fp->csum); head->truesize += fp->truesize; |
1da177e4c Linux-2.6.12-rc2 |
583 |
} |
d27f9b358 ip_frag: Remove s... |
584 |
atomic_sub(head->truesize, &qp->q.net->mem); |
1da177e4c Linux-2.6.12-rc2 |
585 586 587 |
head->next = NULL; head->dev = dev; |
5ab11c98d [INET]: Move comm... |
588 |
head->tstamp = qp->q.stamp; |
1da177e4c Linux-2.6.12-rc2 |
589 |
|
eddc9ec53 [SK_BUFF]: Introd... |
590 |
iph = ip_hdr(head); |
1da177e4c Linux-2.6.12-rc2 |
591 592 |
iph->frag_off = 0; iph->tot_len = htons(len); |
5173cc057 ipv4: more compli... |
593 |
iph->tos |= ecn; |
2bad35b7c netns: oops in ip... |
594 |
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); |
5ab11c98d [INET]: Move comm... |
595 |
qp->q.fragments = NULL; |
d6bebca92 fragment: add fas... |
596 |
qp->q.fragments_tail = NULL; |
1706d5876 [IPV4]: Make ip_d... |
597 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
598 599 |
out_nomem: |
e905a9eda [NET] IPV4: Fix w... |
600 |
LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing " |
64ce20730 [NET]: Make NETDE... |
601 602 |
"queue %p ", qp); |
45542479f [NET]: Fix uninit... |
603 |
err = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
604 605 606 |
goto out_fail; out_oversize: if (net_ratelimit()) |
673d57e72 net: replace NIPQ... |
607 608 609 |
printk(KERN_INFO "Oversized IP packet from %pI4. ", &qp->saddr); |
1da177e4c Linux-2.6.12-rc2 |
610 |
out_fail: |
bbf31bf18 ipv4: additional ... |
611 |
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); |
1706d5876 [IPV4]: Make ip_d... |
612 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
613 614 615 |
} /* Process an incoming IP datagram fragment. */ |
776c729e8 [IPV4]: Change ip... |
616 |
int ip_defrag(struct sk_buff *skb, u32 user) |
1da177e4c Linux-2.6.12-rc2 |
617 |
{ |
1da177e4c Linux-2.6.12-rc2 |
618 |
struct ipq *qp; |
ac18e7509 [NETNS][FRAGS]: M... |
619 |
struct net *net; |
e905a9eda [NET] IPV4: Fix w... |
620 |
|
adf30907d net: skb->dst acc... |
621 |
net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev); |
7c73a6faf mib: add net to I... |
622 |
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); |
1da177e4c Linux-2.6.12-rc2 |
623 624 |
/* Start by cleaning up the memory. */ |
e31e0bdc7 [NETNS][FRAGS]: M... |
625 |
if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh) |
6ddc08222 [NETNS][FRAGS]: M... |
626 |
ip_evictor(net); |
1da177e4c Linux-2.6.12-rc2 |
627 |
|
1da177e4c Linux-2.6.12-rc2 |
628 |
/* Lookup (or create) queue header */ |
ac18e7509 [NETNS][FRAGS]: M... |
629 |
if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) { |
1706d5876 [IPV4]: Make ip_d... |
630 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
631 |
|
5ab11c98d [INET]: Move comm... |
632 |
spin_lock(&qp->q.lock); |
1da177e4c Linux-2.6.12-rc2 |
633 |
|
1706d5876 [IPV4]: Make ip_d... |
634 |
ret = ip_frag_queue(qp, skb); |
1da177e4c Linux-2.6.12-rc2 |
635 |
|
5ab11c98d [INET]: Move comm... |
636 |
spin_unlock(&qp->q.lock); |
4b6cb5d8e [INET]: Small cle... |
637 |
ipq_put(qp); |
776c729e8 [IPV4]: Change ip... |
638 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
639 |
} |
7c73a6faf mib: add net to I... |
640 |
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); |
1da177e4c Linux-2.6.12-rc2 |
641 |
kfree_skb(skb); |
776c729e8 [IPV4]: Change ip... |
642 |
return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
643 |
} |
4bc2f18ba net/ipv4: EXPORT_... |
644 |
EXPORT_SYMBOL(ip_defrag); |
1da177e4c Linux-2.6.12-rc2 |
645 |
|
bc416d976 macvlan: handle f... |
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 |
struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) { const struct iphdr *iph; u32 len; if (skb->protocol != htons(ETH_P_IP)) return skb; if (!pskb_may_pull(skb, sizeof(struct iphdr))) return skb; iph = ip_hdr(skb); if (iph->ihl < 5 || iph->version != 4) return skb; if (!pskb_may_pull(skb, iph->ihl*4)) return skb; iph = ip_hdr(skb); len = ntohs(iph->tot_len); if (skb->len < len || len < (iph->ihl * 4)) return skb; if (ip_is_fragment(ip_hdr(skb))) { skb = skb_share_check(skb, GFP_ATOMIC); if (skb) { if (pskb_trim_rcsum(skb, len)) return skb; memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); if (ip_defrag(skb, user)) return NULL; skb->rxhash = 0; } } return skb; } EXPORT_SYMBOL(ip_check_defrag); |
8d8354d2f [NETNS][FRAGS]: M... |
681 682 |
#ifdef CONFIG_SYSCTL static int zero; |
0a64b4b81 inet: Rename frag... |
683 |
static struct ctl_table ip4_frags_ns_ctl_table[] = { |
8d8354d2f [NETNS][FRAGS]: M... |
684 |
{ |
8d8354d2f [NETNS][FRAGS]: M... |
685 |
.procname = "ipfrag_high_thresh", |
e31e0bdc7 [NETNS][FRAGS]: M... |
686 |
.data = &init_net.ipv4.frags.high_thresh, |
8d8354d2f [NETNS][FRAGS]: M... |
687 688 |
.maxlen = sizeof(int), .mode = 0644, |
6d9f239a1 net: '&' redux |
689 |
.proc_handler = proc_dointvec |
8d8354d2f [NETNS][FRAGS]: M... |
690 691 |
}, { |
8d8354d2f [NETNS][FRAGS]: M... |
692 |
.procname = "ipfrag_low_thresh", |
e31e0bdc7 [NETNS][FRAGS]: M... |
693 |
.data = &init_net.ipv4.frags.low_thresh, |
8d8354d2f [NETNS][FRAGS]: M... |
694 695 |
.maxlen = sizeof(int), .mode = 0644, |
6d9f239a1 net: '&' redux |
696 |
.proc_handler = proc_dointvec |
8d8354d2f [NETNS][FRAGS]: M... |
697 698 |
}, { |
8d8354d2f [NETNS][FRAGS]: M... |
699 |
.procname = "ipfrag_time", |
b2fd5321d [NETNS][FRAGS]: M... |
700 |
.data = &init_net.ipv4.frags.timeout, |
8d8354d2f [NETNS][FRAGS]: M... |
701 702 |
.maxlen = sizeof(int), .mode = 0644, |
6d9f239a1 net: '&' redux |
703 |
.proc_handler = proc_dointvec_jiffies, |
8d8354d2f [NETNS][FRAGS]: M... |
704 |
}, |
7d291ebb8 inet: Register fr... |
705 706 707 708 |
{ } }; static struct ctl_table ip4_frags_ctl_table[] = { |
8d8354d2f [NETNS][FRAGS]: M... |
709 |
{ |
8d8354d2f [NETNS][FRAGS]: M... |
710 |
.procname = "ipfrag_secret_interval", |
3b4bc4a2b [NETNS][FRAGS]: I... |
711 |
.data = &ip4_frags.secret_interval, |
8d8354d2f [NETNS][FRAGS]: M... |
712 713 |
.maxlen = sizeof(int), .mode = 0644, |
6d9f239a1 net: '&' redux |
714 |
.proc_handler = proc_dointvec_jiffies, |
8d8354d2f [NETNS][FRAGS]: M... |
715 716 717 718 719 720 |
}, { .procname = "ipfrag_max_dist", .data = &sysctl_ipfrag_max_dist, .maxlen = sizeof(int), .mode = 0644, |
6d9f239a1 net: '&' redux |
721 |
.proc_handler = proc_dointvec_minmax, |
8d8354d2f [NETNS][FRAGS]: M... |
722 723 724 725 |
.extra1 = &zero }, { } }; |
2c8c1e729 net: spread __net... |
726 |
static int __net_init ip4_frags_ns_ctl_register(struct net *net) |
8d8354d2f [NETNS][FRAGS]: M... |
727 |
{ |
e4a2d5c2b [NETNS][FRAGS]: D... |
728 |
struct ctl_table *table; |
8d8354d2f [NETNS][FRAGS]: M... |
729 |
struct ctl_table_header *hdr; |
0a64b4b81 inet: Rename frag... |
730 |
table = ip4_frags_ns_ctl_table; |
09ad9bc75 net: use net_eq t... |
731 |
if (!net_eq(net, &init_net)) { |
0a64b4b81 inet: Rename frag... |
732 |
table = kmemdup(table, sizeof(ip4_frags_ns_ctl_table), GFP_KERNEL); |
e4a2d5c2b [NETNS][FRAGS]: D... |
733 734 |
if (table == NULL) goto err_alloc; |
e31e0bdc7 [NETNS][FRAGS]: M... |
735 736 |
table[0].data = &net->ipv4.frags.high_thresh; table[1].data = &net->ipv4.frags.low_thresh; |
b2fd5321d [NETNS][FRAGS]: M... |
737 |
table[2].data = &net->ipv4.frags.timeout; |
e4a2d5c2b [NETNS][FRAGS]: D... |
738 739 740 741 742 743 744 745 746 747 |
} hdr = register_net_sysctl_table(net, net_ipv4_ctl_path, table); if (hdr == NULL) goto err_reg; net->ipv4.frags_hdr = hdr; return 0; err_reg: |
09ad9bc75 net: use net_eq t... |
748 |
if (!net_eq(net, &init_net)) |
e4a2d5c2b [NETNS][FRAGS]: D... |
749 750 751 752 |
kfree(table); err_alloc: return -ENOMEM; } |
2c8c1e729 net: spread __net... |
753 |
static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net) |
e4a2d5c2b [NETNS][FRAGS]: D... |
754 755 756 757 758 759 |
{ struct ctl_table *table; table = net->ipv4.frags_hdr->ctl_table_arg; unregister_net_sysctl_table(net->ipv4.frags_hdr); kfree(table); |
8d8354d2f [NETNS][FRAGS]: M... |
760 |
} |
7d291ebb8 inet: Register fr... |
761 762 763 764 765 |
static void ip4_frags_ctl_register(void) { register_net_sysctl_rotable(net_ipv4_ctl_path, ip4_frags_ctl_table); } |
8d8354d2f [NETNS][FRAGS]: M... |
766 |
#else |
0a64b4b81 inet: Rename frag... |
767 |
static inline int ip4_frags_ns_ctl_register(struct net *net) |
8d8354d2f [NETNS][FRAGS]: M... |
768 769 770 |
{ return 0; } |
e4a2d5c2b [NETNS][FRAGS]: D... |
771 |
|
0a64b4b81 inet: Rename frag... |
772 |
static inline void ip4_frags_ns_ctl_unregister(struct net *net) |
e4a2d5c2b [NETNS][FRAGS]: D... |
773 774 |
{ } |
7d291ebb8 inet: Register fr... |
775 776 777 778 |
static inline void ip4_frags_ctl_register(void) { } |
8d8354d2f [NETNS][FRAGS]: M... |
779 |
#endif |
2c8c1e729 net: spread __net... |
780 |
static int __net_init ipv4_frags_init_net(struct net *net) |
8d8354d2f [NETNS][FRAGS]: M... |
781 |
{ |
b2fd5321d [NETNS][FRAGS]: M... |
782 |
/* |
e31e0bdc7 [NETNS][FRAGS]: M... |
783 784 785 786 787 788 789 790 |
* Fragment cache limits. We will commit 256K at one time. Should we * cross that limit we will prune down to 192K. This should cope with * even the most extreme cases without allowing an attacker to * measurably harm machine performance. */ net->ipv4.frags.high_thresh = 256 * 1024; net->ipv4.frags.low_thresh = 192 * 1024; /* |
b2fd5321d [NETNS][FRAGS]: M... |
791 792 793 794 795 |
* Important NOTE! Fragment queue must be destroyed before MSL expires. * RFC791 is wrong proposing to prolongate timer each fragment arrival * by TTL. */ net->ipv4.frags.timeout = IP_FRAG_TIME; |
e5a2bb842 [NETNS][FRAGS]: M... |
796 |
inet_frags_init_net(&net->ipv4.frags); |
0a64b4b81 inet: Rename frag... |
797 |
return ip4_frags_ns_ctl_register(net); |
8d8354d2f [NETNS][FRAGS]: M... |
798 |
} |
2c8c1e729 net: spread __net... |
799 |
static void __net_exit ipv4_frags_exit_net(struct net *net) |
81566e832 [NETNS][FRAGS]: M... |
800 |
{ |
0a64b4b81 inet: Rename frag... |
801 |
ip4_frags_ns_ctl_unregister(net); |
81566e832 [NETNS][FRAGS]: M... |
802 803 804 805 806 807 808 |
inet_frags_exit_net(&net->ipv4.frags, &ip4_frags); } static struct pernet_operations ip4_frags_ops = { .init = ipv4_frags_init_net, .exit = ipv4_frags_exit_net, }; |
b7aa0bf70 [NET]: convert ne... |
809 |
void __init ipfrag_init(void) |
1da177e4c Linux-2.6.12-rc2 |
810 |
{ |
7d291ebb8 inet: Register fr... |
811 |
ip4_frags_ctl_register(); |
81566e832 [NETNS][FRAGS]: M... |
812 |
register_pernet_subsys(&ip4_frags_ops); |
321a3a99e [INET]: Consolida... |
813 |
ip4_frags.hashfn = ip4_hashfn; |
c6fda2822 [INET]: Consolida... |
814 |
ip4_frags.constructor = ip4_frag_init; |
1e4b82873 [INET]: Consolida... |
815 816 817 |
ip4_frags.destructor = ip4_frag_free; ip4_frags.skb_free = NULL; ip4_frags.qsize = sizeof(struct ipq); |
abd6523d1 [INET]: Consolida... |
818 |
ip4_frags.match = ip4_frag_match; |
e521db9d7 [INET]: Consolida... |
819 |
ip4_frags.frag_expire = ip_expire; |
3b4bc4a2b [NETNS][FRAGS]: I... |
820 |
ip4_frags.secret_interval = 10 * 60 * HZ; |
7eb95156d [INET]: Collect f... |
821 |
inet_frags_init(&ip4_frags); |
1da177e4c Linux-2.6.12-rc2 |
822 |
} |