patch-2.2.7 linux/net/ipv6/datagram.c
Next file: linux/net/ipv6/ip6_fib.c
Previous file: linux/net/ipv6/af_inet6.c
Back to the patch index
Back to the overall index
- Lines: 114
- Date:
Thu Apr 22 19:45:20 1999
- Orig file:
v2.2.6/linux/net/ipv6/datagram.c
- Orig date:
Mon Oct 5 13:13:49 1998
diff -u --recursive --new-file v2.2.6/linux/net/ipv6/datagram.c linux/net/ipv6/datagram.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: datagram.c,v 1.16 1998/10/03 09:38:25 davem Exp $
+ * $Id: datagram.c,v 1.17 1999/04/22 10:07:40 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -132,10 +132,13 @@
sin = (struct sockaddr_in6 *)msg->msg_name;
if (sin) {
sin->sin6_family = AF_INET6;
+ sin->sin6_flowinfo = 0;
sin->sin6_port = serr->port;
- if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6)
+ if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) {
memcpy(&sin->sin6_addr, skb->nh.raw + serr->addr_offset, 16);
- else
+ if (sk->net_pinfo.af_inet6.sndflow)
+ sin->sin6_flowinfo = *(u32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK;
+ } else
ipv6_addr_set(&sin->sin6_addr, 0, 0,
__constant_htonl(0xffff),
*(u32*)(skb->nh.raw + serr->addr_offset));
@@ -146,6 +149,7 @@
sin->sin6_family = AF_UNSPEC;
if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
sin->sin6_family = AF_INET6;
+ sin->sin6_flowinfo = 0;
if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) {
memcpy(&sin->sin6_addr, &skb->nh.ipv6h->saddr, 16);
if (sk->net_pinfo.af_inet6.rxopt.all)
@@ -199,6 +203,10 @@
put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
}
+ if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) {
+ u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK;
+ put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo);
+ }
if (np->rxopt.bits.hopopts && opt->hop) {
u8 *ptr = skb->nh.raw + opt->hop;
put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr);
@@ -222,8 +230,8 @@
return 0;
}
-int datagram_send_ctl(struct msghdr *msg, int *oif,
- struct in6_addr **src_addr, struct ipv6_txoptions *opt,
+int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
+ struct ipv6_txoptions *opt,
int *hlimit)
{
struct in6_pktinfo *src_info;
@@ -235,17 +243,15 @@
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
- if ((unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
+ (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
+ cmsg->cmsg_len) > msg->msg_controllen) {
err = -EINVAL;
goto exit_f;
}
- if (cmsg->cmsg_level != SOL_IPV6) {
- if (net_ratelimit())
- printk(KERN_DEBUG "invalid cmsg_level %d\n", cmsg->cmsg_level);
+ if (cmsg->cmsg_level != SOL_IPV6)
continue;
- }
switch (cmsg->cmsg_type) {
case IPV6_PKTINFO:
@@ -257,9 +263,9 @@
src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
if (src_info->ipi6_ifindex) {
- if (*oif && src_info->ipi6_ifindex != *oif)
+ if (fl->oif && src_info->ipi6_ifindex != fl->oif)
return -EINVAL;
- *oif = src_info->ipi6_ifindex;
+ fl->oif = src_info->ipi6_ifindex;
}
if (!ipv6_addr_any(&src_info->ipi6_addr)) {
@@ -272,9 +278,24 @@
goto exit_f;
}
- *src_addr = &src_info->ipi6_addr;
+ fl->fl6_src = &src_info->ipi6_addr;
+ }
+
+ break;
+
+ case IPV6_FLOWINFO:
+ if (cmsg->cmsg_len < CMSG_LEN(4)) {
+ err = -EINVAL;
+ goto exit_f;
}
+ if (fl->fl6_flowlabel&IPV6_FLOWINFO_MASK) {
+ if ((fl->fl6_flowlabel^*(u32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) {
+ err = -EINVAL;
+ goto exit_f;
+ }
+ }
+ fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg);
break;
case IPV6_HOPOPTS:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)