int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
- struct in6_addr *daddr;
+ struct in6_addr *daddr, *final_p = NULL, final;
struct dst_entry *dst;
struct flowi fl;
struct ip6_flowlabel *flowlabel = NULL;
if (flowlabel) {
if (flowlabel->opt && flowlabel->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
} else if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto out;
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ dst_release(dst);
+ goto out;
+ }
/* source address lookup done in ip6_dst_lookup */
}
ip6_dst_store(sk, dst,
- !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
+ ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
sk->sk_state = TCP_ESTABLISHED;
if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
sin->sin6_scope_id = IP6CB(skb)->iif;
} else {
- struct inet_opt *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
ipv6_addr_set(&sin->sin6_addr, 0, 0,
htonl(0xffff),
int addr_type;
struct net_device *dev = NULL;
- if (cmsg->cmsg_len < sizeof(struct cmsghdr) ||
- (unsigned long)(((char*)cmsg - (char*)msg->msg_control)
- + cmsg->cmsg_len) > msg->msg_controllen) {
+ if (!CMSG_OK(msg, cmsg)) {
err = -EINVAL;
goto exit_f;
}