patch-2.2.7 linux/net/ipv6/raw.c
Next file: linux/net/ipv6/tcp_ipv6.c
Previous file: linux/net/ipv6/ndisc.c
Back to the patch index
Back to the overall index
- Lines: 113
- Date:
Thu Apr 22 19:45:20 1999
- Orig file:
v2.2.6/linux/net/ipv6/raw.c
- Orig date:
Thu Nov 19 09:56:29 1998
diff -u --recursive --new-file v2.2.6/linux/net/ipv6/raw.c linux/net/ipv6/raw.c
@@ -7,7 +7,7 @@
*
* Adapted from linux/net/ipv4/raw.c
*
- * $Id: raw.c,v 1.23 1998/11/08 11:17:09 davem Exp $
+ * $Id: raw.c,v 1.24 1999/04/22 10:07:45 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -283,6 +283,7 @@
sin6->sin6_family = AF_INET6;
memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr,
sizeof(struct in6_addr));
+ sin6->sin6_flowinfo = 0;
}
if (sk->net_pinfo.af_inet6.rxopt.all)
@@ -363,7 +364,7 @@
struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;
struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
struct ipv6_txoptions *opt = NULL;
- struct in6_addr *saddr = NULL;
+ struct ip6_flowlabel *flowlabel = NULL;
struct flowi fl;
int addr_len = msg->msg_namelen;
struct in6_addr *daddr;
@@ -388,6 +389,8 @@
* Get and verify the address.
*/
+ fl.fl6_flowlabel = 0;
+
if (sin6) {
if (addr_len < sizeof(struct sockaddr_in6))
return(-EINVAL);
@@ -405,12 +408,28 @@
return(-EINVAL);
daddr = &sin6->sin6_addr;
+ if (np->sndflow) {
+ fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
+ if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
+ flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+ if (flowlabel == NULL)
+ return -EINVAL;
+ daddr = &flowlabel->dst;
+ }
+ }
+
+
+ /* Otherwise it will be difficult to maintain sk->dst_cache. */
+ if (sk->state == TCP_ESTABLISHED &&
+ !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr))
+ daddr = &sk->net_pinfo.af_inet6.daddr;
} else {
if (sk->state != TCP_ESTABLISHED)
return(-EINVAL);
proto = sk->num;
daddr = &(sk->net_pinfo.af_inet6.daddr);
+ fl.fl6_flowlabel = np->flow_label;
}
if (ipv6_addr_any(daddr)) {
@@ -422,23 +441,34 @@
}
fl.oif = sk->bound_dev_if;
+ fl.fl6_src = NULL;
if (msg->msg_controllen) {
opt = &opt_space;
memset(opt, 0, sizeof(struct ipv6_txoptions));
- err = datagram_send_ctl(msg, &fl.oif, &saddr, opt, &hlimit);
- if (err < 0)
+ err = datagram_send_ctl(msg, &fl, opt, &hlimit);
+ if (err < 0) {
+ fl6_sock_release(flowlabel);
return err;
+ }
+ if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
+ flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+ if (flowlabel == NULL)
+ return -EINVAL;
+ }
+ if (!(opt->opt_nflen|opt->opt_flen))
+ opt = NULL;
}
- if (opt == NULL || !(opt->opt_nflen|opt->opt_flen))
+ if (opt == NULL)
opt = np->opt;
+ if (flowlabel)
+ opt = fl6_merge_options(&opt_space, flowlabel, opt);
raw_opt = &sk->tp_pinfo.tp_raw;
fl.proto = proto;
- fl.nl_u.ip6_u.daddr = daddr;
- fl.nl_u.ip6_u.saddr = saddr;
+ fl.fl6_dst = daddr;
fl.uli_u.icmpt.type = 0;
fl.uli_u.icmpt.code = 0;
@@ -462,6 +492,8 @@
err = ip6_build_xmit(sk, rawv6_getfrag, msg->msg_iov, &fl, len,
opt, hlimit, msg->msg_flags);
}
+
+ fl6_sock_release(flowlabel);
return err<0?err:len;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)