diff options
| -rw-r--r-- | net/ipv4/ip_fragment.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 891c72aea520..9f41bd311754 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
| @@ -32,6 +32,8 @@ | |||
| 32 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
| 33 | #include <linux/jhash.h> | 33 | #include <linux/jhash.h> |
| 34 | #include <linux/random.h> | 34 | #include <linux/random.h> |
| 35 | #include <net/route.h> | ||
| 36 | #include <net/dst.h> | ||
| 35 | #include <net/sock.h> | 37 | #include <net/sock.h> |
| 36 | #include <net/ip.h> | 38 | #include <net/ip.h> |
| 37 | #include <net/icmp.h> | 39 | #include <net/icmp.h> |
| @@ -205,13 +207,37 @@ static void ip_expire(unsigned long arg) | |||
| 205 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { | 207 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { |
| 206 | struct sk_buff *head = qp->q.fragments; | 208 | struct sk_buff *head = qp->q.fragments; |
| 207 | 209 | ||
| 208 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | ||
| 209 | rcu_read_lock(); | 210 | rcu_read_lock(); |
| 210 | head->dev = dev_get_by_index_rcu(net, qp->iif); | 211 | head->dev = dev_get_by_index_rcu(net, qp->iif); |
| 211 | if (head->dev) | 212 | if (!head->dev) |
| 212 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 213 | goto out_rcu_unlock; |
| 213 | rcu_read_unlock(); | 214 | |
| 215 | /* | ||
| 216 | * Only search router table for the head fragment, | ||
| 217 | * when defraging timeout at PRE_ROUTING HOOK. | ||
| 218 | */ | ||
| 219 | if (qp->user == IP_DEFRAG_CONNTRACK_IN && !skb_dst(head)) { | ||
| 220 | const struct iphdr *iph = ip_hdr(head); | ||
| 221 | int err = ip_route_input(head, iph->daddr, iph->saddr, | ||
| 222 | iph->tos, head->dev); | ||
| 223 | if (unlikely(err)) | ||
| 224 | goto out_rcu_unlock; | ||
| 225 | |||
| 226 | /* | ||
| 227 | * Only an end host needs to send an ICMP | ||
| 228 | * "Fragment Reassembly Timeout" message, per RFC792. | ||
| 229 | */ | ||
| 230 | if (skb_rtable(head)->rt_type != RTN_LOCAL) | ||
| 231 | goto out_rcu_unlock; | ||
| 232 | |||
| 233 | } | ||
| 234 | |||
| 235 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | ||
| 236 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | ||
| 214 | } | 237 | } |
| 238 | |||
| 239 | out_rcu_unlock: | ||
| 240 | rcu_read_unlock(); | ||
| 215 | out: | 241 | out: |
| 216 | spin_unlock(&qp->q.lock); | 242 | spin_unlock(&qp->q.lock); |
| 217 | ipq_put(qp); | 243 | ipq_put(qp); |
