Commit 845ddb44 authored by Jon Grimm's avatar Jon Grimm Committed by Sridhar Samudrala

[SCTP] Support v4-mapped-v6 addresses (Ardelle Fan)

parent 33585c7e
...@@ -611,4 +611,23 @@ int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state) ...@@ -611,4 +611,23 @@ int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
return sk->sk_state == state; return sk->sk_state == state;
} }
/* Map v4-mapped v6 address back to v4 address */
static inline void sctp_v6_map_v4(union sctp_addr *addr)
{
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = addr->v6.sin6_port;
addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3];
}
/* Map v4 address to v4-mapped v6 address */
static inline void sctp_v4_map_v6(union sctp_addr *addr)
{
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = addr->v4.sin_port;
addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
addr->v6.sin6_addr.s6_addr32[0] = 0;
addr->v6.sin6_addr.s6_addr32[1] = 0;
addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
}
#endif /* __net_sctp_h__ */ #endif /* __net_sctp_h__ */
...@@ -260,11 +260,13 @@ struct sctp_af { ...@@ -260,11 +260,13 @@ struct sctp_af {
struct sock *sk); struct sock *sk);
void (*to_sk_daddr) (union sctp_addr *, 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 *,
struct sctp_opt *);
sctp_scope_t (*scope) (union sctp_addr *); sctp_scope_t (*scope) (union sctp_addr *);
void (*inaddr_any) (union sctp_addr *, unsigned short); void (*inaddr_any) (union sctp_addr *, unsigned short);
int (*is_any) (const union sctp_addr *); int (*is_any) (const union sctp_addr *);
int (*available) (const union sctp_addr *); int (*available) (union sctp_addr *,
struct sctp_opt *);
int (*skb_iif) (const struct sk_buff *sk); int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk); int (*is_ce) (const struct sk_buff *sk);
void (*seq_dump_addr)(struct seq_file *seq, void (*seq_dump_addr)(struct seq_file *seq,
...@@ -282,7 +284,7 @@ int sctp_register_af(struct sctp_af *); ...@@ -282,7 +284,7 @@ int sctp_register_af(struct sctp_af *);
struct sctp_pf { struct sctp_pf {
void (*event_msgname)(struct sctp_ulpevent *, char *, int *); void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
void (*skb_msgname) (struct sk_buff *, char *, int *); void (*skb_msgname) (struct sk_buff *, char *, int *);
int (*af_supported) (sa_family_t); int (*af_supported) (sa_family_t, struct sctp_opt *);
int (*cmp_addr) (const union sctp_addr *, int (*cmp_addr) (const union sctp_addr *,
const union sctp_addr *, const union sctp_addr *,
struct sctp_opt *); struct sctp_opt *);
...@@ -291,6 +293,7 @@ struct sctp_pf { ...@@ -291,6 +293,7 @@ struct sctp_pf {
int (*supported_addrs)(const struct sctp_opt *, __u16 *); int (*supported_addrs)(const struct sctp_opt *, __u16 *);
struct sock *(*create_accept_sk) (struct sock *sk, struct sock *(*create_accept_sk) (struct sock *sk,
struct sctp_association *asoc); struct sctp_association *asoc);
void (*addr_v4map) (struct sctp_opt *, union sctp_addr *);
struct sctp_af *af; struct sctp_af *af;
}; };
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2002 Intel Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -41,6 +42,7 @@ ...@@ -41,6 +42,7 @@
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* Ryan Layer <rmlayer@us.ibm.com> * Ryan Layer <rmlayer@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
......
...@@ -150,7 +150,7 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -150,7 +150,7 @@ int sctp_rcv(struct sk_buff *skb)
* IP broadcast addresses cannot be used in an SCTP transport * IP broadcast addresses cannot be used in an SCTP transport
* address." * address."
*/ */
if (!af->addr_valid(&src) || !af->addr_valid(&dest)) if (!af->addr_valid(&src, NULL) || !af->addr_valid(&dest, NULL))
goto discard_it; goto discard_it;
asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
* Copyright (c) 2002-2003 International Business Machines, Corp. * Copyright (c) 2002-2003 International Business Machines, Corp.
* Copyright (c) 2002-2003 Intel Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -15,7 +16,7 @@ ...@@ -15,7 +16,7 @@
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
...@@ -32,14 +33,15 @@ ...@@ -32,14 +33,15 @@
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* Le Yanqun <yanqun.le@nokia.com> * Le Yanqun <yanqun.le@nokia.com>
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
* *
* Based on: * Based on:
* linux/net/ipv6/tcp_ipv6.c * linux/net/ipv6/tcp_ipv6.c
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
...@@ -172,7 +174,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, ...@@ -172,7 +174,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
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);
...@@ -370,13 +372,28 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) ...@@ -370,13 +372,28 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
/* Initialize sk->sk_rcv_saddr from sctp_addr. */ /* Initialize sk->sk_rcv_saddr from sctp_addr. */
static void sctp_v6_to_sk_saddr(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; if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) {
inet6_sk(sk)->rcv_saddr.s6_addr32[0] = 0;
inet6_sk(sk)->rcv_saddr.s6_addr32[1] = 0;
inet6_sk(sk)->rcv_saddr.s6_addr32[2] = htonl(0x0000ffff);
inet6_sk(sk)->rcv_saddr.s6_addr32[3] =
addr->v4.sin_addr.s_addr;
} else {
inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
}
} }
/* Initialize sk->sk_daddr from sctp_addr. */ /* Initialize sk->sk_daddr from sctp_addr. */
static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
{ {
inet6_sk(sk)->daddr = addr->v6.sin6_addr; if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) {
inet6_sk(sk)->daddr.s6_addr32[0] = 0;
inet6_sk(sk)->daddr.s6_addr32[1] = 0;
inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff);
inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
} else {
inet6_sk(sk)->daddr = addr->v6.sin6_addr;
}
} }
/* Initialize a sctp_addr from a dst_entry. */ /* Initialize a sctp_addr from a dst_entry. */
...@@ -390,13 +407,30 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, ...@@ -390,13 +407,30 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst,
} }
/* Compare addresses exactly. /* Compare addresses exactly.
* FIXME: v4-mapped-v6. * v4-mapped-v6 is also in consideration.
*/ */
static int sctp_v6_cmp_addr(const union sctp_addr *addr1, static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
const union sctp_addr *addr2) const union sctp_addr *addr2)
{ {
if (addr1->sa.sa_family != addr2->sa.sa_family) if (addr1->sa.sa_family != addr2->sa.sa_family) {
if (addr1->sa.sa_family == AF_INET &&
addr2->sa.sa_family == AF_INET6 &&
IPV6_ADDR_MAPPED == ipv6_addr_type(&addr2->v6.sin6_addr)) {
if (addr2->v6.sin6_port == addr1->v4.sin_port &&
addr2->v6.sin6_addr.s6_addr32[3] ==
addr1->v4.sin_addr.s_addr)
return 1;
}
if (addr2->sa.sa_family == AF_INET &&
addr1->sa.sa_family == AF_INET6 &&
IPV6_ADDR_MAPPED == ipv6_addr_type(&addr1->v6.sin6_addr)) {
if (addr1->v6.sin6_port == addr2->v4.sin_port &&
addr1->v6.sin6_addr.s6_addr32[3] ==
addr2->v4.sin_addr.s_addr)
return 1;
}
return 0; return 0;
}
if (ipv6_addr_cmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr)) if (ipv6_addr_cmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr))
return 0; return 0;
/* If this is a linklocal address, compare the scope_id. */ /* If this is a linklocal address, compare the scope_id. */
...@@ -427,7 +461,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr) ...@@ -427,7 +461,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr)
} }
/* Should this be available for binding? */ /* Should this be available for binding? */
static int sctp_v6_available(const union sctp_addr *addr) static int sctp_v6_available(union sctp_addr *addr, struct sctp_opt *sp)
{ {
int type; int type;
struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr; struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr;
...@@ -435,6 +469,12 @@ static int sctp_v6_available(const union sctp_addr *addr) ...@@ -435,6 +469,12 @@ static int sctp_v6_available(const union sctp_addr *addr)
type = ipv6_addr_type(in6); type = ipv6_addr_type(in6);
if (IPV6_ADDR_ANY == type) if (IPV6_ADDR_ANY == type)
return 1; return 1;
if (type == IPV6_ADDR_MAPPED) {
if (sp && !sp->v4mapped)
return 0;
sctp_v6_map_v4(addr);
return sctp_get_af_specific(AF_INET)->available(addr, sp);
}
if (!(type & IPV6_ADDR_UNICAST)) if (!(type & IPV6_ADDR_UNICAST))
return 0; return 0;
...@@ -448,11 +488,20 @@ static int sctp_v6_available(const union sctp_addr *addr) ...@@ -448,11 +488,20 @@ static int sctp_v6_available(const union sctp_addr *addr)
* Return 0 - If the address is a non-unicast or an illegal address. * Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast. * Return 1 - If the address is a unicast.
*/ */
static int sctp_v6_addr_valid(union sctp_addr *addr) static int sctp_v6_addr_valid(union sctp_addr *addr, struct sctp_opt *sp)
{ {
int ret = ipv6_addr_type(&addr->v6.sin6_addr); int ret = ipv6_addr_type(&addr->v6.sin6_addr);
/* FIXME: v4-mapped-v6 address support. */ /* Support v4-mapped-v6 address. */
if (ret == IPV6_ADDR_MAPPED) {
/* Note: This routine is used in input, so v4-mapped-v6
* are disallowed here when there is no sctp_opt.
*/
if (!sp || !sp->v4mapped)
return 0;
sctp_v6_map_v4(addr);
return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp);
}
/* Is this a non-unicast address */ /* Is this a non-unicast address */
if (!(ret & IPV6_ADDR_UNICAST)) if (!(ret & IPV6_ADDR_UNICAST))
...@@ -536,7 +585,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -536,7 +585,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newnp->saddr = np->saddr; newnp->saddr = np->saddr;
newnp->rcv_saddr = np->rcv_saddr; newnp->rcv_saddr = np->rcv_saddr;
newinet->dport = htons(asoc->peer.port); newinet->dport = htons(asoc->peer.port);
newnp->daddr = asoc->peer.primary_addr.v6.sin6_addr; sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk);
/* Init the ipv4 part of the socket since we can have sockets /* Init the ipv4 part of the socket since we can have sockets
* using v6 API for ipv4. * using v6 API for ipv4.
...@@ -566,6 +615,13 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -566,6 +615,13 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
return newsk; return newsk;
} }
/* Map v4 address to mapped v6 address */
static void sctp_v6_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr)
{
if (sp->v4mapped && AF_INET == addr->sa.sa_family)
sctp_v4_map_v6(addr);
}
/* Where did this skb come from? */ /* Where did this skb come from? */
static int sctp_v6_skb_iif(const struct sk_buff *skb) static int sctp_v6_skb_iif(const struct sk_buff *skb)
{ {
...@@ -617,10 +673,11 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, ...@@ -617,10 +673,11 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
*/ */
/* Map ipv4 address into v4-mapped-on-v6 address. */ /* Map ipv4 address into v4-mapped-on-v6 address. */
if (AF_INET == addr->sa.sa_family) { if (sctp_sk(event->asoc->base.sk)->v4mapped &&
/* FIXME: Easy, but there was no way to test this AF_INET == addr->sa.sa_family) {
* yet. sctp_v4_map_v6((union sctp_addr *)sin6);
*/ sin6->sin6_addr.s6_addr32[3] =
addr->v4.sin_addr.s_addr;
return; return;
} }
...@@ -644,16 +701,15 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, ...@@ -644,16 +701,15 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
sh = (struct sctphdr *)skb->h.raw; sh = (struct sctphdr *)skb->h.raw;
sin6->sin6_port = sh->source; sin6->sin6_port = sh->source;
/* FIXME: Map ipv4 address into v4-mapped-on-v6 address. */ /* Map ipv4 address into v4-mapped-on-v6 address. */
if (__constant_htons(ETH_P_IP) == skb->protocol) { if (sctp_sk(skb->sk)->v4mapped &&
/* FIXME: The latest I-D added options for two skb->nh.iph->version == 4) {
* behaviors. sctp_v4_map_v6((union sctp_addr *)sin6);
*/ sin6->sin6_addr.s6_addr32[3] = skb->nh.iph->saddr;
return; return;
} }
/* Otherwise, just copy the v6 address. */ /* Otherwise, just copy the v6 address. */
ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr); ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
struct sctp_ulpevent *ev = sctp_skb2event(skb); struct sctp_ulpevent *ev = sctp_skb2event(skb);
...@@ -663,16 +719,15 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, ...@@ -663,16 +719,15 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
} }
/* Do we support this AF? */ /* Do we support this AF? */
static int sctp_inet6_af_supported(sa_family_t family) static int sctp_inet6_af_supported(sa_family_t family, struct sctp_opt *sp)
{ {
/* FIXME: v4-mapped-v6 addresses. The I-D is still waffling
* on what to do with sockaddr formats for PF_INET6 sockets.
* For now assume we'll support both.
*/
switch (family) { switch (family) {
case AF_INET6: case AF_INET6:
case AF_INET:
return 1; return 1;
/* v4-mapped-v6 addresses */
case AF_INET:
if (sp->v4mapped)
return 1;
default: default:
return 0; return 0;
} }
...@@ -730,7 +785,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) ...@@ -730,7 +785,7 @@ static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
} }
af = opt->pf->af; af = opt->pf->af;
} }
return af->available(addr); return af->available(addr, opt);
} }
/* Verify that the provided sockaddr looks bindable. Common verification, /* Verify that the provided sockaddr looks bindable. Common verification,
...@@ -863,6 +918,7 @@ static struct sctp_pf sctp_pf_inet6_specific = { ...@@ -863,6 +918,7 @@ static struct sctp_pf sctp_pf_inet6_specific = {
.send_verify = sctp_inet6_send_verify, .send_verify = sctp_inet6_send_verify,
.supported_addrs = sctp_inet6_supported_addrs, .supported_addrs = sctp_inet6_supported_addrs,
.create_accept_sk = sctp_v6_create_accept_sk, .create_accept_sk = sctp_v6_create_accept_sk,
.addr_v4map = sctp_v6_addr_v4map,
.af = &sctp_ipv6_specific, .af = &sctp_ipv6_specific,
}; };
......
...@@ -340,7 +340,7 @@ static int sctp_v4_is_any(const union sctp_addr *addr) ...@@ -340,7 +340,7 @@ static int sctp_v4_is_any(const union sctp_addr *addr)
* Return 0 - If the address is a non-unicast or an illegal address. * Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast. * Return 1 - If the address is a unicast.
*/ */
static int sctp_v4_addr_valid(union sctp_addr *addr) static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_opt *sp)
{ {
/* Is this a non-unicast address or a unusable SCTP address? */ /* Is this a non-unicast address or a unusable SCTP address? */
if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
...@@ -350,7 +350,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr) ...@@ -350,7 +350,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr)
} }
/* Should this be available for binding? */ /* Should this be available for binding? */
static int sctp_v4_available(const union sctp_addr *addr) static int sctp_v4_available(union sctp_addr *addr, struct sctp_opt *sp)
{ {
int ret = inet_addr_type(addr->v4.sin_addr.s_addr); int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
...@@ -580,6 +580,12 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, ...@@ -580,6 +580,12 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
return newsk; return newsk;
} }
/* Map address, empty for v4 family */
static void sctp_v4_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr)
{
/* Empty */
}
/* Dump the v4 addr to the seq file. */ /* Dump the v4 addr to the seq file. */
static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
{ {
...@@ -709,7 +715,7 @@ static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len) ...@@ -709,7 +715,7 @@ static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len)
} }
/* Do we support this AF? */ /* Do we support this AF? */
static int sctp_inet_af_supported(sa_family_t family) static int sctp_inet_af_supported(sa_family_t family, struct sctp_opt *sp)
{ {
/* PF_INET only supports AF_INET addresses. */ /* PF_INET only supports AF_INET addresses. */
return (AF_INET == family); return (AF_INET == family);
...@@ -737,7 +743,7 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1, ...@@ -737,7 +743,7 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
*/ */
static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
{ {
return sctp_v4_available(addr); return sctp_v4_available(addr, opt);
} }
/* Verify that sockaddr looks sendable. Common verification has already /* Verify that sockaddr looks sendable. Common verification has already
...@@ -783,6 +789,7 @@ static struct sctp_pf sctp_pf_inet = { ...@@ -783,6 +789,7 @@ static struct sctp_pf sctp_pf_inet = {
.send_verify = sctp_inet_send_verify, .send_verify = sctp_inet_send_verify,
.supported_addrs = sctp_inet_supported_addrs, .supported_addrs = sctp_inet_supported_addrs,
.create_accept_sk = sctp_v4_create_accept_sk, .create_accept_sk = sctp_v4_create_accept_sk,
.addr_v4map = sctp_v4_addr_v4map,
.af = &sctp_ipv4_specific, .af = &sctp_ipv4_specific,
}; };
......
...@@ -156,6 +156,9 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk, ...@@ -156,6 +156,9 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
if (id_asoc && (id_asoc != addr_asoc)) if (id_asoc && (id_asoc != addr_asoc))
return NULL; return NULL;
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
(union sctp_addr *)addr);
return transport; return transport;
} }
...@@ -206,7 +209,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt, ...@@ -206,7 +209,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt,
return NULL; return NULL;
/* Does this PF support this AF? */ /* Does this PF support this AF? */
if (!opt->pf->af_supported(addr->sa.sa_family)) if (!opt->pf->af_supported(addr->sa.sa_family, opt))
return NULL; return NULL;
/* If we get this far, af is valid. */ /* If we get this far, af is valid. */
...@@ -1362,7 +1365,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, ...@@ -1362,7 +1365,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
/* Free the event which includes releasing the reference to /* Free the event which includes releasing the reference to
* the owner of the skb, freeing the skb and updating the * the owner of the skb, freeing the skb and updating the
* rwnd. * rwnd.
*/ */
sctp_ulpevent_free(event); sctp_ulpevent_free(event);
} }
out: out:
...@@ -1747,14 +1750,18 @@ static int sctp_setsockopt_associnfo(struct sock *sk, char *optval, int optlen) ...@@ -1747,14 +1750,18 @@ static int sctp_setsockopt_associnfo(struct sock *sk, char *optval, int optlen)
static int sctp_setsockopt_mappedv4(struct sock *sk, char *optval, int optlen) static int sctp_setsockopt_mappedv4(struct sock *sk, char *optval, int optlen)
{ {
int val; int val;
struct sctp_opt *sp = sctp_sk(sk);
if (optlen < sizeof(int)) if (optlen < sizeof(int))
return -EINVAL; return -EINVAL;
if (get_user(val, (int *)optval)) if (get_user(val, (int *)optval))
return -EFAULT; return -EFAULT;
/* FIXME: Put real support here. */ if (val)
sp->v4mapped = 1;
else
sp->v4mapped = 0;
return -ENOPROTOOPT; return 0;
} }
/* /*
...@@ -2305,6 +2312,9 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval, ...@@ -2305,6 +2312,9 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, char *optval,
status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc); status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
memcpy(&status.sstat_primary.spinfo_address, memcpy(&status.sstat_primary.spinfo_address,
&(transport->ipaddr), sizeof(union sctp_addr)); &(transport->ipaddr), sizeof(union sctp_addr));
/* Map ipv4 address into v4-mapped-on-v6 address. */
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
(union sctp_addr *)&status.sstat_primary.spinfo_address);
status.sstat_primary.spinfo_state = transport->active; status.sstat_primary.spinfo_state = transport->active;
status.sstat_primary.spinfo_cwnd = transport->cwnd; status.sstat_primary.spinfo_cwnd = transport->cwnd;
status.sstat_primary.spinfo_srtt = transport->srtt; status.sstat_primary.spinfo_srtt = transport->srtt;
...@@ -2642,6 +2652,8 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, ...@@ -2642,6 +2652,8 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
struct sctp_getaddrs getaddrs; struct sctp_getaddrs getaddrs;
struct sctp_transport *from; struct sctp_transport *from;
struct sockaddr_storage *to; struct sockaddr_storage *to;
union sctp_addr temp;
struct sctp_opt *sp = sctp_sk(sk);
if (len != sizeof(struct sctp_getaddrs)) if (len != sizeof(struct sctp_getaddrs))
return -EINVAL; return -EINVAL;
...@@ -2660,7 +2672,9 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, ...@@ -2660,7 +2672,9 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
to = getaddrs.addrs; to = getaddrs.addrs;
list_for_each(pos, &asoc->peer.transport_addr_list) { list_for_each(pos, &asoc->peer.transport_addr_list) {
from = list_entry(pos, struct sctp_transport, transports); from = list_entry(pos, struct sctp_transport, transports);
if (copy_to_user(to, &from->ipaddr, sizeof(from->ipaddr))) memcpy(&temp, &from->ipaddr, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
if (copy_to_user(to, &temp, sizeof(temp)))
return -EFAULT; return -EFAULT;
to ++; to ++;
cnt ++; cnt ++;
...@@ -2722,6 +2736,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, ...@@ -2722,6 +2736,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
struct sctp_getaddrs getaddrs; struct sctp_getaddrs getaddrs;
struct sctp_sockaddr_entry *from; struct sctp_sockaddr_entry *from;
struct sockaddr_storage *to; struct sockaddr_storage *to;
union sctp_addr temp;
struct sctp_opt *sp = sctp_sk(sk);
if (len != sizeof(struct sctp_getaddrs)) if (len != sizeof(struct sctp_getaddrs))
return -EINVAL; return -EINVAL;
...@@ -2750,7 +2766,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, ...@@ -2750,7 +2766,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
from = list_entry(pos, from = list_entry(pos,
struct sctp_sockaddr_entry, struct sctp_sockaddr_entry,
list); list);
if (copy_to_user(to, &from->a, sizeof(from->a))) memcpy(&temp, &from->a, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
if (copy_to_user(to, &temp, sizeof(temp)))
return -EFAULT; return -EFAULT;
to ++; to ++;
cnt ++; cnt ++;
...@@ -2774,6 +2792,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, ...@@ -2774,6 +2792,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
{ {
struct sctp_prim prim; struct sctp_prim prim;
struct sctp_association *asoc; struct sctp_association *asoc;
struct sctp_opt *sp = sctp_sk(sk);
if (len != sizeof(struct sctp_prim)) if (len != sizeof(struct sctp_prim))
return -EINVAL; return -EINVAL;
...@@ -2791,6 +2810,9 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, ...@@ -2791,6 +2810,9 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr, memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr,
sizeof(union sctp_addr)); sizeof(union sctp_addr));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
(union sctp_addr *)&prim.ssp_addr);
if (copy_to_user(optval, &prim, sizeof(struct sctp_prim))) if (copy_to_user(optval, &prim, sizeof(struct sctp_prim)))
return -EFAULT; return -EFAULT;
...@@ -2805,6 +2827,8 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, ...@@ -2805,6 +2827,8 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
* specify a default set of parameters that would normally be supplied * specify a default set of parameters that would normally be supplied
* through the inclusion of ancillary data. This socket option allows * through the inclusion of ancillary data. This socket option allows
* such an application to set the default sctp_sndrcvinfo structure. * such an application to set the default sctp_sndrcvinfo structure.
* The application that wishes to use this socket option simply passes * The application that wishes to use this socket option simply passes
* in to this call the sctp_sndrcvinfo structure defined in Section * in to this call the sctp_sndrcvinfo structure defined in Section
* 5.2.2) The input parameters accepted by this call include * 5.2.2) The input parameters accepted by this call include
...@@ -3012,12 +3036,13 @@ static int sctp_getsockopt_mappedv4(struct sock *sk, int len, ...@@ -3012,12 +3036,13 @@ static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
char *optval, int *optlen) char *optval, int *optlen)
{ {
int val; int val;
struct sctp_opt *sp = sctp_sk(sk);
if (len < sizeof(int)) if (len < sizeof(int))
return -EINVAL; return -EINVAL;
len = sizeof(int); len = sizeof(int);
/* FIXME: Until we have support, return disabled. */ val = sp->v4mapped;
val = 0;
if (put_user(len, optlen)) if (put_user(len, optlen))
return -EFAULT; return -EFAULT;
if (copy_to_user(optval, &val, len)) if (copy_to_user(optval, &val, len))
...@@ -3863,7 +3888,7 @@ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, ...@@ -3863,7 +3888,7 @@ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
return -EINVAL; return -EINVAL;
/* Is this a valid SCTP address? */ /* Is this a valid SCTP address? */
if (!af->addr_valid(addr)) if (!af->addr_valid(addr, sctp_sk(sk)))
return -EINVAL; return -EINVAL;
if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr))) if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
* Written or modified by: * Written or modified by:
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Ardelle Fan <ardelle.fan@intel.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
...@@ -286,6 +287,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( ...@@ -286,6 +287,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
*/ */
memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage)); memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage));
/* Map ipv4 address into v4-mapped-on-v6 address. */
sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map(
sctp_sk(asoc->base.sk),
(union sctp_addr *)&spc->spc_aaddr);
return event; return event;
fail: fail:
......
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