patch-2.1.79 linux/net/ipv4/ip_output.c
Next file: linux/net/ipv4/ip_sockglue.c
Previous file: linux/net/ipv4/ip_input.c
Back to the patch index
Back to the overall index
- Lines: 441
- Date:
Mon Jan 12 15:28:28 1998
- Orig file:
v2.1.78/linux/net/ipv4/ip_output.c
- Orig date:
Fri Dec 19 15:53:06 1997
diff -u --recursive --new-file v2.1.78/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.41 1997/11/28 15:32:37 alan Exp $
+ * Version: $Id: ip_output.c,v 1.44 1997/12/27 20:41:14 kuznet Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -76,13 +76,6 @@
int sysctl_ip_dynaddr = 0;
-static void __inline__ ip_ll_header_reserve(struct sk_buff *skb)
-{
- struct rtable *rt = (struct rtable*)skb->dst;
- skb_reserve(skb, (rt->u.dst.dev->hard_header_len+15)&~15);
- ip_ll_header(skb);
-}
-
int ip_id_count = 0;
@@ -105,19 +98,15 @@
return err;
}
- if (opt && opt->is_strictroute && rt->rt_flags&RTF_GATEWAY) {
+ if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
ip_rt_put(rt);
ip_statistics.IpOutNoRoutes++;
return -ENETUNREACH;
}
skb->dst = dst_clone(&rt->u.dst);
+ skb_reserve(skb, (rt->u.dst.dev->hard_header_len+15)&~15);
- skb->dev = rt->u.dst.dev;
- skb->arp = 0;
-
- ip_ll_header_reserve(skb);
-
/*
* Now build the IP header.
*/
@@ -184,7 +173,7 @@
sk->dst_cache = &rt->u.dst;
}
- if (opt && opt->is_strictroute && rt->rt_flags&RTF_GATEWAY) {
+ if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
sk->dst_cache = NULL;
ip_rt_put(rt);
ip_statistics.IpOutNoRoutes++;
@@ -192,11 +181,7 @@
}
skb->dst = dst_clone(sk->dst_cache);
-
- skb->dev = rt->u.dst.dev;
- skb->arp = 0;
skb_reserve(skb, MAX_HEADER);
- skb->mac.raw = skb->data;
/*
* Now build the IP header.
@@ -234,6 +219,11 @@
return 0;
}
+int __ip_finish_output(struct sk_buff *skb)
+{
+ return ip_finish_output(skb);
+}
+
int ip_mc_output(struct sk_buff *skb)
{
struct sock *sk = skb->sk;
@@ -245,14 +235,13 @@
*/
ip_statistics.IpOutRequests++;
-#ifdef CONFIG_IP_ACCT
- ip_fw_chk(skb->nh.iph, skb->dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
-#endif
#ifdef CONFIG_IP_ROUTE_NAT
if (rt->rt_flags & RTCF_NAT)
ip_do_nat(skb);
#endif
+ skb->dev = dev;
+
/*
* Multicasts are looped back for other local users
*/
@@ -279,7 +268,7 @@
dev_loopback_xmit(skb);
/* Multicasts with ttl 0 must not go beyond the host */
-
+
if (skb->nh.iph->ttl == 0) {
kfree_skb(skb, FREE_WRITE);
return 0;
@@ -296,44 +285,23 @@
dev_loopback_xmit(skb);
}
- if (dev->flags & IFF_UP) {
- dev_queue_xmit(skb);
- return 0;
- }
- ip_statistics.IpOutDiscards++;
-
- kfree_skb(skb, FREE_WRITE);
- return -ENETDOWN;
+ return ip_finish_output(skb);
}
int ip_output(struct sk_buff *skb)
{
+#ifdef CONFIG_IP_ROUTE_NAT
struct rtable *rt = (struct rtable*)skb->dst;
- struct device *dev = rt->u.dst.dev;
+#endif
- /*
- * If the indicated interface is up and running, send the packet.
- */
-
ip_statistics.IpOutRequests++;
-#ifdef CONFIG_IP_ACCT
- ip_fw_chk(skb->nh.iph, skb->dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
-#endif
-
#ifdef CONFIG_IP_ROUTE_NAT
if (rt->rt_flags&RTCF_NAT)
ip_do_nat(skb);
#endif
- if (dev->flags & IFF_UP) {
- dev_queue_xmit(skb);
- return 0;
- }
- ip_statistics.IpOutDiscards++;
-
- kfree_skb(skb, FREE_WRITE);
- return -ENETDOWN;
+ return ip_finish_output(skb);
}
#ifdef CONFIG_IP_ACCT
@@ -349,7 +317,7 @@
return 0;
}
-#endif
+#endif
/*
* Generate a checksum for an outgoing IP datagram.
@@ -380,13 +348,7 @@
unsigned int tot_len;
struct iphdr *iph = skb->nh.iph;
- /*
- * Discard the surplus MAC header
- */
-
- skb_pull(skb, skb->nh.raw - skb->data);
tot_len = skb->len;
-
iph->tot_len = htons(tot_len);
iph->id = htons(ip_id_count++);
@@ -399,7 +361,7 @@
kfree_skb(skb, FREE_WRITE);
return;
}
-
+
#ifdef CONFIG_NET_SECURITY
/*
* Add an IP checksum (must do this before SECurity because
@@ -413,7 +375,7 @@
kfree_skb(skb, FREE_WRITE);
return;
}
-
+
iph = skb->nh.iph;
/* don't update tot_len, as the dev->mtu is already decreased */
#endif
@@ -433,9 +395,6 @@
iph = skb->nh.iph;
}
- ip_ll_header(skb);
-
-
/*
* Do we need to fragment. Again this is inefficient.
* We need to somehow lock the original buffer and use
@@ -484,13 +443,9 @@
return;
}
- ip_fragment(skb, 1, skb->dst->output);
-
-
+ ip_fragment(skb, skb->dst->output);
}
-
-
/*
* Build and send a packet, with as little as one copy
*
@@ -509,7 +464,6 @@
* the source IP address (may depend on the routing table), the
* destination address (char *), the offset to copy from, and the
* length to be copied.
- *
*/
int ip_build_xmit(struct sock *sk,
@@ -518,7 +472,7 @@
unsigned int,
unsigned int),
const void *frag,
- unsigned short length,
+ unsigned length,
struct ipcm_cookie *ipc,
struct rtable *rt,
int flags)
@@ -528,7 +482,7 @@
int offset, mf;
unsigned short id;
struct iphdr *iph;
- int hh_len = rt->u.dst.dev->hard_header_len;
+ int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
int nfrags=0;
struct ip_options *opt = ipc->opt;
int df = htons(IP_DF);
@@ -551,7 +505,7 @@
if (length <= rt->u.dst.pmtu && opt == NULL) {
int error;
- struct sk_buff *skb=sock_alloc_send_skb(sk, length+15+hh_len,
+ struct sk_buff *skb=sock_alloc_send_skb(sk, length+hh_len+15,
0, flags&MSG_DONTWAIT, &error);
if(skb==NULL) {
ip_statistics.IpOutDiscards++;
@@ -561,8 +515,7 @@
skb->when=jiffies;
skb->priority = sk->priority;
skb->dst = dst_clone(&rt->u.dst);
-
- ip_ll_header_reserve(skb);
+ skb_reserve(skb, hh_len);
skb->nh.iph = iph = (struct iphdr *)skb_put(skb, length);
@@ -592,7 +545,7 @@
if (err)
err = -EFAULT;
- if(!err && call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb) < FW_ACCEPT)
+ if(!err && call_out_firewall(PF_INET, rt->u.dst.dev, iph, NULL, &skb) < FW_ACCEPT)
err = -EPERM;
#ifdef CONFIG_NET_SECURITY
if ((fw_res=call_out_firewall(PF_SECURITY, NULL, NULL, (void *) 5, &skb))<FW_ACCEPT)
@@ -618,12 +571,10 @@
length -= sizeof(struct iphdr);
if (opt) {
- fragheaderlen = hh_len + sizeof(struct iphdr) + opt->optlen;
+ fragheaderlen = sizeof(struct iphdr) + opt->optlen;
maxfraglen = ((rt->u.dst.pmtu-sizeof(struct iphdr)-opt->optlen) & ~7) + fragheaderlen;
} else {
- fragheaderlen = hh_len;
- if(!sk->ip_hdrincl)
- fragheaderlen += sizeof(struct iphdr);
+ fragheaderlen = sk->ip_hdrincl ? 0 : sizeof(struct iphdr);
/*
* Fragheaderlen is the size of 'overhead' on each buffer. Now work
@@ -633,6 +584,9 @@
maxfraglen = ((rt->u.dst.pmtu-sizeof(struct iphdr)) & ~7) + fragheaderlen;
}
+ if (length + fragheaderlen > 0xFFFF)
+ return -EMSGSIZE;
+
/*
* Start at the end of the frame by handling the remainder.
*/
@@ -689,7 +643,7 @@
* Get the memory we require with some space left for alignment.
*/
- skb = sock_alloc_send_skb(sk, fraglen+15, 0, flags&MSG_DONTWAIT, &error);
+ skb = sock_alloc_send_skb(sk, fraglen+hh_len+15, 0, flags&MSG_DONTWAIT, &error);
if (skb == NULL) {
ip_statistics.IpOutDiscards++;
if(nfrags>1)
@@ -705,14 +659,13 @@
skb->when = jiffies;
skb->priority = sk->priority;
skb->dst = dst_clone(&rt->u.dst);
-
- ip_ll_header_reserve(skb);
+ skb_reserve(skb, hh_len);
/*
* Find where to start putting bytes.
*/
- data = skb_put(skb, fraglen-hh_len);
+ data = skb_put(skb, fraglen);
skb->nh.iph = iph = (struct iphdr *)data;
/*
@@ -762,7 +715,7 @@
* Account for the fragment.
*/
- if(!err && !offset && call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb) < FW_ACCEPT)
+ if(!err && !offset && call_out_firewall(PF_INET, rt->u.dst.dev, iph, NULL, &skb) < FW_ACCEPT)
err = -EPERM;
#ifdef CONFIG_NET_SECURITY
if ((fw_res=call_out_firewall(PF_SECURITY, NULL, NULL, (void *) 6, &skb))<FW_ACCEPT)
@@ -800,17 +753,14 @@
/*
* This IP datagram is too large to be sent in one piece. Break it up into
- * smaller pieces (each of size equal to the MAC header plus IP header plus
+ * smaller pieces (each of size equal to IP header plus
* a block of the data of the original IP data part) that will yet fit in a
* single device frame, and queue such a frame for sending.
*
- * Assumption: packet was ready for transmission, link layer header
- * is already in.
- *
* Yes this is inefficient, feel free to submit a quicker one.
*/
-
-void ip_fragment(struct sk_buff *skb, int local, int (*output)(struct sk_buff*))
+
+void ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
{
struct iphdr *iph;
unsigned char *raw;
@@ -823,14 +773,14 @@
u16 dont_fragment;
struct rtable *rt = (struct rtable*)skb->dst;
- dev = skb->dev;
+ dev = rt->u.dst.dev;
/*
* Point into the IP datagram header.
*/
- raw = skb->data;
- iph = skb->nh.iph;
+ raw = skb->nh.raw;
+ iph = (struct iphdr*)raw;
/*
* Setup starting values.
@@ -838,11 +788,7 @@
hlen = iph->ihl * 4;
left = ntohs(iph->tot_len) - hlen; /* Space per frame */
- hlen += skb->nh.raw - raw;
- if (local)
- mtu = rt->u.dst.pmtu - hlen; /* Size of data space */
- else
- mtu = dev->mtu - hlen;
+ mtu = rt->u.dst.pmtu - hlen; /* Size of data space */
ptr = raw + hlen; /* Where to start from */
/*
@@ -891,7 +837,7 @@
* Allocate buffer.
*/
- if ((skb2 = alloc_skb(len+hlen+15,GFP_ATOMIC)) == NULL) {
+ if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15,GFP_ATOMIC)) == NULL) {
NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
ip_statistics.IpFragFails++;
kfree_skb(skb, FREE_WRITE);
@@ -902,15 +848,13 @@
* Set up data on packet
*/
- skb2->arp = skb->arp;
- skb2->dev = skb->dev;
skb2->when = skb->when;
skb2->pkt_type = skb->pkt_type;
skb2->priority = skb->priority;
+ skb_reserve(skb2, (dev->hard_header_len+15)&~15);
skb_put(skb2, len + hlen);
- skb2->mac.raw = (char *) skb2->data;
- skb2->nh.raw = skb2->mac.raw + dev->hard_header_len;
- skb2->h.raw = skb2->mac.raw + hlen;
+ skb2->nh.raw = skb2->data;
+ skb2->h.raw = skb2->data + hlen;
/*
* Charge the memory for the fragment to any owner
@@ -925,7 +869,7 @@
* Copy the packet header into the new buffer.
*/
- memcpy(skb2->mac.raw, raw, hlen);
+ memcpy(skb2->nh.raw, raw, hlen);
/*
* Copy a block of the IP datagram.
@@ -963,7 +907,7 @@
ip_statistics.IpFragCreates++;
- iph->tot_len = htons(len + hlen - dev->hard_header_len);
+ iph->tot_len = htons(len + hlen);
ip_send_check(iph);
@@ -1008,8 +952,7 @@
reply->priority = skb->priority;
reply->dst = &rt->u.dst;
-
- ip_ll_header_reserve(reply);
+ skb_reserve(reply, (rt->u.dst.dev->hard_header_len+15)&~15);
/*
* Now build the IP header.
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov