Commit 54eca890 authored by Sridhar Samudrala's avatar Sridhar Samudrala

[SCTP] Convert sctp_param2sockaddr() and sockaddr2sctp_addr() to

address family specific routines af->from_addr_parm() and
af->to_addr_param() respectively. 
parent f1079649
...@@ -533,6 +533,19 @@ static inline int ipver2af(__u8 ipver) ...@@ -533,6 +533,19 @@ static inline int ipver2af(__u8 ipver)
}; };
} }
/* Convert from an address parameter type to an address family. */
static inline int param_type2af(__u16 type)
{
switch (type) {
case SCTP_PARAM_IPV4_ADDRESS:
return AF_INET;
case SCTP_PARAM_IPV6_ADDRESS:
return AF_INET6;
default:
return 0;
};
}
/* Perform some sanity checks. */ /* Perform some sanity checks. */
static inline int sctp_sanity_check(void) static inline int sctp_sanity_check(void)
{ {
......
...@@ -334,12 +334,6 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, ...@@ -334,12 +334,6 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
__u32 sctp_generate_tag(const struct sctp_endpoint *); __u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *); __u32 sctp_generate_tsn(const struct sctp_endpoint *);
/* 4th level prototypes */
void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *,
__u16 port, int iif);
int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *);
int sockaddr2sctp_addr(const union sctp_addr *, union sctp_addr_param *);
/* Extern declarations for major data structures. */ /* Extern declarations for major data structures. */
const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t); const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
extern const sctp_sm_table_entry_t extern const sctp_sm_table_entry_t
......
...@@ -218,86 +218,6 @@ extern struct sctp_globals { ...@@ -218,86 +218,6 @@ extern struct sctp_globals {
#define sctp_local_addr_list (sctp_globals.local_addr_list) #define sctp_local_addr_list (sctp_globals.local_addr_list)
#define sctp_local_addr_lock (sctp_globals.local_addr_lock) #define sctp_local_addr_lock (sctp_globals.local_addr_lock)
/*
* Pointers to address related SCTP functions.
* (i.e. things that depend on the address family.)
*/
struct sctp_af {
int (*sctp_xmit) (struct sk_buff *skb,
struct sctp_transport *,
int ipfragok);
int (*setsockopt) (struct sock *sk,
int level,
int optname,
char *optval,
int optlen);
int (*getsockopt) (struct sock *sk,
int level,
int optname,
char *optval,
int *optlen);
struct dst_entry *(*get_dst) (struct sctp_association *asoc,
union sctp_addr *daddr,
union sctp_addr *saddr);
void (*get_saddr) (struct sctp_association *asoc,
struct dst_entry *dst,
union sctp_addr *daddr,
union sctp_addr *saddr);
void (*copy_addrlist) (struct list_head *,
struct net_device *);
void (*dst_saddr) (union sctp_addr *saddr,
struct dst_entry *dst,
unsigned short port);
int (*cmp_addr) (const union sctp_addr *addr1,
const union sctp_addr *addr2);
void (*addr_copy) (union sctp_addr *dst,
union sctp_addr *src);
void (*from_skb) (union sctp_addr *,
struct sk_buff *skb,
int saddr);
void (*from_sk) (union sctp_addr *,
struct sock *sk);
void (*to_sk_saddr) (union sctp_addr *,
struct sock *sk);
void (*to_sk_daddr) (union sctp_addr *,
struct sock *sk);
int (*addr_valid) (union sctp_addr *,
struct sctp_opt *);
sctp_scope_t (*scope) (union sctp_addr *);
void (*inaddr_any) (union sctp_addr *, unsigned short);
int (*is_any) (const union sctp_addr *);
int (*available) (union sctp_addr *,
struct sctp_opt *);
int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk);
void (*seq_dump_addr)(struct seq_file *seq,
union sctp_addr *addr);
__u16 net_header_len;
int sockaddr_len;
sa_family_t sa_family;
struct list_head list;
};
struct sctp_af *sctp_get_af_specific(sa_family_t);
int sctp_register_af(struct sctp_af *);
/* Protocol family functions. */
struct sctp_pf {
void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
void (*skb_msgname) (struct sk_buff *, char *, int *);
int (*af_supported) (sa_family_t, struct sctp_opt *);
int (*cmp_addr) (const union sctp_addr *,
const union sctp_addr *,
struct sctp_opt *);
int (*bind_verify) (struct sctp_opt *, union sctp_addr *);
int (*send_verify) (struct sctp_opt *, union sctp_addr *);
int (*supported_addrs)(const struct sctp_opt *, __u16 *);
struct sock *(*create_accept_sk) (struct sock *sk,
struct sctp_association *asoc);
void (*addr_v4map) (struct sctp_opt *, union sctp_addr *);
struct sctp_af *af;
};
/* SCTP Socket type: UDP or TCP style. */ /* SCTP Socket type: UDP or TCP style. */
typedef enum { typedef enum {
SCTP_SOCKET_UDP = 0, SCTP_SOCKET_UDP = 0,
...@@ -489,6 +409,92 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id) ...@@ -489,6 +409,92 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id)
return stream->ssn[id]++; return stream->ssn[id]++;
} }
/*
* Pointers to address related SCTP functions.
* (i.e. things that depend on the address family.)
*/
struct sctp_af {
int (*sctp_xmit) (struct sk_buff *skb,
struct sctp_transport *,
int ipfragok);
int (*setsockopt) (struct sock *sk,
int level,
int optname,
char *optval,
int optlen);
int (*getsockopt) (struct sock *sk,
int level,
int optname,
char *optval,
int *optlen);
struct dst_entry *(*get_dst) (struct sctp_association *asoc,
union sctp_addr *daddr,
union sctp_addr *saddr);
void (*get_saddr) (struct sctp_association *asoc,
struct dst_entry *dst,
union sctp_addr *daddr,
union sctp_addr *saddr);
void (*copy_addrlist) (struct list_head *,
struct net_device *);
void (*dst_saddr) (union sctp_addr *saddr,
struct dst_entry *dst,
unsigned short port);
int (*cmp_addr) (const union sctp_addr *addr1,
const union sctp_addr *addr2);
void (*addr_copy) (union sctp_addr *dst,
union sctp_addr *src);
void (*from_skb) (union sctp_addr *,
struct sk_buff *skb,
int saddr);
void (*from_sk) (union sctp_addr *,
struct sock *sk);
void (*to_sk_saddr) (union sctp_addr *,
struct sock *sk);
void (*to_sk_daddr) (union sctp_addr *,
struct sock *sk);
void (*from_addr_param) (union sctp_addr *,
union sctp_addr_param *,
__u16 port, int iif);
int (*to_addr_param) (const union sctp_addr *,
union sctp_addr_param *);
int (*addr_valid) (union sctp_addr *,
struct sctp_opt *);
sctp_scope_t (*scope) (union sctp_addr *);
void (*inaddr_any) (union sctp_addr *, unsigned short);
int (*is_any) (const union sctp_addr *);
int (*available) (union sctp_addr *,
struct sctp_opt *);
int (*skb_iif) (const struct sk_buff *sk);
int (*is_ce) (const struct sk_buff *sk);
void (*seq_dump_addr)(struct seq_file *seq,
union sctp_addr *addr);
__u16 net_header_len;
int sockaddr_len;
sa_family_t sa_family;
struct list_head list;
};
struct sctp_af *sctp_get_af_specific(sa_family_t);
int sctp_register_af(struct sctp_af *);
/* Protocol family functions. */
struct sctp_pf {
void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
void (*skb_msgname) (struct sk_buff *, char *, int *);
int (*af_supported) (sa_family_t, struct sctp_opt *);
int (*cmp_addr) (const union sctp_addr *,
const union sctp_addr *,
struct sctp_opt *);
int (*bind_verify) (struct sctp_opt *, union sctp_addr *);
int (*send_verify) (struct sctp_opt *, union sctp_addr *);
int (*supported_addrs)(const struct sctp_opt *, __u16 *);
struct sock *(*create_accept_sk) (struct sock *sk,
struct sctp_association *asoc);
void (*addr_v4map) (struct sctp_opt *, union sctp_addr *);
struct sctp_af *af;
};
/* Structure to track chunk fragments that have been acked, but peer /* Structure to track chunk fragments that have been acked, but peer
* fragments of the same message have not. * fragments of the same message have not.
*/ */
......
...@@ -225,6 +225,7 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, ...@@ -225,6 +225,7 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
struct list_head *pos; struct list_head *pos;
addrparms_len = 0; addrparms_len = 0;
len = 0; len = 0;
struct sctp_af *af;
/* Allocate enough memory at once. */ /* Allocate enough memory at once. */
list_for_each(pos, &bp->address_list) { list_for_each(pos, &bp->address_list) {
...@@ -247,7 +248,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, ...@@ -247,7 +248,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
list_for_each(pos, &bp->address_list) { list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list); addr = list_entry(pos, struct sctp_sockaddr_entry, list);
len = sockaddr2sctp_addr(&addr->a, &rawaddr); af = sctp_get_af_specific(addr->a.v4.sin_family);
len = af->to_addr_param(&addr->a, &rawaddr);
memcpy(addrparms.v, &rawaddr, len); memcpy(addrparms.v, &rawaddr, len);
addrparms.v += len; addrparms.v += len;
addrparms_len += len; addrparms_len += len;
...@@ -270,34 +272,31 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, ...@@ -270,34 +272,31 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
union sctp_addr addr; union sctp_addr addr;
int retval = 0; int retval = 0;
int len; int len;
struct sctp_af *af;
/* Convert the raw address to standard address format */ /* Convert the raw address to standard address format */
while (addrs_len) { while (addrs_len) {
param = (struct sctp_paramhdr *)raw_addr_list; param = (struct sctp_paramhdr *)raw_addr_list;
rawaddr = (union sctp_addr_param *)raw_addr_list; rawaddr = (union sctp_addr_param *)raw_addr_list;
switch (param->type) { af = sctp_get_af_specific(param_type2af(param->type));
case SCTP_PARAM_IPV4_ADDRESS: if (unlikely(!af)) {
case SCTP_PARAM_IPV6_ADDRESS: retval = -EINVAL;
sctp_param2sockaddr(&addr, rawaddr, port, 0); sctp_bind_addr_clean(bp);
break;
}
af->from_addr_param(&addr, rawaddr, port, 0);
retval = sctp_add_bind_addr(bp, &addr, gfp); retval = sctp_add_bind_addr(bp, &addr, gfp);
if (retval) { if (retval) {
/* Can't finish building the list, clean up. */ /* Can't finish building the list, clean up. */
sctp_bind_addr_clean(bp); sctp_bind_addr_clean(bp);
break;; break;;
} }
len = ntohs(param->length); len = ntohs(param->length);
addrs_len -= len; addrs_len -= len;
raw_addr_list += len; raw_addr_list += len;
break;
default:
/* Corrupted raw addr list! */
retval = -EINVAL;
sctp_bind_addr_clean(bp);
break;
}
if (retval)
break;
} }
return retval; return retval;
......
...@@ -768,6 +768,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, ...@@ -768,6 +768,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
union sctp_params params; union sctp_params params;
sctp_init_chunk_t *init; sctp_init_chunk_t *init;
struct sctp_transport *transport; struct sctp_transport *transport;
struct sctp_af *af;
ch = (sctp_chunkhdr_t *) skb->data; ch = (sctp_chunkhdr_t *) skb->data;
...@@ -802,11 +803,12 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, ...@@ -802,11 +803,12 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
sctp_walk_params(params, init, init_hdr.params) { sctp_walk_params(params, init, init_hdr.params) {
/* Note: Ignoring hostname addresses. */ /* Note: Ignoring hostname addresses. */
if ((SCTP_PARAM_IPV4_ADDRESS != params.p->type) && af = sctp_get_af_specific(param_type2af(params.p->type));
(SCTP_PARAM_IPV6_ADDRESS != params.p->type)) if (!af)
continue; continue;
sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source), 0); af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0);
asoc = __sctp_lookup_association(laddr, paddr, &transport); asoc = __sctp_lookup_association(laddr, paddr, &transport);
if (asoc) if (asoc)
return asoc; return asoc;
......
...@@ -399,6 +399,33 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) ...@@ -399,6 +399,33 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
} }
} }
/* Initialize a sctp_addr from an address parameter. */
static void sctp_v6_from_addr_param(union sctp_addr *addr,
union sctp_addr_param *param,
__u16 port, int iif)
{
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = port;
addr->v6.sin6_flowinfo = 0; /* BUG */
ipv6_addr_copy(&addr->v6.sin6_addr, &param->v6.addr);
addr->v6.sin6_scope_id = iif;
}
/* Initialize an address parameter from a sctp_addr and return the length
* of the address parameter.
*/
static int sctp_v6_to_addr_param(const union sctp_addr *addr,
union sctp_addr_param *param)
{
int length = sizeof(sctp_ipv6addr_param_t);
param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
param->v6.param_hdr.length = ntohs(length);
ipv6_addr_copy(&param->v6.addr, &addr->v6.sin6_addr);
return length;
}
/* 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)
...@@ -903,6 +930,8 @@ static struct sctp_af sctp_ipv6_specific = { ...@@ -903,6 +930,8 @@ static struct sctp_af sctp_ipv6_specific = {
.from_sk = sctp_v6_from_sk, .from_sk = sctp_v6_from_sk,
.to_sk_saddr = sctp_v6_to_sk_saddr, .to_sk_saddr = sctp_v6_to_sk_saddr,
.to_sk_daddr = sctp_v6_to_sk_daddr, .to_sk_daddr = sctp_v6_to_sk_daddr,
.from_addr_param = sctp_v6_from_addr_param,
.to_addr_param = sctp_v6_to_addr_param,
.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,
......
...@@ -295,6 +295,31 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) ...@@ -295,6 +295,31 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr; inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr;
} }
/* Initialize a sctp_addr from an address parameter. */
static void sctp_v4_from_addr_param(union sctp_addr *addr,
union sctp_addr_param *param,
__u16 port, int iif)
{
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = port;
addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
}
/* Initialize an address parameter from a sctp_addr and return the length
* of the address parameter.
*/
static int sctp_v4_to_addr_param(const union sctp_addr *addr,
union sctp_addr_param *param)
{
int length = sizeof(sctp_ipv4addr_param_t);
param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
param->v4.param_hdr.length = ntohs(length);
param->v4.addr.s_addr = addr->v4.sin_addr.s_addr;
return length;
}
/* 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,
unsigned short port) unsigned short port)
...@@ -862,6 +887,8 @@ struct sctp_af sctp_ipv4_specific = { ...@@ -862,6 +887,8 @@ struct sctp_af sctp_ipv4_specific = {
.from_sk = sctp_v4_from_sk, .from_sk = sctp_v4_from_sk,
.to_sk_saddr = sctp_v4_to_sk_saddr, .to_sk_saddr = sctp_v4_to_sk_saddr,
.to_sk_daddr = sctp_v4_to_sk_daddr, .to_sk_daddr = sctp_v4_to_sk_daddr,
.from_addr_param= sctp_v4_from_addr_param,
.to_addr_param = sctp_v4_to_addr_param,
.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,
......
...@@ -1214,6 +1214,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, ...@@ -1214,6 +1214,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
struct sctp_association *asoc; struct sctp_association *asoc;
struct sk_buff *skb; struct sk_buff *skb;
sctp_scope_t scope; sctp_scope_t scope;
struct sctp_af *af;
/* Create the bare association. */ /* Create the bare association. */
scope = sctp_scope(sctp_source(chunk)); scope = sctp_scope(sctp_source(chunk));
...@@ -1223,29 +1224,10 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, ...@@ -1223,29 +1224,10 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep,
asoc->temp = 1; asoc->temp = 1;
skb = chunk->skb; skb = chunk->skb;
/* Create an entry for the source address of the packet. */ /* Create an entry for the source address of the packet. */
/* FIXME: Use the af specific helpers. */ af = sctp_get_af_specific(ipver2af(skb->nh.iph->version));
switch (skb->nh.iph->version) { if (unlikely(!af))
case 4:
asoc->c.peer_addr.v4.sin_family = AF_INET;
asoc->c.peer_addr.v4.sin_port = ntohs(chunk->sctp_hdr->source);
asoc->c.peer_addr.v4.sin_addr.s_addr = skb->nh.iph->saddr;
break;
case 6:
asoc->c.peer_addr.v6.sin6_family = AF_INET6;
asoc->c.peer_addr.v6.sin6_port
= ntohs(chunk->sctp_hdr->source);
asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */
asoc->c.peer_addr.v6.sin6_addr = skb->nh.ipv6h->saddr;
asoc->c.peer_addr.v6.sin6_scope_id =
((struct inet6_skb_parm *)skb->cb)->iif;
break;
default:
/* Yikes! I never heard of this kind of address. */
goto fail; goto fail;
}; af->from_skb(&asoc->c.peer_addr, skb, 1);
nodata: nodata:
return asoc; return asoc;
...@@ -1883,6 +1865,7 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param, ...@@ -1883,6 +1865,7 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
int retval = 1; int retval = 1;
sctp_scope_t scope; sctp_scope_t scope;
time_t stale; time_t stale;
struct sctp_af *af;
/* We maintain all INIT parameters in network byte order all the /* We maintain all INIT parameters in network byte order all the
* time. This allows us to not worry about whether the parameters * time. This allows us to not worry about whether the parameters
...@@ -1894,7 +1877,8 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param, ...@@ -1894,7 +1877,8 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
break; break;
/* Fall through. */ /* Fall through. */
case SCTP_PARAM_IPV4_ADDRESS: case SCTP_PARAM_IPV4_ADDRESS:
sctp_param2sockaddr(&addr, param.addr, asoc->peer.port, 0); af = sctp_get_af_specific(param_type2af(param.p->type));
af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
scope = sctp_scope(peer_addr); scope = sctp_scope(peer_addr);
if (sctp_in_scope(&addr, scope)) if (sctp_in_scope(&addr, scope))
if (!sctp_assoc_add_peer(asoc, &addr, gfp)) if (!sctp_assoc_add_peer(asoc, &addr, gfp))
...@@ -2006,90 +1990,6 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep) ...@@ -2006,90 +1990,6 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep)
return retval; return retval;
} }
/********************************************************************
* 4th Level Abstractions
********************************************************************/
/* Convert from an SCTP IP parameter to a union sctp_addr. */
void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *param,
__u16 port, int iif)
{
switch(param->v4.param_hdr.type) {
case SCTP_PARAM_IPV4_ADDRESS:
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = port;
addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
break;
case SCTP_PARAM_IPV6_ADDRESS:
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = port;
addr->v6.sin6_flowinfo = 0; /* BUG */
addr->v6.sin6_addr = param->v6.addr;
addr->v6.sin6_scope_id = iif;
break;
default:
SCTP_DEBUG_PRINTK("Illegal address type %d\n",
ntohs(param->v4.param_hdr.type));
break;
};
}
/* Convert an IP address in an SCTP param into a sockaddr_in. */
/* Returns true if a valid conversion was possible. */
int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa)
{
switch (p.p->type) {
case SCTP_PARAM_IPV4_ADDRESS:
sa->v4.sin_addr = *((struct in_addr *)&p.v4->addr);
sa->v4.sin_family = AF_INET;
break;
case SCTP_PARAM_IPV6_ADDRESS:
*((struct in6_addr *)&sa->v4.sin_addr)
= p.v6->addr;
sa->v4.sin_family = AF_INET6;
break;
default:
return 0;
};
return 1;
}
/* Convert a sockaddr_in to an IP address in an SCTP param.
* Returns len if a valid conversion was possible.
*/
int sockaddr2sctp_addr(const union sctp_addr *sa, union sctp_addr_param *p)
{
int len = 0;
switch (sa->v4.sin_family) {
case AF_INET:
p->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
p->v4.param_hdr.length = ntohs(sizeof(sctp_ipv4addr_param_t));
len = sizeof(sctp_ipv4addr_param_t);
p->v4.addr.s_addr = sa->v4.sin_addr.s_addr;
break;
case AF_INET6:
p->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
p->v6.param_hdr.length = ntohs(sizeof(sctp_ipv6addr_param_t));
len = sizeof(sctp_ipv6addr_param_t);
p->v6.addr = *(&sa->v6.sin6_addr);
break;
default:
printk(KERN_WARNING "sockaddr2sctp_addr: Illegal family %d.\n",
sa->v4.sin_family);
return 0;
};
return len;
}
/* /*
* ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF) * ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF)
* 0 1 2 3 * 0 1 2 3
...@@ -2120,8 +2020,9 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, ...@@ -2120,8 +2020,9 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
int length = sizeof(asconf) + vparam_len; int length = sizeof(asconf) + vparam_len;
union sctp_params addrparam; union sctp_params addrparam;
int addrlen; int addrlen;
struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family);
addrlen = sockaddr2sctp_addr(addr, (union sctp_addr_param *)&addrparam); addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam);
if (!addrlen) if (!addrlen)
return NULL; return NULL;
length += addrlen; length += addrlen;
...@@ -2163,8 +2064,9 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, ...@@ -2163,8 +2064,9 @@ struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
int len = sizeof(param); int len = sizeof(param);
union sctp_params addrparam; union sctp_params addrparam;
int addrlen; int addrlen;
struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family);
addrlen = sockaddr2sctp_addr(addr, (union sctp_addr_param *)&addrparam); addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam);
if (!addrlen) if (!addrlen)
return NULL; return NULL;
len += addrlen; len += addrlen;
......
...@@ -929,6 +929,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, ...@@ -929,6 +929,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
struct sctp_errhdr *errhdr; struct sctp_errhdr *errhdr;
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)]; char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)];
struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family);
/* Build the error on the stack. We are way to malloc crazy /* Build the error on the stack. We are way to malloc crazy
* throughout the code today. * throughout the code today.
...@@ -937,7 +938,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, ...@@ -937,7 +938,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
addrparm = (union sctp_addr_param *)errhdr->variable; addrparm = (union sctp_addr_param *)errhdr->variable;
/* Copy into a parm format. */ /* Copy into a parm format. */
len = sockaddr2sctp_addr(ssa, addrparm); len = af->to_addr_param(ssa, addrparm);
len += sizeof(sctp_errhdr_t); len += sizeof(sctp_errhdr_t);
errhdr->cause = SCTP_ERROR_RESTART; errhdr->cause = SCTP_ERROR_RESTART;
......
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