patch-2.3.15 linux/net/ipv6/ip6_output.c
Next file: linux/net/ipv6/ipv6_sockglue.c
Previous file: linux/net/ipv6/ip6_input.c
Back to the patch index
Back to the overall index
- Lines: 197
- Date:
Mon Aug 23 10:01:02 1999
- Orig file:
v2.3.14/linux/net/ipv6/ip6_output.c
- Orig date:
Wed Aug 18 11:38:49 1999
diff -u --recursive --new-file v2.3.14/linux/net/ipv6/ip6_output.c linux/net/ipv6/ip6_output.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: ip6_output.c,v 1.20 1999/06/09 10:11:12 davem Exp $
+ * $Id: ip6_output.c,v 1.22 1999/08/20 11:06:21 davem Exp $
*
* Based on linux/net/ipv4/ip_output.c
*
@@ -149,14 +149,11 @@
if (skb->len <= dst->pmtu) {
ipv6_statistics.Ip6OutRequests++;
- dst->output(skb);
- return 0;
+ return dst->output(skb);
}
printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n");
- start_bh_atomic();
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev);
- end_bh_atomic();
kfree_skb(skb);
return -EMSGSIZE;
}
@@ -317,6 +314,9 @@
data_off = frag_off - opt->opt_flen;
}
+ if (flags&MSG_PROBE)
+ return 0;
+
last_skb = sock_alloc_send_skb(sk, unfrag_len + frag_len +
dst->dev->hard_header_len + 15,
0, flags & MSG_DONTWAIT, &err);
@@ -352,7 +352,7 @@
kfree_skb(last_skb);
return -ENOMEM;
}
-
+
frag_off -= frag_len;
data_off -= frag_len;
@@ -378,7 +378,11 @@
ipv6_statistics.Ip6FragCreates++;
ipv6_statistics.Ip6OutRequests++;
- dst->output(skb);
+ err = dst->output(skb);
+ if (err) {
+ kfree_skb(last_skb);
+ return err;
+ }
}
}
@@ -400,9 +404,7 @@
ipv6_statistics.Ip6FragCreates++;
ipv6_statistics.Ip6FragOKs++;
ipv6_statistics.Ip6OutRequests++;
- dst->output(last_skb);
-
- return 0;
+ return dst->output(last_skb);
}
int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
@@ -425,11 +427,9 @@
if (!fl->oif && ipv6_addr_is_multicast(fl->nl_u.ip6_u.daddr))
fl->oif = np->mcast_oif;
- dst = NULL;
- if (sk->dst_cache) {
- dst = dst_check(&sk->dst_cache, np->dst_cookie);
- if (dst) {
- struct rt6_info *rt = (struct rt6_info*)dst_clone(dst);
+ dst = __sk_dst_check(sk, np->dst_cookie);
+ if (dst) {
+ struct rt6_info *rt = (struct rt6_info*)dst;
/* Yes, checking route validity in not connected
case is not very simple. Take into account,
@@ -448,15 +448,15 @@
sockets.
2. oif also should be the same.
*/
- if (((rt->rt6i_dst.plen != 128 ||
- ipv6_addr_cmp(fl->fl6_dst, &rt->rt6i_dst.addr))
- && (np->daddr_cache == NULL ||
- ipv6_addr_cmp(fl->fl6_dst, np->daddr_cache)))
- || (fl->oif && fl->oif != dst->dev->ifindex)) {
- dst_release(dst);
- dst = NULL;
- }
- }
+
+ if (((rt->rt6i_dst.plen != 128 ||
+ ipv6_addr_cmp(fl->fl6_dst, &rt->rt6i_dst.addr))
+ && (np->daddr_cache == NULL ||
+ ipv6_addr_cmp(fl->fl6_dst, np->daddr_cache)))
+ || (fl->oif && fl->oif != dst->dev->ifindex)) {
+ dst = NULL;
+ } else
+ dst_clone(dst);
}
if (dst == NULL)
@@ -493,14 +493,14 @@
jumbolen = 0;
- if (!sk->ip_hdrincl) {
+ if (!sk->protinfo.af_inet.hdrincl) {
pktlength += sizeof(struct ipv6hdr);
if (opt)
pktlength += opt->opt_flen + opt->opt_nflen;
if (pktlength > 0xFFFF + sizeof(struct ipv6hdr)) {
/* Jumbo datagram.
- It is assumed, that in the case of sk->ip_hdrincl
+ It is assumed, that in the case of hdrincl
jumbo option is supplied by user.
*/
pktlength += 8;
@@ -525,11 +525,18 @@
goto out;
}
+ if (flags&MSG_CONFIRM)
+ dst_confirm(dst);
+
if (pktlength <= mtu) {
struct sk_buff *skb;
struct ipv6hdr *hdr;
struct net_device *dev = dst->dev;
+ err = 0;
+ if (flags&MSG_PROBE)
+ goto out;
+
skb = sock_alloc_send_skb(sk, pktlength + 15 +
dev->hard_header_len, 0,
flags & MSG_DONTWAIT, &err);
@@ -546,7 +553,7 @@
hdr = (struct ipv6hdr *) skb->tail;
skb->nh.ipv6h = hdr;
- if (!sk->ip_hdrincl) {
+ if (!sk->protinfo.af_inet.hdrincl) {
ip6_bld_1(sk, skb, fl, hlimit,
jumbolen ? sizeof(struct ipv6hdr) : pktlength);
@@ -565,13 +572,13 @@
if (!err) {
ipv6_statistics.Ip6OutRequests++;
- dst->output(skb);
+ err = dst->output(skb);
} else {
err = -EFAULT;
kfree_skb(skb);
}
} else {
- if (sk->ip_hdrincl || jumbolen ||
+ if (sk->protinfo.af_inet.hdrincl || jumbolen ||
np->pmtudisc == IPV6_PMTUDISC_DO) {
ipv6_local_error(sk, EMSGSIZE, fl, mtu);
err = -EMSGSIZE;
@@ -587,6 +594,8 @@
*/
out:
ip6_dst_store(sk, dst, fl->nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL);
+ if (err > 0)
+ err = np->recverr ? net_xmit_errno(err) : 0;
return err;
}
@@ -595,6 +604,7 @@
struct ip6_ra_chain *ra;
struct sock *last = NULL;
+ read_lock(&ip6_ra_lock);
for (ra = ip6_ra_chain; ra; ra = ra->next) {
struct sock *sk = ra->sk;
if (sk && ra->sel == sel) {
@@ -609,8 +619,10 @@
if (last) {
rawv6_rcv(last, skb, skb->len);
+ read_unlock(&ip6_ra_lock);
return 1;
}
+ read_unlock(&ip6_ra_lock);
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)