patch-2.4.4 linux/net/ipv4/ip_output.c
Next file: linux/net/ipv4/ip_sockglue.c
Previous file: linux/net/ipv4/ip_nat_dumb.c
Back to the patch index
Back to the overall index
- Lines: 159
- Date:
Thu Apr 12 12:11:39 2001
- Orig file:
v2.4.3/linux/net/ipv4/ip_output.c
- Orig date:
Fri Oct 27 11:03:14 2000
diff -u --recursive --new-file v2.4.3/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
@@ -5,7 +5,7 @@
*
* The Internet Protocol (IP) output module.
*
- * Version: $Id: ip_output.c,v 1.87 2000/10/25 20:07:22 davem Exp $
+ * Version: $Id: ip_output.c,v 1.91 2001/03/29 06:25:55 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -95,7 +95,7 @@
static int ip_dev_loopback_xmit(struct sk_buff *newskb)
{
newskb->mac.raw = newskb->data;
- skb_pull(newskb, newskb->nh.raw - newskb->data);
+ __skb_pull(newskb, newskb->nh.raw - newskb->data);
newskb->pkt_type = PACKET_LOOPBACK;
newskb->ip_summed = CHECKSUM_UNNECESSARY;
BUG_TRAP(newskb->dst);
@@ -141,7 +141,7 @@
iph->saddr = rt->rt_src;
iph->protocol = sk->protocol;
iph->tot_len = htons(skb->len);
- ip_select_ident(iph, &rt->u.dst);
+ ip_select_ident(iph, &rt->u.dst, sk);
skb->nh.iph = iph;
if (opt && opt->optlen) {
@@ -307,7 +307,7 @@
if (ip_dont_fragment(sk, &rt->u.dst))
iph->frag_off |= __constant_htons(IP_DF);
- ip_select_ident(iph, &rt->u.dst);
+ ip_select_ident(iph, &rt->u.dst, sk);
/* Add an IP checksum. */
ip_send_check(iph);
@@ -328,7 +328,10 @@
kfree_skb(skb);
return -EMSGSIZE;
}
- ip_select_ident(iph, &rt->u.dst);
+ ip_select_ident(iph, &rt->u.dst, sk);
+ if (skb->ip_summed == CHECKSUM_HW &&
+ (skb = skb_checksum_help(skb)) == NULL)
+ return -ENOMEM;
return ip_fragment(skb, skb->dst->output);
}
@@ -358,6 +361,7 @@
sk->bound_dev_if))
goto no_route;
__sk_dst_set(sk, &rt->u.dst);
+ sk->route_caps = rt->u.dst.dev->features;
}
skb->dst = dst_clone(&rt->u.dst);
@@ -425,7 +429,7 @@
int err;
int offset, mf;
int mtu;
- u16 id = 0;
+ u16 id;
int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
int nfrags=0;
@@ -495,6 +499,8 @@
* Begin outputting the bytes.
*/
+ id = (sk ? sk->protinfo.af_inet.id++ : 0);
+
do {
char *data;
struct sk_buff * skb;
@@ -503,7 +509,7 @@
* Get the memory we require with some space left for alignment.
*/
- skb = sock_alloc_send_skb(sk, fraglen+hh_len+15, 0, flags&MSG_DONTWAIT, &err);
+ skb = sock_alloc_send_skb(sk, fraglen+hh_len+15, flags&MSG_DONTWAIT, &err);
if (skb == NULL)
goto error;
@@ -659,7 +665,7 @@
int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
skb = sock_alloc_send_skb(sk, length+hh_len+15,
- 0, flags&MSG_DONTWAIT, &err);
+ flags&MSG_DONTWAIT, &err);
if(skb==NULL)
goto error;
skb_reserve(skb, hh_len);
@@ -677,7 +683,7 @@
iph->tot_len = htons(length);
iph->frag_off = df;
iph->ttl=sk->protinfo.af_inet.mc_ttl;
- ip_select_ident(iph, &rt->u.dst);
+ ip_select_ident(iph, &rt->u.dst, sk);
if (rt->rt_type != RTN_MULTICAST)
iph->ttl=sk->protinfo.af_inet.ttl;
iph->protocol=sk->protocol;
@@ -722,8 +728,8 @@
int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
{
struct iphdr *iph;
- unsigned char *raw;
- unsigned char *ptr;
+ int raw = 0;
+ int ptr;
struct net_device *dev;
struct sk_buff *skb2;
unsigned int mtu, hlen, left, len;
@@ -738,17 +744,16 @@
* Point into the IP datagram header.
*/
- raw = skb->nh.raw;
- iph = (struct iphdr*)raw;
+ iph = skb->nh.iph;
/*
* Setup starting values.
*/
hlen = iph->ihl * 4;
- left = ntohs(iph->tot_len) - hlen; /* Space per frame */
+ left = skb->len - hlen; /* Space per frame */
mtu = rt->u.dst.pmtu - hlen; /* Size of data space */
- ptr = raw + hlen; /* Where to start from */
+ ptr = raw + hlen; /* Where to start from */
/*
* Fragment the datagram.
@@ -806,12 +811,13 @@
* Copy the packet header into the new buffer.
*/
- memcpy(skb2->nh.raw, raw, hlen);
+ memcpy(skb2->nh.raw, skb->data, hlen);
/*
* Copy a block of the IP datagram.
*/
- memcpy(skb2->h.raw, ptr, len);
+ if (skb_copy_bits(skb, ptr, skb2->h.raw, len))
+ BUG();
left -= len;
/*
@@ -828,6 +834,9 @@
*/
if (offset == 0)
ip_options_fragment(skb);
+
+ /* Copy the flags to each fragment. */
+ IPCB(skb2)->flags = IPCB(skb)->flags;
/*
* Added AC : If we are fragmenting a fragment that's not the
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)