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 @@
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* 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
*
......@@ -257,6 +257,8 @@ typedef struct sctp_func {
void (*from_skb) (union sctp_addr *,
struct sk_buff *skb,
int saddr);
int (*addr_valid) (union sctp_addr *);
sctp_scope_t (*scope) (union sctp_addr *);
__u16 net_header_len;
int sockaddr_len;
sa_family_t sa_family;
......@@ -269,13 +271,14 @@ sctp_func_t *sctp_get_af_specific(sa_family_t);
typedef struct sctp_pf {
void (*event_msgname)(sctp_ulpevent_t *, char *, int *);
void (*skb_msgname)(struct sk_buff *, char *, int *);
int (*af_supported)(sa_family_t);
} sctp_pf_t;
/* SCTP Socket type: UDP or TCP style. */
typedef enum {
SCTP_SOCKET_UDP = 0,
SCTP_SOCKET_UDP_HIGH_BANDWIDTH,
SCTP_SOCKET_TCP
SCTP_SOCKET_UDP_HIGH_BANDWIDTH,
SCTP_SOCKET_TCP
} sctp_socket_type_t;
/* Per socket SCTP information. */
......@@ -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);
sctp_chunk_t *sctp_chunkify(struct sk_buff *, const sctp_association_t *,
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);
/* This is a structure for holding either an IPv6 or an IPv4 address. */
......
/* SCTP kernel reference Implementation
* Copyright (c) Cisco 1999,2000
* 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
*
* 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)
*
* 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)
{
union sctp_params addrparms;
......@@ -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;
switch (param->type) {
case SCTP_PARAM_IPV4_ADDRESS:
case SCTP_PARAM_IPV4_ADDRESS:
case SCTP_PARAM_IPV6_ADDRESS:
sctp_param2sockaddr(&addr, rawaddr, port);
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)
/* What is the scope of '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) {
case AF_INET:
/* We are 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>.
* 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;
};
af = sctp_get_af_specific(addr->sa.sa_family);
if (!af)
return SCTP_SCOPE_UNUSABLE;
return 1;
return af->scope((union sctp_addr *)addr);
}
......@@ -132,7 +132,7 @@ int sctp_rcv(struct sk_buff *skb)
* IP broadcast addresses cannot be used in an SCTP transport
* address."
*/
if (!sctp_addr_is_valid(&src) || !sctp_addr_is_valid(&dest))
if (!af->addr_valid(&src) || !af->addr_valid(&dest))
goto discard_it;
asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
......@@ -172,7 +172,7 @@ int sctp_rcv(struct sk_buff *skb)
chunk->sctp_hdr = sh;
/* 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. */
chunk->transport = transport;
......
......@@ -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 ",
__FUNCTION__, NIP6(fl.fl6_dst));
__FUNCTION__, NIP6(fl.fl6_dst));
if (saddr) {
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,
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_flowinfo = 0; /* FIXME */
addr->v6.sin6_scope_id = 0; /* FIXME */
sh = (struct sctphdr *) skb->h.raw;
if (is_saddr) {
*port = ntohs(sh->source);
......@@ -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. */
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;
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. */
......@@ -282,7 +331,7 @@ static void sctp_inet6_msgname(char *msgname, int *addr_len)
}
/* 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)
{
struct sockaddr_in6 *sin6, *sin6from;
......@@ -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 = {
.family = PF_INET6,
.release = inet6_release,
......@@ -386,6 +452,8 @@ static sctp_func_t sctp_ipv6_specific = {
.copy_addrlist = sctp_v6_copy_addrlist,
.from_skb = sctp_v6_from_skb,
.cmp_saddr = sctp_v6_cmp_saddr,
.scope = sctp_v6_scope,
.addr_valid = sctp_v6_addr_valid,
.net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6),
.sa_family = AF_INET6,
......@@ -394,6 +462,7 @@ static sctp_func_t sctp_ipv6_specific = {
static sctp_pf_t sctp_pf_inet6_specific = {
.event_msgname = sctp_inet6_event_msgname,
.skb_msgname = sctp_inet6_skb_msgname,
.af_supported = sctp_inet6_af_supported,
};
/* Initialize IPv6 support and register with inet6 stack. */
......
......@@ -5,42 +5,42 @@
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
*
*
* This file is part of the SCTP kernel reference Implementation
*
* Initialization/cleanup for SCTP protocol support.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
*
* Initialization/cleanup for SCTP protocol support.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* 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
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* 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
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Jon Grimm <jgrimm@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
*
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*/
......@@ -103,7 +103,7 @@ void sctp_proc_exit(void)
/* Private helper to extract ipv4 address and stash them in
* 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 in_device *in_dev;
......@@ -227,10 +227,10 @@ struct dst_entry *sctp_v4_get_dst(union sctp_addr *daddr,
union sctp_addr *saddr)
{
struct rtable *rt;
struct flowi fl = {
.nl_u = {
struct flowi fl = {
.nl_u = {
.ip4_u = { .daddr =
daddr->v4.sin_addr.s_addr, }},
daddr->v4.sin_addr.s_addr, }},
.proto = IPPROTO_SCTP,
};
......@@ -280,7 +280,52 @@ int sctp_v4_cmp_saddr(struct dst_entry *dst, union sctp_addr *saddr)
{
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.
......@@ -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)
{
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)msgname;
*addr_len = sizeof(struct sockaddr_in);
sin->sin_family = AF_INET;
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
}
/* 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)
{
......@@ -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_addr.s_addr = sinfrom->sin_addr.s_addr;
}
}
}
/* 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;
if (msgname) {
sctp_inet_msgname(msgname, addr_len);
sctp_inet_msgname(msgname, len);
sin = (struct sockaddr_in *)msgname;
sh = (struct sctphdr *)skb->h.raw;
sin->sin_port = sh->source;
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 = {
.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 = {
.copy_addrlist = sctp_v4_copy_addrlist,
.from_skb = sctp_v4_from_skb,
.cmp_saddr = sctp_v4_cmp_saddr,
.addr_valid = sctp_v4_addr_valid,
.scope = sctp_v4_scope,
.net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in),
.sa_family = AF_INET,
......
......@@ -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. */
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;
struct sk_buff *skb;
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;
};
memcpy(&chunk->source, src, sizeof(union sctp_addr));
memcpy(&chunk->dest, dest, sizeof(union sctp_addr));
}
/* 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
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;
sa = (union sctp_addr *)addr;
switch (sa->sa.sa_family) {
case AF_INET:
if (addrlen < sizeof(struct sockaddr_in))
return -EINVAL;
break;
case AF_INET6:
if (PF_INET == sk->family)
return -EINVAL;
SCTP_V6(
if (addrlen < sizeof(struct sockaddr_in6))
return -EINVAL;
break;
);
/* Do we support this address family in general? */
af = sctp_get_af_specific(addr->sa_family);
if (!af)
return -EINVAL;
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;
};
/* Disallow any illegal addresses to be used as destinations. */
if (!sctp_addr_is_valid(sa))
/* Is this a valid SCTP address? */
if (!af->addr_valid((union sctp_addr *)addr))
return -EINVAL;
return 0;
return 0;
}
/* 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