* Fixes:
* Alan Cox : Missing nonblock feature in ip_build_xmit.
* Mike Kilburn : htons() missing in ip_build_xmit.
- * Bradford Johnson: Fix faulty handling of some frames when
+ * Bradford Johnson: Fix faulty handling of some frames when
* no route is found.
* Alexander Demenshin: Missing sk/skb free in ip_queue_xmit
* (in case if packet not accepted by
* some redundant tests.
* Vitaly E. Lavrov : Transparent proxy revived after year coma.
* Andi Kleen : Replace ip_reply with ip_send_reply.
- * Andi Kleen : Split fast and slow ip_build_xmit path
- * for decreased register pressure on x86
- * and more readibility.
+ * Andi Kleen : Split fast and slow ip_build_xmit path
+ * for decreased register pressure on x86
+ * and more readibility.
* Marc Boucher : When call_out_firewall returns FW_QUEUE,
* silently drop skb instead of failing with -EPERM.
* Detlev Wengorz : Copy protocol for fragments.
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/highmem.h>
#include <linux/socket.h>
#include <linux/sockios.h>
return ttl;
}
-/*
+/*
* Add an ip header to a skbuff and send it out.
*
*/
static inline int ip_finish_output2(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
- struct hh_cache *hh = dst->hh;
struct net_device *dev = dst->dev;
int hh_len = LL_RESERVED_SPACE(dev);
skb = skb2;
}
- if (hh) {
- int hh_alen;
-
- read_lock_bh(&hh->hh_lock);
- hh_alen = HH_DATA_ALIGN(hh->hh_len);
- memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
- read_unlock_bh(&hh->hh_lock);
- skb_push(skb, hh->hh_len);
- return hh->hh_output(skb);
- } else if (dst->neighbour)
+ if (dst->hh)
+ return neigh_hh_output(dst->hh, skb);
+ else if (dst->neighbour)
return dst->neighbour->output(skb);
if (net_ratelimit())
struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
if (newskb)
NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL,
- newskb->dev,
+ newskb->dev,
ip_dev_loopback_xmit);
}
skb->protocol = htons(ETH_P_IP);
return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
- ip_finish_output,
+ ip_finish_output,
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
-int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok)
+int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
{
+ struct sock *sk = skb->sk;
struct inet_sock *inet = inet_sk(sk);
struct ip_options *opt = inet->opt;
struct rtable *rt;
return err;
fail:
- kfree_skb(skb);
+ kfree_skb(skb);
IP_INC_STATS(IPSTATS_MIB_FRAGFAILS);
return err;
}
* from many pieces of data. Each pieces will be holded on the socket
* until ip_push_pending_frames() is called. Each piece can be a page
* or non-page data.
- *
+ *
* Not only UDP, other transport protocols - e.g. raw sockets - can use
* this interface potentially.
*
datalen = maxfraglen - fragheaderlen;
fraglen = datalen + fragheaderlen;
- if ((flags & MSG_MORE) &&
+ if ((flags & MSG_MORE) &&
!(rt->u.dst.dev->features&NETIF_F_SG))
alloclen = mtu;
else
alloclen += rt->u.dst.trailer_len;
if (transhdrlen) {
- skb = sock_alloc_send_skb(sk,
+ skb = sock_alloc_send_skb(sk,
alloclen + hh_len + 15,
(flags & MSG_DONTWAIT), &err);
} else {
skb = NULL;
if (atomic_read(&sk->sk_wmem_alloc) <=
2 * sk->sk_sndbuf)
- skb = sock_wmalloc(sk,
+ skb = sock_wmalloc(sk,
alloclen + hh_len + 15, 1,
sk->sk_allocation);
if (unlikely(skb == NULL))
unsigned int off;
off = skb->len;
- if (getfrag(from, skb_put(skb, copy),
+ if (getfrag(from, skb_put(skb, copy),
offset, copy, off, skb) < 0) {
__skb_trim(skb, off);
err = -EFAULT;
goto error;
}
get_page(page);
- skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
+ skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
frag = &skb_shinfo(skb)->frags[i];
}
} else if (i < MAX_SKB_FRAGS) {
error:
inet->cork.length -= length;
IP_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
- return err;
+ return err;
}
ssize_t ip_append_page(struct sock *sk, struct page *page,
skb->dst = dst_clone(&rt->u.dst);
/* Netfilter gets whole the not fragmented skb. */
- err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
+ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
skb->dst->dev, dst_output);
if (err) {
if (err > 0)
/*
* Fetch data from kernel space and fill in checksum if needed.
*/
-static int ip_reply_glue_bits(void *dptr, char *to, int offset,
+static int ip_reply_glue_bits(void *dptr, char *to, int offset,
int len, int odd, struct sk_buff *skb)
{
__wsum csum;
csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0);
skb->csum = csum_block_add(skb->csum, csum, odd);
- return 0;
+ return 0;
}
-/*
+/*
* Generic function to send a packet as reply to another packet.
* Used to send TCP resets so far. ICMP should use this function too.
*
- * Should run single threaded per socket because it uses the sock
+ * Should run single threaded per socket because it uses the sock
* structure to pass arguments.
*
* LATER: switch from ip_build_xmit to ip_append_*
/* Not quite clean, but right. */
.uli_u = { .ports =
{ .sport = skb->h.th->dest,
- .dport = skb->h.th->source } },
+ .dport = skb->h.th->source } },
.proto = sk->sk_protocol };
security_skb_classify_flow(skb, &fl);
if (ip_route_output_key(&rt, &fl))