Commit 9c841195 authored by Sridhar Samudrala's avatar Sridhar Samudrala

[SCTP] getsockname()/getpeername() support for TCP-style sockets.

parent 293f0d65
...@@ -232,7 +232,9 @@ struct sctp_af { ...@@ -232,7 +232,9 @@ struct sctp_af {
int saddr); int saddr);
void (*from_sk) (union sctp_addr *, void (*from_sk) (union sctp_addr *,
struct sock *sk); struct sock *sk);
void (*to_sk) (union sctp_addr *, void (*to_sk_saddr) (union sctp_addr *,
struct sock *sk);
void (*to_sk_daddr) (union sctp_addr *,
struct sock *sk); struct sock *sk);
int (*addr_valid) (union sctp_addr *); int (*addr_valid) (union sctp_addr *);
sctp_scope_t (*scope) (union sctp_addr *); sctp_scope_t (*scope) (union sctp_addr *);
......
...@@ -370,11 +370,17 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) ...@@ -370,11 +370,17 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
} }
/* Initialize sk->rcv_saddr from sctp_addr. */ /* Initialize sk->rcv_saddr from sctp_addr. */
static void sctp_v6_to_sk(union sctp_addr *addr, struct sock *sk) static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
{ {
inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr; inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
} }
/* Initialize sk->daddr from sctp_addr. */
static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
{
inet6_sk(sk)->daddr = addr->v6.sin6_addr;
}
/* Initialize a sctp_addr from a dst_entry. */ /* Initialize a sctp_addr from a dst_entry. */
static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
unsigned short port) unsigned short port)
...@@ -523,10 +529,14 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -523,10 +529,14 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
memcpy(newnp, np, sizeof(struct ipv6_pinfo)); memcpy(newnp, np, sizeof(struct ipv6_pinfo));
ipv6_addr_copy(&newnp->daddr, &asoc->peer.primary_addr.v6.sin6_addr); /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
* and getpeername().
*/
newinet->sport = inet->sport; newinet->sport = inet->sport;
newinet->dport = asoc->peer.port; newnp->saddr = np->saddr;
newnp->rcv_saddr = np->rcv_saddr;
newinet->dport = htons(asoc->peer.port);
newnp->daddr = asoc->peer.primary_addr.v6.sin6_addr;
#ifdef INET_REFCNT_DEBUG #ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr); atomic_inc(&inet6_sock_nr);
...@@ -799,7 +809,8 @@ static struct sctp_af sctp_ipv6_specific = { ...@@ -799,7 +809,8 @@ static struct sctp_af sctp_ipv6_specific = {
.copy_addrlist = sctp_v6_copy_addrlist, .copy_addrlist = sctp_v6_copy_addrlist,
.from_skb = sctp_v6_from_skb, .from_skb = sctp_v6_from_skb,
.from_sk = sctp_v6_from_sk, .from_sk = sctp_v6_from_sk,
.to_sk = sctp_v6_to_sk, .to_sk_saddr = sctp_v6_to_sk_saddr,
.to_sk_daddr = sctp_v6_to_sk_daddr,
.dst_saddr = sctp_v6_dst_saddr, .dst_saddr = sctp_v6_dst_saddr,
.cmp_addr = sctp_v6_cmp_addr, .cmp_addr = sctp_v6_cmp_addr,
.scope = sctp_v6_scope, .scope = sctp_v6_scope,
......
...@@ -266,11 +266,16 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk) ...@@ -266,11 +266,16 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
} }
/* Initialize sk->rcv_saddr from sctp_addr. */ /* Initialize sk->rcv_saddr from sctp_addr. */
static void sctp_v4_to_sk(union sctp_addr *addr, struct sock *sk) static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
{ {
inet_sk(sk)->rcv_saddr = addr->v4.sin_addr.s_addr; inet_sk(sk)->rcv_saddr = addr->v4.sin_addr.s_addr;
} }
/* Initialize sk->daddr from sctp_addr. */
static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
{
inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr;
}
/* Initialize a sctp_addr from a dst_entry. */ /* Initialize a sctp_addr from a dst_entry. */
static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst,
...@@ -475,7 +480,13 @@ void sctp_v4_get_saddr(struct sctp_association *asoc, ...@@ -475,7 +480,13 @@ void sctp_v4_get_saddr(struct sctp_association *asoc,
union sctp_addr *daddr, union sctp_addr *daddr,
union sctp_addr *saddr) union sctp_addr *saddr)
{ {
struct rtable *rt = (struct rtable *)dst;
if (rt) {
saddr->v4.sin_family = AF_INET;
saddr->v4.sin_port = asoc->base.bind_addr.port;
saddr->v4.sin_addr.s_addr = rt->rt_src;
}
} }
/* What interface did this skb arrive on? */ /* What interface did this skb arrive on? */
...@@ -512,10 +523,14 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, ...@@ -512,10 +523,14 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
newsk->backlog_rcv = sk->prot->backlog_rcv; newsk->backlog_rcv = sk->prot->backlog_rcv;
newinet = inet_sk(newsk); newinet = inet_sk(newsk);
/* Initialize sk's sport, dport, rcv_saddr and daddr for
* getsockname() and getpeername()
*/
newinet->sport = inet->sport; newinet->sport = inet->sport;
newinet->saddr = inet->saddr; newinet->saddr = inet->saddr;
newinet->rcv_saddr = inet->saddr; newinet->rcv_saddr = inet->rcv_saddr;
newinet->dport = asoc->peer.port; newinet->dport = htons(asoc->peer.port);
newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
newinet->pmtudisc = inet->pmtudisc; newinet->pmtudisc = inet->pmtudisc;
newinet->id = 0; newinet->id = 0;
...@@ -802,7 +817,8 @@ struct sctp_af sctp_ipv4_specific = { ...@@ -802,7 +817,8 @@ struct sctp_af sctp_ipv4_specific = {
.copy_addrlist = sctp_v4_copy_addrlist, .copy_addrlist = sctp_v4_copy_addrlist,
.from_skb = sctp_v4_from_skb, .from_skb = sctp_v4_from_skb,
.from_sk = sctp_v4_from_sk, .from_sk = sctp_v4_from_sk,
.to_sk = sctp_v4_to_sk, .to_sk_saddr = sctp_v4_to_sk_saddr,
.to_sk_daddr = sctp_v4_to_sk_daddr,
.dst_saddr = sctp_v4_dst_saddr, .dst_saddr = sctp_v4_dst_saddr,
.cmp_addr = sctp_v4_cmp_addr, .cmp_addr = sctp_v4_cmp_addr,
.addr_valid = sctp_v4_addr_valid, .addr_valid = sctp_v4_addr_valid,
......
...@@ -261,7 +261,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) ...@@ -261,7 +261,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
/* Copy back into socket for getsockname() use. */ /* Copy back into socket for getsockname() use. */
if (!ret) { if (!ret) {
inet_sk(sk)->sport = htons(inet_sk(sk)->num); inet_sk(sk)->sport = htons(inet_sk(sk)->num);
af->to_sk(addr, sk); af->to_sk_saddr(addr, sk);
} }
return ret; return ret;
...@@ -1574,6 +1574,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -1574,6 +1574,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
struct sctp_association *asoc; struct sctp_association *asoc;
struct sctp_transport *transport; struct sctp_transport *transport;
union sctp_addr to; union sctp_addr to;
struct sctp_af *af;
sctp_scope_t scope; sctp_scope_t scope;
long timeo; long timeo;
int err = 0; int err = 0;
...@@ -1661,6 +1662,11 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -1661,6 +1662,11 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
goto out_unlock; goto out_unlock;
} }
/* Initialize sk's dport and daddr for getpeername() */
inet_sk(sk)->dport = htons(asoc->peer.port);
af = sctp_get_af_specific(to.sa.sa_family);
af->to_sk_daddr(&to, sk);
timeo = sock_sndtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK); timeo = sock_sndtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK);
err = sctp_wait_for_connect(asoc, &timeo); err = sctp_wait_for_connect(asoc, &timeo);
......
...@@ -237,9 +237,15 @@ void sctp_transport_route(struct sctp_transport *transport, ...@@ -237,9 +237,15 @@ void sctp_transport_route(struct sctp_transport *transport,
af->get_saddr(asoc, dst, daddr, &transport->saddr); af->get_saddr(asoc, dst, daddr, &transport->saddr);
transport->dst = dst; transport->dst = dst;
if (dst) if (dst) {
transport->pmtu = dst_pmtu(dst); transport->pmtu = dst_pmtu(dst);
else
/* Initialize sk->rcv_saddr, if the transport is the
* association's active path for getsockname().
*/
if (asoc && (transport == asoc->peer.active_path))
af->to_sk_saddr(&transport->saddr, asoc->base.sk);
} else
transport->pmtu = SCTP_DEFAULT_MAXSEGMENT; transport->pmtu = SCTP_DEFAULT_MAXSEGMENT;
} }
......
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