Commit f8dfb3b0 authored by Jon Grimm's avatar Jon Grimm

[SCTP] Addr family cleanup part 2. (jgrimm)

Splitting out yet more code.  New af and pf specific functions. 
parent d9a91e70
...@@ -2,7 +2,7 @@ ...@@ -2,7 +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 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 International Business Machines Corp. * Copyright (c) 2001-2002 International Business Machines Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -257,6 +257,8 @@ typedef struct sctp_func { ...@@ -257,6 +257,8 @@ typedef struct sctp_func {
void (*from_skb) (union sctp_addr *, void (*from_skb) (union sctp_addr *,
struct sk_buff *skb, struct sk_buff *skb,
int saddr); int saddr);
int (*addr_valid) (union sctp_addr *);
sctp_scope_t (*scope) (union sctp_addr *);
__u16 net_header_len; __u16 net_header_len;
int sockaddr_len; int sockaddr_len;
sa_family_t sa_family; sa_family_t sa_family;
...@@ -269,13 +271,14 @@ sctp_func_t *sctp_get_af_specific(sa_family_t); ...@@ -269,13 +271,14 @@ sctp_func_t *sctp_get_af_specific(sa_family_t);
typedef struct sctp_pf { typedef struct sctp_pf {
void (*event_msgname)(sctp_ulpevent_t *, char *, int *); void (*event_msgname)(sctp_ulpevent_t *, char *, int *);
void (*skb_msgname)(struct sk_buff *, char *, int *); void (*skb_msgname)(struct sk_buff *, char *, int *);
int (*af_supported)(sa_family_t);
} sctp_pf_t; } sctp_pf_t;
/* 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,
SCTP_SOCKET_UDP_HIGH_BANDWIDTH, SCTP_SOCKET_UDP_HIGH_BANDWIDTH,
SCTP_SOCKET_TCP SCTP_SOCKET_TCP
} sctp_socket_type_t; } sctp_socket_type_t;
/* Per socket SCTP information. */ /* Per socket SCTP information. */
...@@ -505,7 +508,7 @@ void *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data); ...@@ -505,7 +508,7 @@ void *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data);
int sctp_user_addto_chunk(sctp_chunk_t *chunk, int len, struct iovec *data); int sctp_user_addto_chunk(sctp_chunk_t *chunk, int len, struct iovec *data);
sctp_chunk_t *sctp_chunkify(struct sk_buff *, const sctp_association_t *, sctp_chunk_t *sctp_chunkify(struct sk_buff *, const sctp_association_t *,
struct sock *); struct sock *);
void sctp_init_addrs(sctp_chunk_t *chunk); void sctp_init_addrs(sctp_chunk_t *, union sctp_addr *, union sctp_addr *);
const union sctp_addr *sctp_source(const sctp_chunk_t *chunk); const union sctp_addr *sctp_source(const sctp_chunk_t *chunk);
/* This is a structure for holding either an IPv6 or an IPv4 address. */ /* This is a structure for holding either an IPv6 or an IPv4 address. */
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) Cisco 1999,2000 * Copyright (c) Cisco 1999,2000
* Copyright (c) Motorola 1999,2000,2001 * Copyright (c) Motorola 1999,2000,2001
* Copyright (c) International Business Machines Corp., 2001 * Copyright (c) International Business Machines Corp., 2001,2002
* Copyright (c) La Monte H.P. Yarroll 2001 * Copyright (c) La Monte H.P. Yarroll 2001
* *
* This file is part of the SCTP kernel reference implementation. * This file is part of the SCTP kernel reference implementation.
...@@ -196,7 +196,7 @@ int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr) ...@@ -196,7 +196,7 @@ int sctp_del_bind_addr(sctp_bind_addr_t *bp, union sctp_addr *del_addr)
* *
* The second argument is the return value for the length. * The second argument is the return value for the length.
*/ */
union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
int *addrs_len, int priority) int *addrs_len, int priority)
{ {
union sctp_params addrparms; union sctp_params addrparms;
...@@ -252,7 +252,7 @@ int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list, ...@@ -252,7 +252,7 @@ int sctp_raw_to_bind_addrs(sctp_bind_addr_t *bp, __u8 *raw_addr_list,
rawaddr = (sctp_addr_param_t *)raw_addr_list; rawaddr = (sctp_addr_param_t *)raw_addr_list;
switch (param->type) { switch (param->type) {
case SCTP_PARAM_IPV4_ADDRESS: case SCTP_PARAM_IPV4_ADDRESS:
case SCTP_PARAM_IPV6_ADDRESS: case SCTP_PARAM_IPV6_ADDRESS:
sctp_param2sockaddr(&addr, rawaddr, port); sctp_param2sockaddr(&addr, rawaddr, port);
retval = sctp_add_bind_addr(bp, &addr, priority); retval = sctp_add_bind_addr(bp, &addr, priority);
...@@ -422,110 +422,11 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope) ...@@ -422,110 +422,11 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope)
/* What is the scope of 'addr'? */ /* What is the scope of 'addr'? */
sctp_scope_t sctp_scope(const union sctp_addr *addr) sctp_scope_t sctp_scope(const union sctp_addr *addr)
{ {
sctp_scope_t retval = SCTP_SCOPE_GLOBAL; struct sctp_func *af;
switch (addr->sa.sa_family) { af = sctp_get_af_specific(addr->sa.sa_family);
case AF_INET: if (!af)
/* We are checking the loopback, private and other address return SCTP_SCOPE_UNUSABLE;
* scopes as defined in RFC 1918.
* The IPv4 scoping is based on the draft for SCTP IPv4
* scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>.
* The set of SCTP address scope hopefully can cover both
* types of addresses.
*/
/* Should IPv4 scoping be a sysctl configurable option
* so users can turn it off (default on) for certain
* unconventional networking environments?
*/
/* Check for unusable SCTP addresses. */
if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) {
retval = SCTP_SCOPE_UNUSABLE;
} else if (LOOPBACK(addr->v4.sin_addr.s_addr)) {
retval = SCTP_SCOPE_LOOPBACK;
} else if (IS_IPV4_LINK_ADDRESS(&addr->v4.sin_addr.s_addr)) {
retval = SCTP_SCOPE_LINK;
} else if (IS_IPV4_PRIVATE_ADDRESS(&addr->v4.sin_addr.s_addr)) {
retval = SCTP_SCOPE_PRIVATE;
} else {
retval = SCTP_SCOPE_GLOBAL;
}
break;
case AF_INET6:
{
SCTP_V6(
int v6scope;
v6scope = ipv6_addr_scope((struct in6_addr *)
&addr->v6.sin6_addr);
/* The IPv6 scope is really a set of bit
* fields. See IFA_* in <net/if_inet6.h>.
* Mapping them to the generic SCTP scope
* set is an attempt to have code
* consistencies with the IPv4 scoping.
*/
switch (v6scope) {
case IFA_HOST:
retval = SCTP_SCOPE_LOOPBACK;
break;
case IFA_LINK:
retval = SCTP_SCOPE_LINK;
break;
case IFA_SITE:
retval = SCTP_SCOPE_PRIVATE;
break;
default:
retval = SCTP_SCOPE_GLOBAL;
break;
};
);
break;
}
default:
retval = SCTP_SCOPE_GLOBAL;
break;
};
return retval;
}
/* This function checks if the address is a valid address to be used for
* SCTP.
*
* Output:
* Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast.
*/
int sctp_addr_is_valid(const union sctp_addr *addr)
{
unsigned short sa_family = addr->sa.sa_family;
switch (sa_family) {
case AF_INET:
/* Is this a non-unicast address or a unusable SCTP address? */
if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
return 0;
break;
case AF_INET6:
SCTP_V6(
{
int ret = sctp_ipv6_addr_type(&addr->v6.sin6_addr);
/* Is this a non-unicast address */
if (!(ret & IPV6_ADDR_UNICAST))
return 0;
break;
});
default:
return 0;
};
return 1; return af->scope((union sctp_addr *)addr);
} }
...@@ -132,7 +132,7 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -132,7 +132,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 (!sctp_addr_is_valid(&src) || !sctp_addr_is_valid(&dest)) if (!af->addr_valid(&src) || !af->addr_valid(&dest))
goto discard_it; goto discard_it;
asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
...@@ -172,7 +172,7 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -172,7 +172,7 @@ int sctp_rcv(struct sk_buff *skb)
chunk->sctp_hdr = sh; chunk->sctp_hdr = sh;
/* Set the source and destination addresses of the incoming chunk. */ /* Set the source and destination addresses of the incoming chunk. */
sctp_init_addrs(chunk); sctp_init_addrs(chunk, &src, &dest);
/* Remember where we came from. */ /* Remember where we came from. */
chunk->transport = transport; chunk->transport = transport;
......
...@@ -181,7 +181,7 @@ struct dst_entry *sctp_v6_get_dst(union sctp_addr *daddr, ...@@ -181,7 +181,7 @@ struct dst_entry *sctp_v6_get_dst(union sctp_addr *daddr,
SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
__FUNCTION__, NIP6(fl.fl6_dst)); __FUNCTION__, NIP6(fl.fl6_dst));
if (saddr) { if (saddr) {
fl.fl6_src = &saddr->v6.sin6_addr; fl.fl6_src = &saddr->v6.sin6_addr;
...@@ -249,7 +249,7 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, ...@@ -249,7 +249,7 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
addr->v6.sin6_family = AF_INET6; addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_flowinfo = 0; /* FIXME */ addr->v6.sin6_flowinfo = 0; /* FIXME */
addr->v6.sin6_scope_id = 0; /* FIXME */ addr->v6.sin6_scope_id = 0; /* FIXME */
sh = (struct sctphdr *) skb->h.raw; sh = (struct sctphdr *) skb->h.raw;
if (is_saddr) { if (is_saddr) {
*port = ntohs(sh->source); *port = ntohs(sh->source);
...@@ -262,11 +262,60 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, ...@@ -262,11 +262,60 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
} }
/* Check if the dst entry's source addr matches the given source addr. */ /* Check if the dst entry's source addr matches the given source addr. */
int sctp_v6_cmp_saddr(struct dst_entry *dst, union sctp_addr *saddr) static int sctp_v6_cmp_saddr(struct dst_entry *dst, union sctp_addr *saddr)
{ {
struct rt6_info *rt = (struct rt6_info *)dst; struct rt6_info *rt = (struct rt6_info *)dst;
return ipv6_addr_cmp(&rt->rt6i_src.addr, &saddr->v6.sin6_addr); return ipv6_addr_cmp(&rt->rt6i_src.addr, &saddr->v6.sin6_addr);
}
/* This function checks if the address is a valid address to be used for
* SCTP.
*
* Output:
* Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast.
*/
static int sctp_v6_addr_valid(union sctp_addr *addr)
{
int ret = sctp_ipv6_addr_type(&addr->v6.sin6_addr);
/* FIXME: v4-mapped-v6 address support. */
/* Is this a non-unicast address */
if (!(ret & IPV6_ADDR_UNICAST))
return 0;
return 1;
}
/* What is the scope of 'addr'? */
static sctp_scope_t sctp_v6_scope(union sctp_addr *addr)
{
int v6scope;
sctp_scope_t retval;
/* The IPv6 scope is really a set of bit fields.
* See IFA_* in <net/if_inet6.h>. Map to a generic SCTP scope.
*/
v6scope = ipv6_addr_scope(&addr->v6.sin6_addr);
switch (v6scope) {
case IFA_HOST:
retval = SCTP_SCOPE_LOOPBACK;
break;
case IFA_LINK:
retval = SCTP_SCOPE_LINK;
break;
case IFA_SITE:
retval = SCTP_SCOPE_PRIVATE;
break;
default:
retval = SCTP_SCOPE_GLOBAL;
break;
};
return retval;
} }
/* Initialize a PF_INET6 socket msg_name. */ /* Initialize a PF_INET6 socket msg_name. */
...@@ -282,7 +331,7 @@ static void sctp_inet6_msgname(char *msgname, int *addr_len) ...@@ -282,7 +331,7 @@ static void sctp_inet6_msgname(char *msgname, int *addr_len)
} }
/* Initialize a PF_INET msgname from a ulpevent. */ /* Initialize a PF_INET msgname from a ulpevent. */
static void sctp_inet6_event_msgname(sctp_ulpevent_t *event, char *msgname, static void sctp_inet6_event_msgname(sctp_ulpevent_t *event, char *msgname,
int *addrlen) int *addrlen)
{ {
struct sockaddr_in6 *sin6, *sin6from; struct sockaddr_in6 *sin6, *sin6from;
...@@ -344,6 +393,23 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, ...@@ -344,6 +393,23 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
} }
} }
/* Do we support this AF? */
static int sctp_inet6_af_supported(sa_family_t family)
{
/* 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) {
case AF_INET6:
case AF_INET:
return 1;
default:
return 0;
}
}
static struct proto_ops inet6_seqpacket_ops = { static struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6, .family = PF_INET6,
.release = inet6_release, .release = inet6_release,
...@@ -386,6 +452,8 @@ static sctp_func_t sctp_ipv6_specific = { ...@@ -386,6 +452,8 @@ static sctp_func_t 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,
.cmp_saddr = sctp_v6_cmp_saddr, .cmp_saddr = sctp_v6_cmp_saddr,
.scope = sctp_v6_scope,
.addr_valid = sctp_v6_addr_valid,
.net_header_len = sizeof(struct ipv6hdr), .net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6), .sockaddr_len = sizeof(struct sockaddr_in6),
.sa_family = AF_INET6, .sa_family = AF_INET6,
...@@ -394,6 +462,7 @@ static sctp_func_t sctp_ipv6_specific = { ...@@ -394,6 +462,7 @@ static sctp_func_t sctp_ipv6_specific = {
static sctp_pf_t sctp_pf_inet6_specific = { static sctp_pf_t sctp_pf_inet6_specific = {
.event_msgname = sctp_inet6_event_msgname, .event_msgname = sctp_inet6_event_msgname,
.skb_msgname = sctp_inet6_skb_msgname, .skb_msgname = sctp_inet6_skb_msgname,
.af_supported = sctp_inet6_af_supported,
}; };
/* Initialize IPv6 support and register with inet6 stack. */ /* Initialize IPv6 support and register with inet6 stack. */
......
...@@ -5,42 +5,42 @@ ...@@ -5,42 +5,42 @@
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* 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
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* Initialization/cleanup for SCTP protocol support. * Initialization/cleanup for SCTP protocol support.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* 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.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@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
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -103,7 +103,7 @@ void sctp_proc_exit(void) ...@@ -103,7 +103,7 @@ void sctp_proc_exit(void)
/* Private helper to extract ipv4 address and stash them in /* Private helper to extract ipv4 address and stash them in
* the protocol structure. * the protocol structure.
*/ */
static void sctp_v4_copy_addrlist(struct list_head *addrlist, static void sctp_v4_copy_addrlist(struct list_head *addrlist,
struct net_device *dev) struct net_device *dev)
{ {
struct in_device *in_dev; struct in_device *in_dev;
...@@ -227,10 +227,10 @@ struct dst_entry *sctp_v4_get_dst(union sctp_addr *daddr, ...@@ -227,10 +227,10 @@ struct dst_entry *sctp_v4_get_dst(union sctp_addr *daddr,
union sctp_addr *saddr) union sctp_addr *saddr)
{ {
struct rtable *rt; struct rtable *rt;
struct flowi fl = { struct flowi fl = {
.nl_u = { .nl_u = {
.ip4_u = { .daddr = .ip4_u = { .daddr =
daddr->v4.sin_addr.s_addr, }}, daddr->v4.sin_addr.s_addr, }},
.proto = IPPROTO_SCTP, .proto = IPPROTO_SCTP,
}; };
...@@ -280,7 +280,52 @@ int sctp_v4_cmp_saddr(struct dst_entry *dst, union sctp_addr *saddr) ...@@ -280,7 +280,52 @@ int sctp_v4_cmp_saddr(struct dst_entry *dst, union sctp_addr *saddr)
{ {
struct rtable *rt = (struct rtable *)dst; struct rtable *rt = (struct rtable *)dst;
return (rt->rt_src == saddr->v4.sin_addr.s_addr); return (rt->rt_src == saddr->v4.sin_addr.s_addr);
}
/* This function checks if the address is a valid address to be used for
* SCTP.
*
* Output:
* Return 0 - If the address is a non-unicast or an illegal address.
* Return 1 - If the address is a unicast.
*/
static int sctp_v4_addr_valid(union sctp_addr *addr)
{
/* Is this a non-unicast address or a unusable SCTP address? */
if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
return 0;
return 1;
}
/* Checking the loopback, private and other address scopes as defined in
* RFC 1918. The IPv4 scoping is based on the draft for SCTP IPv4
* scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>.
*/
static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
{
sctp_scope_t retval;
/* Should IPv4 scoping be a sysctl configurable option
* so users can turn it off (default on) for certain
* unconventional networking environments?
*/
/* Check for unusable SCTP addresses. */
if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) {
retval = SCTP_SCOPE_UNUSABLE;
} else if (LOOPBACK(addr->v4.sin_addr.s_addr)) {
retval = SCTP_SCOPE_LOOPBACK;
} else if (IS_IPV4_LINK_ADDRESS(&addr->v4.sin_addr.s_addr)) {
retval = SCTP_SCOPE_LINK;
} else if (IS_IPV4_PRIVATE_ADDRESS(&addr->v4.sin_addr.s_addr)) {
retval = SCTP_SCOPE_PRIVATE;
} else {
retval = SCTP_SCOPE_GLOBAL;
}
return retval;
} }
/* Event handler for inet device events. /* Event handler for inet device events.
...@@ -352,13 +397,13 @@ sctp_func_t *sctp_get_af_specific(sa_family_t family) ...@@ -352,13 +397,13 @@ sctp_func_t *sctp_get_af_specific(sa_family_t family)
static void sctp_inet_msgname(char *msgname, int *addr_len) static void sctp_inet_msgname(char *msgname, int *addr_len)
{ {
struct sockaddr_in *sin; struct sockaddr_in *sin;
sin = (struct sockaddr_in *)msgname; sin = (struct sockaddr_in *)msgname;
*addr_len = sizeof(struct sockaddr_in); *addr_len = sizeof(struct sockaddr_in);
sin->sin_family = AF_INET; sin->sin_family = AF_INET;
memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
} }
/* Copy the primary address of the peer primary address as the msg_name. */ /* Copy the primary address of the peer primary address as the msg_name. */
static void sctp_inet_event_msgname(sctp_ulpevent_t *event, char *msgname, int *addr_len) static void sctp_inet_event_msgname(sctp_ulpevent_t *event, char *msgname, int *addr_len)
{ {
...@@ -371,26 +416,34 @@ static void sctp_inet_event_msgname(sctp_ulpevent_t *event, char *msgname, int * ...@@ -371,26 +416,34 @@ static void sctp_inet_event_msgname(sctp_ulpevent_t *event, char *msgname, int *
sin->sin_port = htons(event->asoc->peer.port); sin->sin_port = htons(event->asoc->peer.port);
sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr; sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr;
} }
} }
/* Initialize and copy out a msgname from an inbound skb. */ /* Initialize and copy out a msgname from an inbound skb. */
static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *addr_len) static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len)
{ {
struct sctphdr *sh; struct sctphdr *sh;
struct sockaddr_in *sin; struct sockaddr_in *sin;
if (msgname) { if (msgname) {
sctp_inet_msgname(msgname, addr_len); sctp_inet_msgname(msgname, len);
sin = (struct sockaddr_in *)msgname; sin = (struct sockaddr_in *)msgname;
sh = (struct sctphdr *)skb->h.raw; sh = (struct sctphdr *)skb->h.raw;
sin->sin_port = sh->source; sin->sin_port = sh->source;
sin->sin_addr.s_addr = skb->nh.iph->saddr; sin->sin_addr.s_addr = skb->nh.iph->saddr;
} }
} }
/* Do we support this AF? */
static int sctp_inet_af_supported(sa_family_t family)
{
/* PF_INET only supports AF_INET addresses. */
return (AF_INET == family);
}
static sctp_pf_t sctp_pf_inet = { static sctp_pf_t sctp_pf_inet = {
.event_msgname = sctp_inet_event_msgname, .event_msgname = sctp_inet_event_msgname,
.skb_msgname = sctp_inet_skb_msgname, .skb_msgname = sctp_inet_skb_msgname,
.af_supported = sctp_inet_af_supported,
}; };
...@@ -446,6 +499,8 @@ struct sctp_func sctp_ipv4_specific = { ...@@ -446,6 +499,8 @@ struct sctp_func 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,
.cmp_saddr = sctp_v4_cmp_saddr, .cmp_saddr = sctp_v4_cmp_saddr,
.addr_valid = sctp_v4_addr_valid,
.scope = sctp_v4_scope,
.net_header_len = sizeof(struct iphdr), .net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in), .sockaddr_len = sizeof(struct sockaddr_in),
.sa_family = AF_INET, .sa_family = AF_INET,
......
...@@ -1031,47 +1031,11 @@ sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, const sctp_association_t *asoc, ...@@ -1031,47 +1031,11 @@ sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, const sctp_association_t *asoc,
} }
/* Set chunk->source and dest based on the IP header in chunk->skb. */ /* Set chunk->source and dest based on the IP header in chunk->skb. */
void sctp_init_addrs(sctp_chunk_t *chunk) void sctp_init_addrs(sctp_chunk_t *chunk, union sctp_addr *src,
union sctp_addr *dest)
{ {
union sctp_addr *source, *dest; memcpy(&chunk->source, src, sizeof(union sctp_addr));
struct sk_buff *skb; memcpy(&chunk->dest, dest, sizeof(union sctp_addr));
struct sctphdr *sh;
struct iphdr *ih4;
struct ipv6hdr *ih6;
source = &chunk->source;
dest = &chunk->dest;
skb = chunk->skb;
ih4 = skb->nh.iph;
ih6 = skb->nh.ipv6h;
sh = chunk->sctp_hdr;
switch (ih4->version) {
case 4:
source->v4.sin_family = AF_INET;
source->v4.sin_port = ntohs(sh->source);
source->v4.sin_addr.s_addr = ih4->saddr;
dest->v4.sin_family = AF_INET;
dest->v4.sin_port = ntohs(sh->dest);
dest->v4.sin_addr.s_addr = ih4->daddr;
break;
case 6:
SCTP_V6(
source->v6.sin6_family = AF_INET6;
source->v6.sin6_port = ntohs(sh->source);
source->v6.sin6_addr = ih6->saddr;
dest->v6.sin6_family = AF_INET6;
dest->v6.sin6_port = ntohs(sh->dest);
dest->v6.sin6_addr = ih6->daddr;
/* FIXME: What do we do with scope, etc. ? */
break;
)
default:
/* This is a bogus address type, just bail. */
break;
};
} }
/* Extract the source address from a chunk. */ /* Extract the source address from a chunk. */
......
...@@ -2691,38 +2691,33 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no ...@@ -2691,38 +2691,33 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no
return NULL; return NULL;
} }
static inline int sctp_verify_addr(struct sock *sk, struct sockaddr *addr, int addrlen) /* Verify that this is a valid address. */
static int sctp_verify_addr(struct sock *sk, struct sockaddr *addr, int len)
{ {
union sctp_addr *sa; struct sctp_func *af;
if (addrlen < sizeof (struct sockaddr)) /* Check minimum size. */
if (len < sizeof (struct sockaddr))
return -EINVAL; return -EINVAL;
sa = (union sctp_addr *)addr; /* Do we support this address family in general? */
switch (sa->sa.sa_family) { af = sctp_get_af_specific(addr->sa_family);
case AF_INET: if (!af)
if (addrlen < sizeof(struct sockaddr_in)) return -EINVAL;
return -EINVAL;
break;
case AF_INET6:
if (PF_INET == sk->family)
return -EINVAL;
SCTP_V6(
if (addrlen < sizeof(struct sockaddr_in6))
return -EINVAL;
break;
);
default: /* Does this PF support this AF? */
if (!sctp_sk(sk)->pf->af_supported(addr->sa_family))
return -EINVAL;
/* Verify the minimum for this AF sockaddr. */
if (len < af->sockaddr_len)
return -EINVAL; return -EINVAL;
};
/* Disallow any illegal addresses to be used as destinations. */ /* Is this a valid SCTP address? */
if (!sctp_addr_is_valid(sa)) if (!af->addr_valid((union sctp_addr *)addr))
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
/* Get the sndbuf space available at the time on the association. */ /* Get the sndbuf space available at the time on the association. */
......
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