Commit 3eef54d7 authored by Ville Nuorvala's avatar Ville Nuorvala Committed by David S. Miller

[IPV6]: Fix refcount leaks in udpv6_connect().

parent 431aa1db
......@@ -299,9 +299,10 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (addr_type == IPV6_ADDR_MAPPED) {
struct sockaddr_in sin;
if (__ipv6_only_sock(sk))
return -ENETUNREACH;
if (__ipv6_only_sock(sk)) {
err = -ENETUNREACH;
goto out;
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = daddr->s6_addr32[3];
sin.sin_port = usin->sin6_port;
......@@ -309,8 +310,8 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
err = udp_connect(sk, (struct sockaddr*) &sin, sizeof(sin));
ipv4_connected:
if (err < 0)
return err;
if (err)
goto out;
ipv6_addr_set(&np->daddr, 0, 0, htonl(0x0000ffff), inet->daddr);
......@@ -323,7 +324,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000ffff),
inet->rcv_saddr);
}
return 0;
goto out;
}
if (addr_type&IPV6_ADDR_LINKLOCAL) {
......@@ -331,8 +332,8 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
usin->sin6_scope_id) {
if (sk->sk_bound_dev_if &&
sk->sk_bound_dev_if != usin->sin6_scope_id) {
fl6_sock_release(flowlabel);
return -EINVAL;
err = -EINVAL;
goto out;
}
sk->sk_bound_dev_if = usin->sin6_scope_id;
if (!sk->sk_bound_dev_if &&
......@@ -341,8 +342,10 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
}
/* Connect to link-local address requires an interface */
if (!sk->sk_bound_dev_if)
return -EINVAL;
if (!sk->sk_bound_dev_if) {
err = -EINVAL;
goto out;
}
}
ipv6_addr_copy(&np->daddr, daddr);
......@@ -379,31 +382,33 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if ((err = dst->error) != 0) {
dst_release(dst);
fl6_sock_release(flowlabel);
return err;
goto out;
}
/* get the source address used in the appropriate device */
err = ipv6_get_saddr(dst, daddr, &fl.fl6_src);
if (err == 0) {
if (ipv6_addr_any(&np->saddr))
ipv6_addr_copy(&np->saddr, &fl.fl6_src);
if (ipv6_addr_any(&np->rcv_saddr)) {
ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
inet->rcv_saddr = LOOPBACK4_IPV6;
}
if (err) {
dst_release(dst);
goto out;
}
ip6_dst_store(sk, dst,
!ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
if (ipv6_addr_any(&np->saddr))
ipv6_addr_copy(&np->saddr, &fl.fl6_src);
sk->sk_state = TCP_ESTABLISHED;
if (ipv6_addr_any(&np->rcv_saddr)) {
ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
inet->rcv_saddr = LOOPBACK4_IPV6;
}
fl6_sock_release(flowlabel);
ip6_dst_store(sk, dst,
!ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
sk->sk_state = TCP_ESTABLISHED;
out:
fl6_sock_release(flowlabel);
return err;
}
......
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