Commit d8367696 authored by Jon Grimm's avatar Jon Grimm

[SCTP] Last of the v4/v6 partioning (for now)

Mostly code on the bind path, splitting out to pf and af family
specific functions.   Minor code cleanups/fixes mixed in.  
parent d09fc925
......@@ -123,8 +123,8 @@ extern sctp_protocol_t sctp_proto;
extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *,
sctp_scope_t, int priority, int flags);
extern sctp_pf_t *sctp_get_pf_specific(int family);
extern void sctp_set_pf_specific(int family, sctp_pf_t *);
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
/*
* sctp_socket.c
......
......@@ -234,7 +234,7 @@ struct SCTP_protocol {
* Pointers to address related SCTP functions.
* (i.e. things that depend on the address family.)
*/
typedef struct sctp_func {
struct sctp_af {
int (*queue_xmit) (struct sk_buff *skb);
int (*setsockopt) (struct sock *sk,
int level,
......@@ -259,27 +259,34 @@ typedef struct sctp_func {
void (*from_skb) (union sctp_addr *,
struct sk_buff *skb,
int saddr);
void (*from_sk) (union sctp_addr *,
struct sock *sk);
void (*to_sk) (union sctp_addr *,
struct sock *sk);
int (*addr_valid) (union sctp_addr *);
sctp_scope_t (*scope) (union sctp_addr *);
void (*inaddr_any) (union sctp_addr *, unsigned short);
int (*is_any) (const union sctp_addr *);
int (*available) (const union sctp_addr *);
__u16 net_header_len;
int sockaddr_len;
sa_family_t sa_family;
struct list_head list;
} sctp_func_t;
};
sctp_func_t *sctp_get_af_specific(sa_family_t);
struct sctp_af *sctp_get_af_specific(sa_family_t);
int sctp_register_af(struct sctp_af *);
/* Protocol family functions. */
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);
void (*skb_msgname) (struct sk_buff *, char *, int *);
int (*af_supported) (sa_family_t);
int (*cmp_addr) (const union sctp_addr *,
const union sctp_addr *,
struct sctp_opt *);
struct sctp_func *af;
int (*bind_verify) (struct sctp_opt *, union sctp_addr *);
struct sctp_af *af;
} sctp_pf_t;
/* SCTP Socket type: UDP or TCP style. */
......@@ -623,7 +630,7 @@ struct SCTP_transport {
union sctp_addr ipaddr;
/* These are the functions we call to handle LLP stuff. */
sctp_func_t *af_specific;
struct sctp_af *af_specific;
/* Which association do we belong to? */
sctp_association_t *asoc;
......
......@@ -24,3 +24,4 @@ EXPORT_SYMBOL(inet6_bind);
EXPORT_SYMBOL(inet6_getname);
EXPORT_SYMBOL(inet6_ioctl);
EXPORT_SYMBOL(ipv6_get_saddr);
EXPORT_SYMBOL(ipv6_chk_addr);
......@@ -642,7 +642,7 @@ __u16 __sctp_association_get_next_ssn(sctp_association_t *asoc, __u16 sid)
int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2)
{
struct sctp_func *af;
struct sctp_af *af;
af = sctp_get_af_specific(ss1->sa.sa_family);
if (!af)
......
......@@ -327,7 +327,7 @@ static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr,
/* Is this a wildcard address? */
int sctp_is_any(const union sctp_addr *addr)
{
struct sctp_func *af = sctp_get_af_specific(addr->sa.sa_family);
struct sctp_af *af = sctp_get_af_specific(addr->sa.sa_family);
if (!af)
return 0;
return af->is_any(addr);
......@@ -362,7 +362,7 @@ 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)
{
struct sctp_func *af;
struct sctp_af *af;
af = sctp_get_af_specific(addr->sa.sa_family);
if (!af)
......
......@@ -96,7 +96,7 @@ int sctp_rcv(struct sk_buff *skb)
struct sctphdr *sh;
union sctp_addr src;
union sctp_addr dest;
struct sctp_func *af;
struct sctp_af *af;
int ret = 0;
if (skb->pkt_type!=PACKET_HOST)
......
......@@ -140,8 +140,8 @@ static inline int sctp_v6_xmit(struct sk_buff *skb)
* to disallow loopback when the scoping rules have
* not bound loopback to the endpoint.
*/
if (sctp_ipv6_addr_type(&saddr) & IPV6_ADDR_LOOPBACK) {
if (!(sctp_ipv6_addr_type(&np->daddr) &
if (ipv6_addr_type(&saddr) & IPV6_ADDR_LOOPBACK) {
if (!(ipv6_addr_type(&np->daddr) &
IPV6_ADDR_LOOPBACK)) {
ipv6_addr_copy(&saddr, &np->daddr);
}
......@@ -261,6 +261,20 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
ipv6_addr_copy(&addr->v6.sin6_addr, from);
}
/* Initialize an sctp_addr from a socket. */
static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
{
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = inet_sk(sk)->num;
addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr;
}
/* Initialize sk->rcv_saddr from sctp_addr. */
static void sctp_v6_to_sk(union sctp_addr *addr, struct sock *sk)
{
inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
}
/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst)
{
......@@ -270,7 +284,7 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst)
}
/* Compare addresses exactly. Well.. almost exactly; ignore scope_id
* for now. FIXME.
* for now. FIXME: v4-mapped-v6.
*/
static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
const union sctp_addr *addr2)
......@@ -300,6 +314,22 @@ static int sctp_v6_is_any(const union sctp_addr *addr)
return IPV6_ADDR_ANY == type;
}
/* Should this be available for binding? */
static int sctp_v6_available(const union sctp_addr *addr)
{
int type;
struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr;
type = ipv6_addr_type(in6);
if (IPV6_ADDR_ANY == type)
return 1;
if (!(type & IPV6_ADDR_UNICAST))
return 0;
return ipv6_chk_addr(in6, NULL);
}
/* This function checks if the address is a valid address to be used for
* SCTP.
*
......@@ -309,7 +339,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr)
*/
static int sctp_v6_addr_valid(union sctp_addr *addr)
{
int ret = sctp_ipv6_addr_type(&addr->v6.sin6_addr);
int ret = ipv6_addr_type(&addr->v6.sin6_addr);
/* FIXME: v4-mapped-v6 address support. */
......@@ -448,7 +478,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
const union sctp_addr *addr2,
struct sctp_opt *opt)
{
struct sctp_func *af1, *af2;
struct sctp_af *af1, *af2;
af1 = sctp_get_af_specific(addr1->sa.sa_family);
af2 = sctp_get_af_specific(addr2->sa.sa_family);
......@@ -465,7 +495,21 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
return af1->cmp_addr(addr1, addr2);
}
/* Verify that the provided sockaddr looks bindable. Common verification,
* has already been taken care of.
*/
static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
{
struct sctp_af *af;
/* ASSERT: address family has already been verified. */
if (addr->sa.sa_family != AF_INET6) {
af = sctp_get_af_specific(addr->sa.sa_family);
} else
af = opt->pf->af;
return af->available(addr);
}
static struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6,
......@@ -501,29 +545,33 @@ static struct inet6_protocol sctpv6_protocol = {
.err_handler = sctp_v6_err,
};
static sctp_func_t sctp_ipv6_specific = {
static struct sctp_af sctp_ipv6_specific = {
.queue_xmit = sctp_v6_xmit,
.setsockopt = ipv6_setsockopt,
.getsockopt = ipv6_getsockopt,
.get_dst = sctp_v6_get_dst,
.copy_addrlist = sctp_v6_copy_addrlist,
.from_skb = sctp_v6_from_skb,
.from_sk = sctp_v6_from_sk,
.to_sk = sctp_v6_to_sk,
.dst_saddr = sctp_v6_dst_saddr,
.cmp_addr = sctp_v6_cmp_addr,
.scope = sctp_v6_scope,
.addr_valid = sctp_v6_addr_valid,
.inaddr_any = sctp_v6_inaddr_any,
.is_any = sctp_v6_is_any,
.available = sctp_v6_available,
.net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6),
.sa_family = AF_INET6,
};
static sctp_pf_t sctp_pf_inet6_specific = {
static struct sctp_pf sctp_pf_inet6_specific = {
.event_msgname = sctp_inet6_event_msgname,
.skb_msgname = sctp_inet6_skb_msgname,
.af_supported = sctp_inet6_af_supported,
.cmp_addr = sctp_inet6_cmp_addr,
.bind_verify = sctp_inet6_bind_verify,
.af = &sctp_ipv6_specific,
};
......@@ -538,11 +586,10 @@ int sctp_v6_init(void)
inet6_register_protosw(&sctpv6_protosw);
/* Register the SCTP specfic PF_INET6 functions. */
sctp_set_pf_specific(PF_INET6, &sctp_pf_inet6_specific);
sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6);
/* Fill in address family info. */
INIT_LIST_HEAD(&sctp_ipv6_specific.list);
list_add_tail(&sctp_ipv6_specific.list, &sctp_proto.address_families);
/* Register the SCTP specfic AF_INET6 functions. */
sctp_register_af(&sctp_ipv6_specific);
return 0;
}
......
......@@ -67,8 +67,10 @@ struct sctp_mib sctp_statistics[NR_CPUS * 2];
*/
static struct socket *sctp_ctl_socket;
static sctp_pf_t *sctp_pf_inet6_specific;
static sctp_pf_t *sctp_pf_inet_specific;
static struct sctp_pf *sctp_pf_inet6_specific;
static struct sctp_pf *sctp_pf_inet_specific;
static struct sctp_af *sctp_af_v4_specific;
static struct sctp_af *sctp_af_v6_specific;
extern struct net_proto_family inet_family_ops;
......@@ -140,12 +142,12 @@ static void __sctp_get_local_addr_list(sctp_protocol_t *proto)
{
struct net_device *dev;
struct list_head *pos;
struct sctp_func *af;
struct sctp_af *af;
read_lock(&dev_base_lock);
for (dev = dev_base; dev; dev = dev->next) {
list_for_each(pos, &proto->address_families) {
af = list_entry(pos, sctp_func_t, list);
af = list_entry(pos, struct sctp_af, list);
af->copy_addrlist(&proto->local_addr_list, dev);
}
}
......@@ -251,7 +253,6 @@ struct dst_entry *sctp_v4_get_dst(union sctp_addr *daddr,
return &rt->u.dst;
}
/* Initialize a sctp_addr from in incoming skb. */
static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
......@@ -274,6 +275,21 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr));
}
/* Initialize an sctp_addr from a socket. */
static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
{
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = inet_sk(sk)->num;
addr->v4.sin_addr.s_addr = inet_sk(sk)->rcv_saddr;
}
/* Initialize sk->rcv_saddr from sctp_addr. */
static void sctp_v4_to_sk(union sctp_addr *addr, struct sock *sk)
{
inet_sk(sk)->rcv_saddr = addr->v4.sin_addr.s_addr;
}
/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst)
{
......@@ -311,7 +327,7 @@ static int sctp_v4_is_any(const union sctp_addr *addr)
}
/* This function checks if the address is a valid address to be used for
* SCTP.
* SCTP binding.
*
* Output:
* Return 0 - If the address is a non-unicast or an illegal address.
......@@ -326,6 +342,18 @@ static int sctp_v4_addr_valid(union sctp_addr *addr)
return 1;
}
/* Should this be available for binding? */
static int sctp_v4_available(const union sctp_addr *addr)
{
int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
/* FIXME: ip_nonlocal_bind sysctl support. */
if (addr->v4.sin_addr.s_addr != INADDR_ANY && ret != RTN_LOCAL)
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>.
......@@ -405,29 +433,42 @@ int sctp_ctl_sock_init(void)
return 0;
}
/* Get the table of functions for manipulating a particular address
* family.
*/
sctp_func_t *sctp_get_af_specific(sa_family_t family)
/* Register address family specific functions. */
int sctp_register_af(struct sctp_af *af)
{
struct list_head *pos;
sctp_protocol_t *proto = sctp_get_protocol();
struct sctp_func *retval, *af;
switch (af->sa_family) {
case AF_INET:
if (sctp_af_v4_specific)
return 0;
sctp_af_v4_specific = sctp_af_v4_specific = af;
break;
case AF_INET6:
if (sctp_af_v6_specific)
return 0;
sctp_af_v6_specific = sctp_af_v6_specific = af;
break;
default:
return 0;
}
retval = NULL;
INIT_LIST_HEAD(&af->list);
list_add_tail(&af->list, &sctp_proto.address_families);
return 1;
}
/* Cycle through all AF specific functions looking for a
* match.
/* Get the table of functions for manipulating a particular address
* family.
*/
list_for_each(pos, &proto->address_families) {
af = list_entry(pos, sctp_func_t, list);
if (family == af->sa_family) {
retval = af;
break;
}
struct sctp_af *sctp_get_af_specific(sa_family_t family)
{
switch (family) {
case AF_INET:
return sctp_af_v4_specific;
case AF_INET6:
return sctp_af_v6_specific;
default:
return NULL;
}
return retval;
}
/* Common code to initialize a AF_INET msg_name. */
......@@ -495,18 +536,25 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
return 0;
}
/* Verify that provided sockaddr looks bindable. Common verification has
* already been taken care of.
*/
static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
{
return sctp_v4_available(addr);
}
struct sctp_func sctp_ipv4_specific;
struct sctp_af sctp_ipv4_specific;
static sctp_pf_t sctp_pf_inet = {
static struct sctp_pf sctp_pf_inet = {
.event_msgname = sctp_inet_event_msgname,
.skb_msgname = sctp_inet_skb_msgname,
.af_supported = sctp_inet_af_supported,
.cmp_addr = sctp_inet_cmp_addr,
.bind_verify = sctp_inet_bind_verify,
.af = &sctp_ipv4_specific,
};
/* Registration for netdev events. */
struct notifier_block sctp_netdev_notifier = {
.notifier_call = sctp_netdev_event,
......@@ -551,25 +599,28 @@ static struct inet_protocol sctp_protocol = {
};
/* IPv4 address related functions. */
struct sctp_func sctp_ipv4_specific = {
struct sctp_af sctp_ipv4_specific = {
.queue_xmit = ip_queue_xmit,
.setsockopt = ip_setsockopt,
.getsockopt = ip_getsockopt,
.get_dst = sctp_v4_get_dst,
.copy_addrlist = sctp_v4_copy_addrlist,
.from_skb = sctp_v4_from_skb,
.from_sk = sctp_v4_from_sk,
.to_sk = sctp_v4_to_sk,
.dst_saddr = sctp_v4_dst_saddr,
.cmp_addr = sctp_v4_cmp_addr,
.addr_valid = sctp_v4_addr_valid,
.inaddr_any = sctp_v4_inaddr_any,
.is_any = sctp_v4_is_any,
.available = sctp_v4_available,
.scope = sctp_v4_scope,
.net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in),
.sa_family = AF_INET,
};
sctp_pf_t *sctp_get_pf_specific(int family) {
struct sctp_pf *sctp_get_pf_specific(sa_family_t family) {
switch (family) {
case PF_INET:
......@@ -581,20 +632,24 @@ sctp_pf_t *sctp_get_pf_specific(int family) {
}
}
/* Set the PF specific function table. */
void sctp_set_pf_specific(int family, sctp_pf_t *pf)
/* Register the PF specific function table. */
int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
{
switch (family) {
case PF_INET:
if (sctp_pf_inet_specific)
return 0;
sctp_pf_inet_specific = pf;
break;
case PF_INET6:
if (sctp_pf_inet6_specific)
return 0;
sctp_pf_inet6_specific = pf;
break;
default:
BUG();
break;
return 0;
}
return 1;
}
/* Initialize the universe into something sensible. */
......@@ -617,7 +672,7 @@ int sctp_init(void)
sctp_dbg_objcnt_init();
/* Initialize the SCTP specific PF functions. */
sctp_set_pf_specific(PF_INET, &sctp_pf_inet);
sctp_register_pf(&sctp_pf_inet, PF_INET);
/*
* 14. Suggested SCTP Protocol Parameter Values
*/
......@@ -709,8 +764,7 @@ int sctp_init(void)
sctp_sysctl_register();
INIT_LIST_HEAD(&sctp_proto.address_families);
INIT_LIST_HEAD(&sctp_ipv4_specific.list);
list_add_tail(&sctp_ipv4_specific.list, &sctp_proto.address_families);
sctp_register_af(&sctp_ipv4_specific);
status = sctp_v6_init();
if (status)
......
This diff is collapsed.
......@@ -207,7 +207,7 @@ void sctp_transport_route(sctp_transport_t *transport, union sctp_addr *saddr,
struct sctp_opt *opt)
{
sctp_association_t *asoc = transport->asoc;
struct sctp_func *af = transport->af_specific;
struct sctp_af *af = transport->af_specific;
union sctp_addr *daddr = &transport->ipaddr;
sctp_bind_addr_t *bp;
rwlock_t *addr_lock;
......
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