Commit 094694d0 authored by David S. Miller's avatar David S. Miller

[IPV6]: Dont store pointers to in6_addrs in struct flowi.

parent 7e3683e3
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#ifndef _NET_FLOW_H #ifndef _NET_FLOW_H
#define _NET_FLOW_H #define _NET_FLOW_H
#include <linux/in6.h>
struct flowi { struct flowi {
int oif; int oif;
int iif; int iif;
...@@ -21,8 +23,8 @@ struct flowi { ...@@ -21,8 +23,8 @@ struct flowi {
} ip4_u; } ip4_u;
struct { struct {
struct in6_addr * daddr; struct in6_addr daddr;
struct in6_addr * saddr; struct in6_addr saddr;
__u32 flowlabel; __u32 flowlabel;
} ip6_u; } ip6_u;
......
...@@ -334,8 +334,7 @@ extern void ip6_flush_pending_frames(struct sock *sk); ...@@ -334,8 +334,7 @@ extern void ip6_flush_pending_frames(struct sock *sk);
extern int ip6_dst_lookup(struct sock *sk, extern int ip6_dst_lookup(struct sock *sk,
struct dst_entry **dst, struct dst_entry **dst,
struct flowi *fl, struct flowi *fl);
struct in6_addr **saddr);
/* /*
* skb processing functions * skb processing functions
......
...@@ -315,14 +315,14 @@ static inline u32 __flow_hash4(struct flowi *fl) ...@@ -315,14 +315,14 @@ static inline u32 __flow_hash4(struct flowi *fl)
static inline u32 __flow_hash6(struct flowi *fl) static inline u32 __flow_hash6(struct flowi *fl)
{ {
u32 hash = fl->fl6_src->s6_addr32[2] ^ u32 hash = fl->fl6_src.s6_addr32[2] ^
fl->fl6_src->s6_addr32[3] ^ fl->fl6_src.s6_addr32[3] ^
fl->fl_ip_sport; fl->fl_ip_sport;
hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4); hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
hash ^= fl->fl6_dst->s6_addr32[2] ^ hash ^= fl->fl6_dst.s6_addr32[2] ^
fl->fl6_dst->s6_addr32[3] ^ fl->fl6_dst.s6_addr32[3] ^
fl->fl_ip_dport; fl->fl_ip_dport;
hash ^= (hash >> 10); hash ^= (hash >> 10);
hash ^= (hash >> 20); hash ^= (hash >> 20);
...@@ -471,8 +471,8 @@ __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) ...@@ -471,8 +471,8 @@ __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
static inline int static inline int
__xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl) __xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
{ {
return addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) && return addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) && addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) && !((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) && !((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
(fl->proto == sel->proto || !sel->proto) && (fl->proto == sel->proto || !sel->proto) &&
...@@ -654,7 +654,7 @@ xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family) ...@@ -654,7 +654,7 @@ xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family)
case AF_INET: case AF_INET:
return (xfrm_address_t *)&fl->fl4_dst; return (xfrm_address_t *)&fl->fl4_dst;
case AF_INET6: case AF_INET6:
return (xfrm_address_t *)fl->fl6_dst; return (xfrm_address_t *)&fl->fl6_dst;
} }
return NULL; return NULL;
} }
...@@ -666,7 +666,7 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family) ...@@ -666,7 +666,7 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
case AF_INET: case AF_INET:
return (xfrm_address_t *)&fl->fl4_src; return (xfrm_address_t *)&fl->fl4_src;
case AF_INET6: case AF_INET6:
return (xfrm_address_t *)fl->fl6_src; return (xfrm_address_t *)&fl->fl6_src;
} }
return NULL; return NULL;
} }
......
...@@ -80,7 +80,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) ...@@ -80,7 +80,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info)
iph = (struct ipv6hdr*)skb_put(skb, sizeof(struct ipv6hdr)); iph = (struct ipv6hdr*)skb_put(skb, sizeof(struct ipv6hdr));
skb->nh.ipv6h = iph; skb->nh.ipv6h = iph;
ipv6_addr_copy(&iph->daddr, fl->fl6_dst); ipv6_addr_copy(&iph->daddr, &fl->fl6_dst);
serr = SKB_EXT_ERR(skb); serr = SKB_EXT_ERR(skb);
serr->ee.ee_errno = err; serr->ee.ee_errno = err;
...@@ -297,7 +297,8 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, ...@@ -297,7 +297,8 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
goto exit_f; goto exit_f;
} }
fl->fl6_src = &src_info->ipi6_addr; ipv6_addr_copy(&fl->fl6_src,
&src_info->ipi6_addr);
} }
break; break;
......
...@@ -223,9 +223,10 @@ int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hd ...@@ -223,9 +223,10 @@ int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hd
if (skb_queue_len(&sk->write_queue) == 1) { if (skb_queue_len(&sk->write_queue) == 1) {
skb->csum = csum_partial((char *)icmp6h, skb->csum = csum_partial((char *)icmp6h,
sizeof(struct icmp6hdr), skb->csum); sizeof(struct icmp6hdr), skb->csum);
icmp6h->icmp6_cksum = csum_ipv6_magic(fl->fl6_src, icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
fl->fl6_dst, &fl->fl6_dst,
len, fl->proto, skb->csum); len, fl->proto,
skb->csum);
} else { } else {
u32 tmp_csum = 0; u32 tmp_csum = 0;
...@@ -235,8 +236,8 @@ int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hd ...@@ -235,8 +236,8 @@ int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hd
tmp_csum = csum_partial((char *)icmp6h, tmp_csum = csum_partial((char *)icmp6h,
sizeof(struct icmp6hdr), tmp_csum); sizeof(struct icmp6hdr), tmp_csum);
tmp_csum = csum_ipv6_magic(fl->fl6_src, tmp_csum = csum_ipv6_magic(&fl->fl6_src,
fl->fl6_dst, &fl->fl6_dst,
len, fl->proto, tmp_csum); len, fl->proto, tmp_csum);
icmp6h->icmp6_cksum = tmp_csum; icmp6h->icmp6_cksum = tmp_csum;
} }
...@@ -266,7 +267,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, ...@@ -266,7 +267,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
struct ipv6hdr *hdr = skb->nh.ipv6h; struct ipv6hdr *hdr = skb->nh.ipv6h;
struct sock *sk = icmpv6_socket->sk; struct sock *sk = icmpv6_socket->sk;
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct in6_addr *saddr = NULL, *tmp_saddr = NULL; struct in6_addr *saddr = NULL;
struct dst_entry *dst; struct dst_entry *dst;
struct icmp6hdr tmp_hdr; struct icmp6hdr tmp_hdr;
struct flowi fl; struct flowi fl;
...@@ -332,11 +333,12 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, ...@@ -332,11 +333,12 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
return; return;
} }
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_ICMPV6; fl.proto = IPPROTO_ICMPV6;
fl.fl6_dst = &hdr->saddr; ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
fl.fl6_src = saddr; if (saddr)
ipv6_addr_copy(&fl.fl6_src, saddr);
fl.oif = iif; fl.oif = iif;
fl.fl6_flowlabel = 0;
fl.fl_icmp_type = type; fl.fl_icmp_type = type;
fl.fl_icmp_code = code; fl.fl_icmp_code = code;
...@@ -350,14 +352,14 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, ...@@ -350,14 +352,14 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
tmp_hdr.icmp6_cksum = 0; tmp_hdr.icmp6_cksum = 0;
tmp_hdr.icmp6_pointer = htonl(info); tmp_hdr.icmp6_pointer = htonl(info);
if (!fl.oif && ipv6_addr_is_multicast(fl.fl6_dst)) if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif; fl.oif = np->mcast_oif;
err = ip6_dst_lookup(sk, &dst, &fl, &tmp_saddr); err = ip6_dst_lookup(sk, &dst, &fl);
if (err) goto out; if (err) goto out;
if (hlimit < 0) { if (hlimit < 0) {
if (ipv6_addr_is_multicast(fl.fl6_dst)) if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops; hlimit = np->mcast_hops;
else else
hlimit = np->hop_limit; hlimit = np->hop_limit;
...@@ -394,7 +396,6 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, ...@@ -394,7 +396,6 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
if (likely(idev != NULL)) if (likely(idev != NULL))
in6_dev_put(idev); in6_dev_put(idev);
out: out:
if (tmp_saddr) kfree(tmp_saddr);
icmpv6_xmit_unlock(); icmpv6_xmit_unlock();
} }
...@@ -403,7 +404,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) ...@@ -403,7 +404,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
struct sock *sk = icmpv6_socket->sk; struct sock *sk = icmpv6_socket->sk;
struct inet6_dev *idev; struct inet6_dev *idev;
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct in6_addr *saddr = NULL, *tmp_saddr = NULL; struct in6_addr *saddr = NULL;
struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw; struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
struct icmp6hdr tmp_hdr; struct icmp6hdr tmp_hdr;
struct flowi fl; struct flowi fl;
...@@ -420,25 +421,25 @@ static void icmpv6_echo_reply(struct sk_buff *skb) ...@@ -420,25 +421,25 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr)); memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY; tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY;
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_ICMPV6; fl.proto = IPPROTO_ICMPV6;
fl.fl6_dst = &skb->nh.ipv6h->saddr; ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
fl.fl6_src = saddr; if (saddr)
ipv6_addr_copy(&fl.fl6_src, saddr);
fl.oif = skb->dev->ifindex; fl.oif = skb->dev->ifindex;
fl.fl6_flowlabel = 0;
fl.fl_icmp_type = ICMPV6_ECHO_REPLY; fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
fl.fl_icmp_code = 0;
icmpv6_xmit_lock(); icmpv6_xmit_lock();
if (!fl.oif && ipv6_addr_is_multicast(fl.nl_u.ip6_u.daddr)) if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif; fl.oif = np->mcast_oif;
err = ip6_dst_lookup(sk, &dst, &fl, &tmp_saddr); err = ip6_dst_lookup(sk, &dst, &fl);
if (err) goto out; if (err) goto out;
if (hlimit < 0) { if (hlimit < 0) {
if (ipv6_addr_is_multicast(fl.fl6_dst)) if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops; hlimit = np->mcast_hops;
else else
hlimit = np->hop_limit; hlimit = np->hop_limit;
...@@ -464,7 +465,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) ...@@ -464,7 +465,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (likely(idev != NULL)) if (likely(idev != NULL))
in6_dev_put(idev); in6_dev_put(idev);
out: out:
if (tmp_saddr) kfree(tmp_saddr);
icmpv6_xmit_unlock(); icmpv6_xmit_unlock();
} }
......
...@@ -152,15 +152,14 @@ int ip6_route_me_harder(struct sk_buff *skb) ...@@ -152,15 +152,14 @@ int ip6_route_me_harder(struct sk_buff *skb)
{ {
struct ipv6hdr *iph = skb->nh.ipv6h; struct ipv6hdr *iph = skb->nh.ipv6h;
struct dst_entry *dst; struct dst_entry *dst;
struct flowi fl; struct flowi fl = {
.oif = skb->sk ? skb->sk->bound_dev_if : 0,
fl.proto = iph->nexthdr; .nl_u =
fl.fl6_dst = &iph->daddr; { .ip6_u =
fl.fl6_src = &iph->saddr; { .daddr = iph->daddr,
fl.oif = skb->sk ? skb->sk->bound_dev_if : 0; .saddr = iph->saddr, } },
fl.fl6_flowlabel = 0; .proto = iph->nexthdr,
fl.fl_ip_dport = 0; };
fl.fl_ip_sport = 0;
dst = ip6_route_output(skb->sk, &fl); dst = ip6_route_output(skb->sk, &fl);
...@@ -200,7 +199,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ...@@ -200,7 +199,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
struct ipv6_txoptions *opt) struct ipv6_txoptions *opt)
{ {
struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL; struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL;
struct in6_addr *first_hop = fl->fl6_dst; struct in6_addr *first_hop = &fl->fl6_dst;
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
struct ipv6hdr *hdr; struct ipv6hdr *hdr;
u8 proto = fl->proto; u8 proto = fl->proto;
...@@ -255,7 +254,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ...@@ -255,7 +254,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
hdr->nexthdr = proto; hdr->nexthdr = proto;
hdr->hop_limit = hlimit; hdr->hop_limit = hlimit;
ipv6_addr_copy(&hdr->saddr, fl->fl6_src); ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
ipv6_addr_copy(&hdr->daddr, first_hop); ipv6_addr_copy(&hdr->daddr, first_hop);
mtu = dst_pmtu(dst); mtu = dst_pmtu(dst);
...@@ -320,8 +319,8 @@ static struct ipv6hdr * ip6_bld_1(struct sock *sk, struct sk_buff *skb, struct f ...@@ -320,8 +319,8 @@ static struct ipv6hdr * ip6_bld_1(struct sock *sk, struct sk_buff *skb, struct f
hdr->hop_limit = hlimit; hdr->hop_limit = hlimit;
hdr->nexthdr = fl->proto; hdr->nexthdr = fl->proto;
ipv6_addr_copy(&hdr->saddr, fl->fl6_src); ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
ipv6_addr_copy(&hdr->daddr, fl->fl6_dst); ipv6_addr_copy(&hdr->daddr, &fl->fl6_dst);
return hdr; return hdr;
} }
...@@ -526,19 +525,19 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data, ...@@ -526,19 +525,19 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
{ {
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct in6_addr *final_dst = NULL; struct in6_addr final_dst_buf, *final_dst = NULL;
struct dst_entry *dst; struct dst_entry *dst;
int err = 0; int err = 0;
unsigned int pktlength, jumbolen, mtu; unsigned int pktlength, jumbolen, mtu;
struct in6_addr saddr;
if (opt && opt->srcrt) { if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
final_dst = fl->fl6_dst; ipv6_addr_copy(&final_dst_buf, &fl->fl6_dst);
fl->fl6_dst = rt0->addr; final_dst = &final_dst_buf;
ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
} }
if (!fl->oif && ipv6_addr_is_multicast(fl->fl6_dst)) if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
fl->oif = np->mcast_oif; fl->oif = np->mcast_oif;
dst = __sk_dst_check(sk, np->dst_cookie); dst = __sk_dst_check(sk, np->dst_cookie);
...@@ -564,9 +563,9 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data, ...@@ -564,9 +563,9 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
*/ */
if (((rt->rt6i_dst.plen != 128 || if (((rt->rt6i_dst.plen != 128 ||
ipv6_addr_cmp(fl->fl6_dst, &rt->rt6i_dst.addr)) ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr))
&& (np->daddr_cache == NULL || && (np->daddr_cache == NULL ||
ipv6_addr_cmp(fl->fl6_dst, np->daddr_cache))) ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache)))
|| (fl->oif && fl->oif != dst->dev->ifindex)) { || (fl->oif && fl->oif != dst->dev->ifindex)) {
dst = NULL; dst = NULL;
} else } else
...@@ -582,8 +581,8 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data, ...@@ -582,8 +581,8 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
return -ENETUNREACH; return -ENETUNREACH;
} }
if (fl->fl6_src == NULL) { if (ipv6_addr_any(&fl->fl6_src)) {
err = ipv6_get_saddr(dst, fl->fl6_dst, &saddr); err = ipv6_get_saddr(dst, &fl->fl6_dst, &fl->fl6_src);
if (err) { if (err) {
#if IP6_DEBUG >= 2 #if IP6_DEBUG >= 2
...@@ -592,7 +591,6 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data, ...@@ -592,7 +591,6 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
#endif #endif
goto out; goto out;
} }
fl->fl6_src = &saddr;
} }
pktlength = length; pktlength = length;
...@@ -604,7 +602,7 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data, ...@@ -604,7 +602,7 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
} }
if (hlimit < 0) { if (hlimit < 0) {
if (ipv6_addr_is_multicast(fl->fl6_dst)) if (ipv6_addr_is_multicast(&fl->fl6_dst))
hlimit = np->mcast_hops; hlimit = np->mcast_hops;
else else
hlimit = np->hop_limit; hlimit = np->hop_limit;
...@@ -715,7 +713,9 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data, ...@@ -715,7 +713,9 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
* cleanup * cleanup
*/ */
out: out:
ip6_dst_store(sk, dst, fl->fl6_dst == &np->daddr ? &np->daddr : NULL); ip6_dst_store(sk, dst,
!ipv6_addr_cmp(&fl->fl6_dst, &np->daddr) ?
&np->daddr : NULL);
if (err > 0) if (err > 0)
err = np->recverr ? net_xmit_errno(err) : 0; err = np->recverr ? net_xmit_errno(err) : 0;
return err; return err;
...@@ -1135,7 +1135,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -1135,7 +1135,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
return err; return err;
} }
int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl, struct in6_addr **saddr) int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
{ {
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
int err = 0; int err = 0;
...@@ -1163,9 +1163,9 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl, st ...@@ -1163,9 +1163,9 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl, st
*/ */
if (((rt->rt6i_dst.plen != 128 || if (((rt->rt6i_dst.plen != 128 ||
ipv6_addr_cmp(fl->fl6_dst, &rt->rt6i_dst.addr)) ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr))
&& (np->daddr_cache == NULL || && (np->daddr_cache == NULL ||
ipv6_addr_cmp(fl->fl6_dst, np->daddr_cache))) ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache)))
|| (fl->oif && fl->oif != (*dst)->dev->ifindex)) { || (fl->oif && fl->oif != (*dst)->dev->ifindex)) {
*dst = NULL; *dst = NULL;
} else } else
...@@ -1181,9 +1181,8 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl, st ...@@ -1181,9 +1181,8 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl, st
return -ENETUNREACH; return -ENETUNREACH;
} }
if (fl->fl6_src == NULL) { if (ipv6_addr_any(&fl->fl6_src)) {
*saddr = kmalloc(sizeof(struct in6_addr), GFP_ATOMIC); err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
err = ipv6_get_saddr(*dst, fl->fl6_dst, *saddr);
if (err) { if (err) {
#if IP6_DEBUG >= 2 #if IP6_DEBUG >= 2
...@@ -1192,7 +1191,6 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl, st ...@@ -1192,7 +1191,6 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl, st
#endif #endif
return err; return err;
} }
fl->fl6_src = *saddr;
} }
if (*dst) { if (*dst) {
...@@ -1415,7 +1413,7 @@ int ip6_push_pending_frames(struct sock *sk) ...@@ -1415,7 +1413,7 @@ int ip6_push_pending_frames(struct sock *sk)
{ {
struct sk_buff *skb, *tmp_skb; struct sk_buff *skb, *tmp_skb;
struct sk_buff **tail_skb; struct sk_buff **tail_skb;
struct in6_addr *final_dst = NULL; struct in6_addr final_dst_buf, *final_dst = &final_dst_buf;
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct ipv6hdr *hdr; struct ipv6hdr *hdr;
...@@ -1446,7 +1444,7 @@ int ip6_push_pending_frames(struct sock *sk) ...@@ -1446,7 +1444,7 @@ int ip6_push_pending_frames(struct sock *sk)
#endif #endif
} }
final_dst = fl->fl6_dst; ipv6_addr_copy(final_dst, &fl->fl6_dst);
__skb_pull(skb, skb->h.raw - skb->nh.raw); __skb_pull(skb, skb->h.raw - skb->nh.raw);
if (opt && opt->opt_flen) if (opt && opt->opt_flen)
ipv6_push_frag_opts(skb, opt, &proto); ipv6_push_frag_opts(skb, opt, &proto);
...@@ -1463,7 +1461,7 @@ int ip6_push_pending_frames(struct sock *sk) ...@@ -1463,7 +1461,7 @@ int ip6_push_pending_frames(struct sock *sk)
hdr->payload_len = 0; hdr->payload_len = 0;
hdr->hop_limit = np->hop_limit; hdr->hop_limit = np->hop_limit;
hdr->nexthdr = proto; hdr->nexthdr = proto;
ipv6_addr_copy(&hdr->saddr, fl->fl6_src); ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
ipv6_addr_copy(&hdr->daddr, final_dst); ipv6_addr_copy(&hdr->daddr, final_dst);
skb->dst = dst_clone(&rt->u.dst); skb->dst = dst_clone(&rt->u.dst);
......
...@@ -405,8 +405,8 @@ static inline void ndisc_flow_init(struct flowi *fl, u8 type, ...@@ -405,8 +405,8 @@ static inline void ndisc_flow_init(struct flowi *fl, u8 type,
struct in6_addr *saddr, struct in6_addr *daddr) struct in6_addr *saddr, struct in6_addr *daddr)
{ {
memset(fl, 0, sizeof(*fl)); memset(fl, 0, sizeof(*fl));
fl->fl6_src = saddr; ipv6_addr_copy(&fl->fl6_src, saddr);
fl->fl6_dst = daddr; ipv6_addr_copy(&fl->fl6_dst, daddr);
fl->proto = IPPROTO_ICMPV6; fl->proto = IPPROTO_ICMPV6;
fl->fl_icmp_type = type; fl->fl_icmp_type = type;
fl->fl_icmp_code = 0; fl->fl_icmp_code = 0;
......
...@@ -461,8 +461,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct r ...@@ -461,8 +461,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct r
* Only one fragment on the socket. * Only one fragment on the socket.
*/ */
/* should be check HW csum miyazawa */ /* should be check HW csum miyazawa */
*csum = csum_ipv6_magic(fl->fl6_src, *csum = csum_ipv6_magic(&fl->fl6_src,
fl->fl6_dst, &fl->fl6_dst,
len, fl->proto, skb->csum); len, fl->proto, skb->csum);
} else { } else {
u32 tmp_csum = 0; u32 tmp_csum = 0;
...@@ -471,8 +471,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct r ...@@ -471,8 +471,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct r
tmp_csum = csum_add(tmp_csum, skb->csum); tmp_csum = csum_add(tmp_csum, skb->csum);
} }
tmp_csum = csum_ipv6_magic(fl->fl6_src, tmp_csum = csum_ipv6_magic(&fl->fl6_src,
fl->fl6_dst, &fl->fl6_dst,
len, fl->proto, tmp_csum); len, fl->proto, tmp_csum);
*csum = tmp_csum; *csum = tmp_csum;
} }
...@@ -540,7 +540,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -540,7 +540,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
{ {
struct ipv6_txoptions opt_space; struct ipv6_txoptions opt_space;
struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;
struct in6_addr *daddr, *saddr = NULL; struct in6_addr *daddr;
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct raw6_opt *raw_opt = raw6_sk(sk); struct raw6_opt *raw_opt = raw6_sk(sk);
...@@ -566,9 +566,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -566,9 +566,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
/* /*
* Get and verify the address. * Get and verify the address.
*/ */
memset(&fl, 0, sizeof(fl));
fl.fl6_flowlabel = 0;
fl.oif = 0;
if (sin6) { if (sin6) {
if (addr_len < SIN6_LEN_RFC2133) if (addr_len < SIN6_LEN_RFC2133)
...@@ -628,7 +626,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -628,7 +626,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
if (fl.oif == 0) if (fl.oif == 0)
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
fl.fl6_src = NULL;
if (msg->msg_controllen) { if (msg->msg_controllen) {
opt = &opt_space; opt = &opt_space;
...@@ -653,26 +650,25 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -653,26 +650,25 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
opt = fl6_merge_options(&opt_space, flowlabel, opt); opt = fl6_merge_options(&opt_space, flowlabel, opt);
fl.proto = proto; fl.proto = proto;
fl.fl6_dst = daddr; ipv6_addr_copy(&fl.fl6_dst, daddr);
if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr)) if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
fl.fl6_src = &np->saddr; ipv6_addr_copy(&fl.fl6_src, &np->saddr);
fl.fl_icmp_type = 0;
fl.fl_icmp_code = 0;
/* merge ip6_build_xmit from ip6_output */ /* merge ip6_build_xmit from ip6_output */
if (opt && opt->srcrt) { if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
if (!fl.oif && ipv6_addr_is_multicast(fl.nl_u.ip6_u.daddr)) if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif; fl.oif = np->mcast_oif;
err = ip6_dst_lookup(sk, &dst, &fl, &saddr); err = ip6_dst_lookup(sk, &dst, &fl);
if (err) goto out; if (err)
goto out;
if (hlimit < 0) { if (hlimit < 0) {
if (ipv6_addr_is_multicast(fl.fl6_dst)) if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops; hlimit = np->mcast_hops;
else else
hlimit = np->hop_limit; hlimit = np->hop_limit;
...@@ -702,14 +698,15 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -702,14 +698,15 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
} }
} }
done: done:
ip6_dst_store(sk, dst, fl.nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL); ip6_dst_store(sk, dst,
!ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
if (err > 0) if (err > 0)
err = np->recverr ? net_xmit_errno(err) : 0; err = np->recverr ? net_xmit_errno(err) : 0;
release_sock(sk); release_sock(sk);
out: out:
fl6_sock_release(flowlabel); fl6_sock_release(flowlabel);
if (saddr) kfree(saddr);
return err<0?err:len; return err<0?err:len;
do_confirm: do_confirm:
dst_confirm(dst); dst_confirm(dst);
......
...@@ -454,12 +454,12 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) ...@@ -454,12 +454,12 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
int strict; int strict;
int attempts = 3; int attempts = 3;
strict = ipv6_addr_type(fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL);
relookup: relookup:
read_lock_bh(&rt6_lock); read_lock_bh(&rt6_lock);
fn = fib6_lookup(&ip6_routing_table, fl->fl6_dst, fl->fl6_src); fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src);
restart: restart:
rt = fn->leaf; rt = fn->leaf;
...@@ -481,7 +481,7 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) ...@@ -481,7 +481,7 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
rt = rt6_cow(rt, fl->fl6_dst, fl->fl6_src); rt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src);
if (rt->u.dst.error != -EEXIST || --attempts <= 0) if (rt->u.dst.error != -EEXIST || --attempts <= 0)
goto out2; goto out2;
...@@ -1616,9 +1616,11 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) ...@@ -1616,9 +1616,11 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
memset(&fl, 0, sizeof(fl)); memset(&fl, 0, sizeof(fl));
if (rta[RTA_SRC-1]) if (rta[RTA_SRC-1])
fl.fl6_src = (struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]); ipv6_addr_copy(&fl.fl6_src,
(struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]));
if (rta[RTA_DST-1]) if (rta[RTA_DST-1])
fl.fl6_dst = (struct in6_addr*)RTA_DATA(rta[RTA_DST-1]); ipv6_addr_copy(&fl.fl6_dst,
(struct in6_addr*)RTA_DATA(rta[RTA_DST-1]));
if (rta[RTA_IIF-1]) if (rta[RTA_IIF-1])
memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int)); memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
...@@ -1642,7 +1644,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) ...@@ -1642,7 +1644,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
err = rt6_fill_node(skb, rt, err = rt6_fill_node(skb, rt,
fl.fl6_dst, fl.fl6_src, &fl.fl6_dst, &fl.fl6_src,
iif, iif,
RTM_NEWROUTE, NETLINK_CB(in_skb).pid, RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
nlh->nlmsg_seq, nlh); nlh->nlmsg_seq, nlh);
......
...@@ -571,7 +571,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -571,7 +571,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
if (usin->sin6_family != AF_INET6) if (usin->sin6_family != AF_INET6)
return(-EAFNOSUPPORT); return(-EAFNOSUPPORT);
fl.fl6_flowlabel = 0; memset(&fl, 0, sizeof(fl));
if (np->sndflow) { if (np->sndflow) {
fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
IP6_ECN_flow_init(fl.fl6_flowlabel); IP6_ECN_flow_init(fl.fl6_flowlabel);
...@@ -666,20 +667,18 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -666,20 +667,18 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
saddr = &np->rcv_saddr; saddr = &np->rcv_saddr;
fl.proto = IPPROTO_TCP; fl.proto = IPPROTO_TCP;
fl.fl6_dst = &np->daddr; ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
fl.fl6_src = saddr; ipv6_addr_copy(&fl.fl6_src,
(saddr ? saddr : &np->saddr));
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
fl.fl_ip_dport = usin->sin6_port; fl.fl_ip_dport = usin->sin6_port;
fl.fl_ip_sport = inet->sport; fl.fl_ip_sport = inet->sport;
if (np->opt && np->opt->srcrt) { if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
if (!fl.fl6_src)
fl.fl6_src = &np->saddr;
dst = ip6_route_output(sk, &fl); dst = ip6_route_output(sk, &fl);
if ((err = dst->error) != 0) { if ((err = dst->error) != 0) {
...@@ -794,9 +793,10 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -794,9 +793,10 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
to handle rthdr case. Ignore this complexity to handle rthdr case. Ignore this complexity
for now. for now.
*/ */
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_TCP; fl.proto = IPPROTO_TCP;
fl.fl6_dst = &np->daddr; ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
fl.fl6_src = &np->saddr; ipv6_addr_copy(&fl.fl6_src, &np->saddr);
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
fl.fl_ip_dport = inet->dport; fl.fl_ip_dport = inet->dport;
fl.fl_ip_sport = inet->sport; fl.fl_ip_sport = inet->sport;
...@@ -879,9 +879,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req, ...@@ -879,9 +879,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
struct flowi fl; struct flowi fl;
int err = -1; int err = -1;
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_TCP; fl.proto = IPPROTO_TCP;
fl.fl6_dst = &req->af.v6_req.rmt_addr; ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
fl.fl6_src = &req->af.v6_req.loc_addr; ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
fl.fl6_flowlabel = 0; fl.fl6_flowlabel = 0;
fl.oif = req->af.v6_req.iif; fl.oif = req->af.v6_req.iif;
fl.fl_ip_dport = req->rmt_port; fl.fl_ip_dport = req->rmt_port;
...@@ -900,7 +901,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req, ...@@ -900,7 +901,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
if (opt && opt->srcrt) { if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
dst = ip6_route_output(sk, &fl); dst = ip6_route_output(sk, &fl);
...@@ -916,7 +917,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req, ...@@ -916,7 +917,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
&req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr, &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr,
csum_partial((char *)th, skb->len, skb->csum)); csum_partial((char *)th, skb->len, skb->csum));
fl.fl6_dst = &req->af.v6_req.rmt_addr; ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
err = ip6_xmit(sk, skb, &fl, opt); err = ip6_xmit(sk, skb, &fl, opt);
if (err == NET_XMIT_CN) if (err == NET_XMIT_CN)
err = 0; err = 0;
...@@ -1018,11 +1019,11 @@ static void tcp_v6_send_reset(struct sk_buff *skb) ...@@ -1018,11 +1019,11 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
fl.fl6_dst = &skb->nh.ipv6h->saddr; memset(&fl, 0, sizeof(fl));
fl.fl6_src = &skb->nh.ipv6h->daddr; ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
fl.fl6_flowlabel = 0; ipv6_addr_copy(&fl.fl6_src, &skb->nh.ipv6h->daddr);
t1->check = csum_ipv6_magic(fl.fl6_src, fl.fl6_dst, t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
sizeof(*t1), IPPROTO_TCP, sizeof(*t1), IPPROTO_TCP,
buff->csum); buff->csum);
...@@ -1082,11 +1083,11 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ...@@ -1082,11 +1083,11 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
buff->csum = csum_partial((char *)t1, tot_len, 0); buff->csum = csum_partial((char *)t1, tot_len, 0);
fl.fl6_dst = &skb->nh.ipv6h->saddr; memset(&fl, 0, sizeof(fl));
fl.fl6_src = &skb->nh.ipv6h->daddr; ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
fl.fl6_flowlabel = 0; ipv6_addr_copy(&fl.fl6_src, &skb->nh.ipv6h->daddr);
t1->check = csum_ipv6_magic(fl.fl6_src, fl.fl6_dst, t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
tot_len, IPPROTO_TCP, tot_len, IPPROTO_TCP,
buff->csum); buff->csum);
...@@ -1261,7 +1262,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, ...@@ -1261,7 +1262,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
{ {
struct ipv6_pinfo *newnp, *np = inet6_sk(sk); struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct tcp6_sock *newtcp6sk; struct tcp6_sock *newtcp6sk;
struct flowi fl;
struct inet_opt *newinet; struct inet_opt *newinet;
struct tcp_opt *newtp; struct tcp_opt *newtp;
struct sock *newsk; struct sock *newsk;
...@@ -1330,14 +1330,16 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, ...@@ -1330,14 +1330,16 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
} }
if (dst == NULL) { if (dst == NULL) {
struct flowi fl;
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_TCP; fl.proto = IPPROTO_TCP;
fl.fl6_dst = &req->af.v6_req.rmt_addr; ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
if (opt && opt->srcrt) { if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
fl.fl6_src = &req->af.v6_req.loc_addr; ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
fl.fl6_flowlabel = 0;
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
fl.fl_ip_dport = req->rmt_port; fl.fl_ip_dport = req->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport; fl.fl_ip_sport = inet_sk(sk)->sport;
...@@ -1725,9 +1727,10 @@ static int tcp_v6_rebuild_header(struct sock *sk) ...@@ -1725,9 +1727,10 @@ static int tcp_v6_rebuild_header(struct sock *sk)
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct flowi fl; struct flowi fl;
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_TCP; fl.proto = IPPROTO_TCP;
fl.fl6_dst = &np->daddr; ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
fl.fl6_src = &np->saddr; ipv6_addr_copy(&fl.fl6_src, &np->saddr);
fl.fl6_flowlabel = np->flow_label; fl.fl6_flowlabel = np->flow_label;
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
fl.fl_ip_dport = inet->dport; fl.fl_ip_dport = inet->dport;
...@@ -1735,7 +1738,7 @@ static int tcp_v6_rebuild_header(struct sock *sk) ...@@ -1735,7 +1738,7 @@ static int tcp_v6_rebuild_header(struct sock *sk)
if (np->opt && np->opt->srcrt) { if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
dst = ip6_route_output(sk, &fl); dst = ip6_route_output(sk, &fl);
...@@ -1762,9 +1765,10 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok) ...@@ -1762,9 +1765,10 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
struct flowi fl; struct flowi fl;
struct dst_entry *dst; struct dst_entry *dst;
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_TCP; fl.proto = IPPROTO_TCP;
fl.fl6_dst = &np->daddr; ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
fl.fl6_src = &np->saddr; ipv6_addr_copy(&fl.fl6_src, &np->saddr);
fl.fl6_flowlabel = np->flow_label; fl.fl6_flowlabel = np->flow_label;
IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel); IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
...@@ -1773,7 +1777,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok) ...@@ -1773,7 +1777,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
if (np->opt && np->opt->srcrt) { if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
dst = __sk_dst_check(sk, np->dst_cookie); dst = __sk_dst_check(sk, np->dst_cookie);
...@@ -1793,7 +1797,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok) ...@@ -1793,7 +1797,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
skb->dst = dst_clone(dst); skb->dst = dst_clone(dst);
/* Restore final destination back after routing done */ /* Restore final destination back after routing done */
fl.fl6_dst = &np->daddr; ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
return ip6_xmit(sk, skb, &fl, np->opt); return ip6_xmit(sk, skb, &fl, np->opt);
} }
......
...@@ -270,7 +270,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -270,7 +270,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (usin->sin6_family != AF_INET6) if (usin->sin6_family != AF_INET6)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
fl.fl6_flowlabel = 0; memset(&fl, 0, sizeof(fl));
if (np->sndflow) { if (np->sndflow) {
fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK; fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
...@@ -350,8 +350,8 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -350,8 +350,8 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
*/ */
fl.proto = IPPROTO_UDP; fl.proto = IPPROTO_UDP;
fl.fl6_dst = &np->daddr; ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
fl.fl6_src = &saddr; ipv6_addr_copy(&fl.fl6_src, &saddr);
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
fl.fl_ip_dport = inet->dport; fl.fl_ip_dport = inet->dport;
fl.fl_ip_sport = inet->sport; fl.fl_ip_sport = inet->sport;
...@@ -362,11 +362,11 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -362,11 +362,11 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (flowlabel) { if (flowlabel) {
if (flowlabel->opt && flowlabel->opt->srcrt) { if (flowlabel->opt && flowlabel->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
} else if (np->opt && np->opt->srcrt) { } else if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
dst = ip6_route_output(sk, &fl); dst = ip6_route_output(sk, &fl);
...@@ -377,7 +377,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -377,7 +377,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
return err; return err;
} }
ip6_dst_store(sk, dst, fl.fl6_dst); ip6_dst_store(sk, dst, &fl.fl6_dst);
/* get the source address used in the appropriate device */ /* get the source address used in the appropriate device */
...@@ -784,8 +784,8 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_opt *up) ...@@ -784,8 +784,8 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_opt *up)
if (skb_queue_len(&sk->write_queue) == 1) { if (skb_queue_len(&sk->write_queue) == 1) {
skb->csum = csum_partial((char *)uh, skb->csum = csum_partial((char *)uh,
sizeof(struct udphdr), skb->csum); sizeof(struct udphdr), skb->csum);
uh->check = csum_ipv6_magic(fl->fl6_src, uh->check = csum_ipv6_magic(&fl->fl6_src,
fl->fl6_dst, &fl->fl6_dst,
up->len, fl->proto, skb->csum); up->len, fl->proto, skb->csum);
} else { } else {
u32 tmp_csum = 0; u32 tmp_csum = 0;
...@@ -795,8 +795,8 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_opt *up) ...@@ -795,8 +795,8 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_opt *up)
} }
tmp_csum = csum_partial((char *)uh, tmp_csum = csum_partial((char *)uh,
sizeof(struct udphdr), tmp_csum); sizeof(struct udphdr), tmp_csum);
tmp_csum = csum_ipv6_magic(fl->fl6_src, tmp_csum = csum_ipv6_magic(&fl->fl6_src,
fl->fl6_dst, &fl->fl6_dst,
up->len, fl->proto, tmp_csum); up->len, fl->proto, tmp_csum);
uh->check = tmp_csum; uh->check = tmp_csum;
...@@ -819,7 +819,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -819,7 +819,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
struct inet_opt *inet = inet_sk(sk); struct inet_opt *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
struct in6_addr *daddr, *saddr = NULL; struct in6_addr *daddr;
struct ipv6_txoptions *opt = NULL; struct ipv6_txoptions *opt = NULL;
struct ip6_flowlabel *flowlabel = NULL; struct ip6_flowlabel *flowlabel = NULL;
struct flowi fl; struct flowi fl;
...@@ -849,8 +849,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -849,8 +849,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
} }
ulen += sizeof(struct udphdr); ulen += sizeof(struct udphdr);
fl.fl6_flowlabel = 0; memset(&fl, 0, sizeof(fl));
fl.oif = 0;
if (sin6) { if (sin6) {
if (sin6->sin6_family == AF_INET) { if (sin6->sin6_family == AF_INET) {
...@@ -919,7 +918,6 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -919,7 +918,6 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
if (!fl.oif) if (!fl.oif)
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
fl.fl6_src = NULL;
if (msg->msg_controllen) { if (msg->msg_controllen) {
opt = &opt_space; opt = &opt_space;
...@@ -944,26 +942,27 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -944,26 +942,27 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
opt = fl6_merge_options(&opt_space, flowlabel, opt); opt = fl6_merge_options(&opt_space, flowlabel, opt);
fl.proto = IPPROTO_UDP; fl.proto = IPPROTO_UDP;
fl.fl6_dst = daddr; ipv6_addr_copy(&fl.fl6_dst, daddr);
if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr)) if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
fl.fl6_src = &np->saddr; ipv6_addr_copy(&fl.fl6_src, &np->saddr);
fl.fl_ip_dport = up->dport; fl.fl_ip_dport = up->dport;
fl.fl_ip_sport = inet->sport; fl.fl_ip_sport = inet->sport;
/* merge ip6_build_xmit from ip6_output */ /* merge ip6_build_xmit from ip6_output */
if (opt && opt->srcrt) { if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
fl.fl6_dst = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
if (!fl.oif && ipv6_addr_is_multicast(fl.nl_u.ip6_u.daddr)) if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif; fl.oif = np->mcast_oif;
err = ip6_dst_lookup(sk, &dst, &fl, &saddr); err = ip6_dst_lookup(sk, &dst, &fl);
if (err) goto out; if (err)
goto out;
if (hlimit < 0) { if (hlimit < 0) {
if (ipv6_addr_is_multicast(fl.fl6_dst)) if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops; hlimit = np->mcast_hops;
else else
hlimit = np->hop_limit; hlimit = np->hop_limit;
...@@ -998,13 +997,14 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -998,13 +997,14 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
else if (!corkreq) else if (!corkreq)
err = udp_v6_push_pending_frames(sk, up); err = udp_v6_push_pending_frames(sk, up);
ip6_dst_store(sk, dst, fl.nl_u.ip6_u.daddr == &np->daddr ? &np->daddr : NULL); ip6_dst_store(sk, dst,
!ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
if (err > 0) if (err > 0)
err = np->recverr ? net_xmit_errno(err) : 0; err = np->recverr ? net_xmit_errno(err) : 0;
release_sock(sk); release_sock(sk);
out: out:
fl6_sock_release(flowlabel); fl6_sock_release(flowlabel);
if (saddr) kfree(saddr);
if (!err) { if (!err) {
UDP6_INC_STATS_USER(UdpOutDatagrams); UDP6_INC_STATS_USER(UdpOutDatagrams);
return len; return len;
......
...@@ -60,8 +60,8 @@ __xfrm6_find_bundle(struct flowi *fl, struct rtable *rt, struct xfrm_policy *pol ...@@ -60,8 +60,8 @@ __xfrm6_find_bundle(struct flowi *fl, struct rtable *rt, struct xfrm_policy *pol
read_lock_bh(&policy->lock); read_lock_bh(&policy->lock);
for (dst = policy->bundles; dst; dst = dst->next) { for (dst = policy->bundles; dst; dst = dst->next) {
struct xfrm_dst *xdst = (struct xfrm_dst*)dst; struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, fl->fl6_dst) && if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, &fl->fl6_dst) &&
!ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, fl->fl6_src) && !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, &fl->fl6_src) &&
__xfrm6_bundle_ok(xdst, fl)) { __xfrm6_bundle_ok(xdst, fl)) {
dst_clone(dst); dst_clone(dst);
break; break;
...@@ -82,8 +82,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int ...@@ -82,8 +82,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
struct dst_entry *dst, *dst_prev; struct dst_entry *dst, *dst_prev;
struct rt6_info *rt0 = (struct rt6_info*)(*dst_p); struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
struct rt6_info *rt = rt0; struct rt6_info *rt = rt0;
struct in6_addr *remote = fl->fl6_dst; struct in6_addr *remote = &fl->fl6_dst;
struct in6_addr *local = fl->fl6_src; struct in6_addr *local = &fl->fl6_src;
int i; int i;
int err = 0; int err = 0;
int header_len = 0; int header_len = 0;
...@@ -116,13 +116,15 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int ...@@ -116,13 +116,15 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
trailer_len += xfrm[i]->props.trailer_len; trailer_len += xfrm[i]->props.trailer_len;
} }
if (ipv6_addr_cmp(remote, fl->fl6_dst)) { if (ipv6_addr_cmp(remote, &fl->fl6_dst)) {
struct flowi fl_tunnel = { .nl_u = { .ip6_u = struct flowi fl_tunnel;
{ .daddr = remote,
.saddr = local } memset(&fl_tunnel, 0, sizeof(fl_tunnel));
} ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
}; ipv6_addr_copy(&fl_tunnel.fl6_src, local);
err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET6);
err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
&fl_tunnel, AF_INET6);
if (err) if (err)
goto error; goto error;
} else { } else {
...@@ -175,8 +177,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) ...@@ -175,8 +177,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
u8 nexthdr = skb->nh.ipv6h->nexthdr; u8 nexthdr = skb->nh.ipv6h->nexthdr;
fl->fl6_dst = &hdr->daddr; ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
fl->fl6_src = &hdr->saddr; ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
switch (nexthdr) { switch (nexthdr) {
......
...@@ -25,8 +25,8 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, ...@@ -25,8 +25,8 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
{ {
/* Initialize temporary selector matching only /* Initialize temporary selector matching only
* to current session. */ * to current session. */
ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, fl->fl6_dst); ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, fl->fl6_src); ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
x->sel.dport = fl->fl_ip_dport; x->sel.dport = fl->fl_ip_dport;
x->sel.dport_mask = ~0; x->sel.dport_mask = ~0;
x->sel.sport = fl->fl_ip_sport; x->sel.sport = fl->fl_ip_sport;
......
...@@ -144,17 +144,19 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, ...@@ -144,17 +144,19 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi fl; struct flowi fl;
memset(&fl, 0, sizeof(fl));
fl.proto = sk->protocol; fl.proto = sk->protocol;
/* Fill in the dest address from the route entry passed with the skb /* Fill in the dest address from the route entry passed with the skb
* and the source address from the transport. * and the source address from the transport.
*/ */
fl.fl6_dst = &transport->ipaddr.v6.sin6_addr; ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr.v6.sin6_addr);
fl.fl6_src = &transport->saddr.v6.sin6_addr; ipv6_addr_copy(&fl.fl6_src, &transport->saddr.v6.sin6_addr);
fl.fl6_flowlabel = np->flow_label; fl.fl6_flowlabel = np->flow_label;
IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel); IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
if (ipv6_addr_type(fl.fl6_src) & IPV6_ADDR_LINKLOCAL) if (ipv6_addr_type(&fl.fl6_src) & IPV6_ADDR_LINKLOCAL)
fl.oif = transport->saddr.v6.sin6_scope_id; fl.oif = transport->saddr.v6.sin6_scope_id;
else else
fl.oif = sk->bound_dev_if; fl.oif = sk->bound_dev_if;
...@@ -163,14 +165,14 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, ...@@ -163,14 +165,14 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
if (np->opt && np->opt->srcrt) { if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
fl.nl_u.ip6_u.daddr = rt0->addr; ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
} }
SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
"src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
"dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
__FUNCTION__, skb, skb->len, __FUNCTION__, skb, skb->len,
NIP6(*fl.fl6_src), NIP6(*fl.fl6_dst)); NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
SCTP_INC_STATS(SctpOutSCTPPacks); SCTP_INC_STATS(SctpOutSCTPPacks);
...@@ -185,17 +187,19 @@ struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, ...@@ -185,17 +187,19 @@ struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
union sctp_addr *saddr) union sctp_addr *saddr)
{ {
struct dst_entry *dst; struct dst_entry *dst;
struct flowi fl = { struct flowi fl;
.nl_u = { .ip6_u = { .daddr = &daddr->v6.sin6_addr, } } };
memset(&fl, 0, sizeof(fl));
ipv6_addr_copy(&fl.fl6_dst, &daddr->v6.sin6_addr);
SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
__FUNCTION__, NIP6(*fl.fl6_dst)); __FUNCTION__, NIP6(fl.fl6_dst));
if (saddr) { if (saddr) {
fl.fl6_src = &saddr->v6.sin6_addr; ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
SCTP_DEBUG_PRINTK( SCTP_DEBUG_PRINTK(
"SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - ", "SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - ",
NIP6(*fl.fl6_src)); NIP6(fl.fl6_src));
} }
dst = ip6_route_output(NULL, &fl); dst = ip6_route_output(NULL, &fl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment