[NETFILTER]: Introduce NF_INET_ hook values
[safe/jmp/linux-2.6] / net / ipv4 / ip_output.c
index 77f67b7..6dd1d9c 100644 (file)
@@ -91,6 +91,28 @@ __inline__ void ip_send_check(struct iphdr *iph)
        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 }
 
+int __ip_local_out(struct sk_buff *skb)
+{
+       struct iphdr *iph = ip_hdr(skb);
+
+       iph->tot_len = htons(skb->len);
+       ip_send_check(iph);
+       return nf_hook(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, skb->dst->dev,
+                      dst_output);
+}
+
+int ip_local_out(struct sk_buff *skb)
+{
+       int err;
+
+       err = __ip_local_out(skb);
+       if (likely(err == 1))
+               err = dst_output(skb);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(ip_local_out);
+
 /* dev_loopback_xmit for use with netfilter. */
 static int ip_dev_loopback_xmit(struct sk_buff *newskb)
 {
@@ -138,20 +160,17 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
        iph->daddr    = rt->rt_dst;
        iph->saddr    = rt->rt_src;
        iph->protocol = sk->sk_protocol;
-       iph->tot_len  = htons(skb->len);
        ip_select_ident(iph, &rt->u.dst, sk);
 
        if (opt && opt->optlen) {
                iph->ihl += opt->optlen>>2;
                ip_options_build(skb, opt, daddr, rt, 0);
        }
-       ip_send_check(iph);
 
        skb->priority = sk->sk_priority;
 
        /* Send it out. */
-       return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-                      dst_output);
+       return ip_local_out(skb);
 }
 
 EXPORT_SYMBOL_GPL(ip_build_and_send_pkt);
@@ -161,7 +180,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
        struct dst_entry *dst = skb->dst;
        struct rtable *rt = (struct rtable *)dst;
        struct net_device *dev = dst->dev;
-       int hh_len = LL_RESERVED_SPACE(dev);
+       unsigned int hh_len = LL_RESERVED_SPACE(dev);
 
        if (rt->rt_type == RTN_MULTICAST)
                IP_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
@@ -169,7 +188,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)
                IP_INC_STATS(IPSTATS_MIB_OUTBCASTPKTS);
 
        /* Be paranoid, rather than too clever. */
-       if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
+       if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
                struct sk_buff *skb2;
 
                skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
@@ -202,7 +221,7 @@ static inline int ip_skb_dst_mtu(struct sk_buff *skb)
               skb->dst->dev->mtu : dst_mtu(skb->dst);
 }
 
-static inline int ip_finish_output(struct sk_buff *skb)
+static int ip_finish_output(struct sk_buff *skb)
 {
 #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
        /* Policy lookup after SNAT yielded a new policy */
@@ -251,8 +270,8 @@ int ip_mc_output(struct sk_buff *skb)
                ) {
                        struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
                        if (newskb)
-                               NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL,
-                                       newskb->dev,
+                               NF_HOOK(PF_INET, NF_INET_POST_ROUTING, newskb,
+                                       NULL, newskb->dev,
                                        ip_dev_loopback_xmit);
                }
 
@@ -267,11 +286,11 @@ int ip_mc_output(struct sk_buff *skb)
        if (rt->rt_flags&RTCF_BROADCAST) {
                struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
                if (newskb)
-                       NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL,
+                       NF_HOOK(PF_INET, NF_INET_POST_ROUTING, newskb, NULL,
                                newskb->dev, ip_dev_loopback_xmit);
        }
 
-       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev,
+       return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
                            ip_finish_output,
                            !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
@@ -285,7 +304,7 @@ int ip_output(struct sk_buff *skb)
        skb->dev = dev;
        skb->protocol = htons(ETH_P_IP);
 
-       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
+       return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, dev,
                            ip_finish_output,
                            !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
@@ -347,7 +366,6 @@ packet_routed:
        skb_reset_network_header(skb);
        iph = ip_hdr(skb);
        *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));
-       iph->tot_len = htons(skb->len);
        if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok)
                iph->frag_off = htons(IP_DF);
        else
@@ -366,13 +384,9 @@ packet_routed:
        ip_select_ident_more(iph, &rt->u.dst, sk,
                             (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
-       /* Add an IP checksum. */
-       ip_send_check(iph);
-
        skb->priority = sk->sk_priority;
 
-       return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-                      dst_output);
+       return ip_local_out(skb);
 
 no_route:
        IP_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
@@ -1016,8 +1030,6 @@ alloc_new_skb:
 
                                skb_fill_page_desc(skb, i, page, 0, 0);
                                frag = &skb_shinfo(skb)->frags[i];
-                               skb->truesize += PAGE_SIZE;
-                               atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
                        } else {
                                err = -EMSGSIZE;
                                goto error;
@@ -1030,6 +1042,8 @@ alloc_new_skb:
                        frag->size += copy;
                        skb->len += copy;
                        skb->data_len += copy;
+                       skb->truesize += copy;
+                       atomic_add(copy, &sk->sk_wmem_alloc);
                }
                offset += copy;
                length -= copy;
@@ -1172,6 +1186,8 @@ ssize_t   ip_append_page(struct sock *sk, struct page *page,
 
                skb->len += len;
                skb->data_len += len;
+               skb->truesize += len;
+               atomic_add(len, &sk->sk_wmem_alloc);
                offset += len;
                size -= len;
        }
@@ -1183,6 +1199,17 @@ error:
        return err;
 }
 
+static void ip_cork_release(struct inet_sock *inet)
+{
+       inet->cork.flags &= ~IPCORK_OPT;
+       kfree(inet->cork.opt);
+       inet->cork.opt = NULL;
+       if (inet->cork.rt) {
+               ip_rt_put(inet->cork.rt);
+               inet->cork.rt = NULL;
+       }
+}
+
 /*
  *     Combined all pending IP fragments on the socket as one IP datagram
  *     and push them out.
@@ -1249,14 +1276,12 @@ int ip_push_pending_frames(struct sock *sk)
                ip_options_build(skb, opt, inet->cork.addr, rt, 0);
        }
        iph->tos = inet->tos;
-       iph->tot_len = htons(skb->len);
        iph->frag_off = df;
        ip_select_ident(iph, &rt->u.dst, sk);
        iph->ttl = ttl;
        iph->protocol = sk->sk_protocol;
        iph->saddr = rt->rt_src;
        iph->daddr = rt->rt_dst;
-       ip_send_check(iph);
 
        skb->priority = sk->sk_priority;
        skb->dst = dst_clone(&rt->u.dst);
@@ -1266,8 +1291,7 @@ int ip_push_pending_frames(struct sock *sk)
                        skb_transport_header(skb))->type);
 
        /* Netfilter gets whole the not fragmented skb. */
-       err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
-                     skb->dst->dev, dst_output);
+       err = ip_local_out(skb);
        if (err) {
                if (err > 0)
                        err = inet->recverr ? net_xmit_errno(err) : 0;
@@ -1276,13 +1300,7 @@ int ip_push_pending_frames(struct sock *sk)
        }
 
 out:
-       inet->cork.flags &= ~IPCORK_OPT;
-       kfree(inet->cork.opt);
-       inet->cork.opt = NULL;
-       if (inet->cork.rt) {
-               ip_rt_put(inet->cork.rt);
-               inet->cork.rt = NULL;
-       }
+       ip_cork_release(inet);
        return err;
 
 error:
@@ -1295,19 +1313,12 @@ error:
  */
 void ip_flush_pending_frames(struct sock *sk)
 {
-       struct inet_sock *inet = inet_sk(sk);
        struct sk_buff *skb;
 
        while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL)
                kfree_skb(skb);
 
-       inet->cork.flags &= ~IPCORK_OPT;
-       kfree(inet->cork.opt);
-       inet->cork.opt = NULL;
-       if (inet->cork.rt) {
-               ip_rt_put(inet->cork.rt);
-               inet->cork.rt = NULL;
-       }
+       ip_cork_release(inet_sk(sk));
 }