X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fsctp%2Fprotocol.c;h=0ef48126b117c76267208833f76c96c84fa814bb;hb=refs%2Fheads%2Fvserver;hp=191682be45f8e4fc400ec69d80641c968682bc94;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 191682be4..0ef48126b 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -54,18 +54,19 @@ #include #include #include +#include #include #include #include #include /* Global data structures. */ -struct sctp_globals sctp_globals; +struct sctp_globals sctp_globals __read_mostly; struct proc_dir_entry *proc_net_sctp; -DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics); +DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly; struct idr sctp_assocs_id; -spinlock_t sctp_assocs_id_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(sctp_assocs_id_lock); /* This is the global socket data structure used for responding to * the Out-of-the-blue (OOTB) packets. A control sock will be created @@ -78,15 +79,8 @@ static struct sctp_pf *sctp_pf_inet_specific; static struct sctp_af *sctp_af_v4_specific; static struct sctp_af *sctp_af_v6_specific; -kmem_cache_t *sctp_chunk_cachep; -kmem_cache_t *sctp_bucket_cachep; - -extern int sctp_snmp_proc_init(void); -extern int sctp_snmp_proc_exit(void); -extern int sctp_eps_proc_init(void); -extern int sctp_eps_proc_exit(void); -extern int sctp_assocs_proc_init(void); -extern int sctp_assocs_proc_exit(void); +struct kmem_cache *sctp_chunk_cachep __read_mostly; +struct kmem_cache *sctp_bucket_cachep __read_mostly; /* Return the address of the control sock. */ struct sock *sctp_get_ctl_sock(void) @@ -95,7 +89,7 @@ struct sock *sctp_get_ctl_sock(void) } /* Set up the proc fs entry for the SCTP protocol. */ -__init int sctp_proc_init(void) +static __init int sctp_proc_init(void) { if (!proc_net_sctp) { struct proc_dir_entry *ent; @@ -124,7 +118,7 @@ out_nomem: * Note: Do not make this __exit as it is used in the init error * path. */ -void sctp_proc_exit(void) +static void sctp_proc_exit(void) { sctp_snmp_proc_exit(); sctp_eps_proc_exit(); @@ -147,7 +141,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, struct sctp_sockaddr_entry *addr; rcu_read_lock(); - if ((in_dev = __in_dev_get(dev)) == NULL) { + if ((in_dev = __in_dev_get_rcu(dev)) == NULL) { rcu_read_unlock(); return; } @@ -169,7 +163,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, /* Extract our IP addresses from the system and stash them in the * protocol structure. */ -static void __sctp_get_local_addr_list(void) +static void sctp_get_local_addr_list(void) { struct net_device *dev; struct list_head *pos; @@ -185,17 +179,8 @@ static void __sctp_get_local_addr_list(void) read_unlock(&dev_base_lock); } -static void sctp_get_local_addr_list(void) -{ - unsigned long flags; - - sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); - __sctp_get_local_addr_list(); - sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); -} - /* Free the existing local addresses. */ -static void __sctp_free_local_addr_list(void) +static void sctp_free_local_addr_list(void) { struct sctp_sockaddr_entry *addr; struct list_head *pos, *temp; @@ -207,27 +192,15 @@ static void __sctp_free_local_addr_list(void) } } -/* Free the existing local addresses. */ -static void sctp_free_local_addr_list(void) -{ - unsigned long flags; - - sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); - __sctp_free_local_addr_list(); - sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); -} - /* Copy the local addresses which are valid for 'scope' into 'bp'. */ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, - int gfp, int copy_flags) + gfp_t gfp, int copy_flags) { struct sctp_sockaddr_entry *addr; int error = 0; - struct list_head *pos; - unsigned long flags; + struct list_head *pos, *temp; - sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); - list_for_each(pos, &sctp_local_addr_list) { + list_for_each_safe(pos, temp, &sctp_local_addr_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); if (sctp_in_scope(&addr->a, scope)) { /* Now that the address is in scope, check to see if @@ -239,7 +212,7 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, (((AF_INET6 == addr->a.sa.sa_family) && (copy_flags & SCTP_ADDR6_ALLOWED) && (copy_flags & SCTP_ADDR6_PEERSUPP)))) { - error = sctp_add_bind_addr(bp, &addr->a, + error = sctp_add_bind_addr(bp, &addr->a, 1, GFP_ATOMIC); if (error) goto end_copy; @@ -248,7 +221,6 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, } end_copy: - sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); return error; } @@ -257,7 +229,7 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, int is_saddr) { void *from; - __u16 *port; + __be16 *port; struct sctphdr *sh; port = &addr->v4.sin_port; @@ -265,10 +237,10 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, sh = (struct sctphdr *) skb->h.raw; if (is_saddr) { - *port = ntohs(sh->source); + *port = sh->source; from = &skb->nh.iph->saddr; } else { - *port = ntohs(sh->dest); + *port = sh->dest; from = &skb->nh.iph->daddr; } memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr)); @@ -278,7 +250,7 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb, 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_port = 0; addr->v4.sin_addr.s_addr = inet_sk(sk)->rcv_saddr; } @@ -297,7 +269,7 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) /* 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) + __be16 port, int iif) { addr->v4.sin_family = AF_INET; addr->v4.sin_port = port; @@ -313,7 +285,7 @@ static int sctp_v4_to_addr_param(const union sctp_addr *addr, 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.param_hdr.length = htons(length); param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; return length; @@ -321,7 +293,7 @@ static int sctp_v4_to_addr_param(const union sctp_addr *addr, /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, - unsigned short port) + __be16 port) { struct rtable *rt = (struct rtable *)dst; saddr->v4.sin_family = AF_INET; @@ -344,7 +316,7 @@ static int sctp_v4_cmp_addr(const union sctp_addr *addr1, } /* Initialize addr struct to INADDR_ANY. */ -static void sctp_v4_inaddr_any(union sctp_addr *addr, unsigned short port) +static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port) { addr->v4.sin_family = AF_INET; addr->v4.sin_addr.s_addr = INADDR_ANY; @@ -364,24 +336,33 @@ 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 1 - If the address is a unicast. */ -static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_opt *sp) +static int sctp_v4_addr_valid(union sctp_addr *addr, + struct sctp_sock *sp, + const struct sk_buff *skb) { /* Is this a non-unicast address or a unusable SCTP address? */ if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) return 0; + /* Is this a broadcast address? */ + if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST) + return 0; + return 1; } /* Should this be available for binding? */ -static int sctp_v4_available(union sctp_addr *addr, struct sctp_opt *sp) +static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) { 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) + if (addr->v4.sin_addr.s_addr != INADDR_ANY && + ret != RTN_LOCAL && + !sp->inet.freebind && + !sysctl_ip_nonlocal_bind) return 0; + return 1; } @@ -428,9 +409,9 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) * addresses. If an association is passed, trys to get a dst entry with a * source address that matches an address in the bind address list. */ -struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, - union sctp_addr *daddr, - union sctp_addr *saddr) +static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, + union sctp_addr *daddr, + union sctp_addr *saddr) { struct rtable *rt; struct flowi fl; @@ -476,7 +457,9 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); - sctp_v4_dst_saddr(&dst_saddr, dst, bp->port); + if (!laddr->use_as_src) + continue; + sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port)); if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) goto out_unlock; } @@ -496,7 +479,8 @@ struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, list_for_each(pos, &bp->address_list) { laddr = list_entry(pos, struct sctp_sockaddr_entry, list); - if (AF_INET == laddr->a.sa.sa_family) { + if ((laddr->use_as_src) && + (AF_INET == laddr->a.sa.sa_family)) { fl.fl4_src = laddr->a.v4.sin_addr.s_addr; if (!ip_route_output_key(&rt, &fl)) { dst = &rt->u.dst; @@ -520,16 +504,19 @@ out: /* For v4, the source address is cached in the route entry(dst). So no need * to cache it separately and hence this is an empty routine. */ -void sctp_v4_get_saddr(struct sctp_association *asoc, - struct dst_entry *dst, - union sctp_addr *daddr, - union sctp_addr *saddr) +static void sctp_v4_get_saddr(struct sctp_association *asoc, + struct dst_entry *dst, + union sctp_addr *daddr, + union sctp_addr *saddr) { struct rtable *rt = (struct rtable *)dst; + if (!asoc) + return; + if (rt) { saddr->v4.sin_family = AF_INET; - saddr->v4.sin_port = asoc->base.bind_addr.port; + saddr->v4.sin_port = htons(asoc->base.bind_addr.port); saddr->v4.sin_addr.s_addr = rt->rt_src; } } @@ -547,33 +534,29 @@ static int sctp_v4_is_ce(const struct sk_buff *skb) } /* Create and initialize a new sk for the socket returned by accept(). */ -struct sock *sctp_v4_create_accept_sk(struct sock *sk, - struct sctp_association *asoc) +static struct sock *sctp_v4_create_accept_sk(struct sock *sk, + struct sctp_association *asoc) { - struct sock *newsk; - struct inet_opt *inet = inet_sk(sk); - struct inet_opt *newinet; + struct inet_sock *inet = inet_sk(sk); + struct inet_sock *newinet; + struct sock *newsk = sk_alloc(PF_INET, GFP_KERNEL, sk->sk_prot, 1); - newsk = sk_alloc(PF_INET, GFP_KERNEL, sk->sk_prot->slab_obj_size, - sk->sk_prot->slab); if (!newsk) goto out; sock_init_data(NULL, newsk); - sk_set_owner(newsk, THIS_MODULE); newsk->sk_type = SOCK_STREAM; - newsk->sk_prot = sk->sk_prot; newsk->sk_no_check = sk->sk_no_check; newsk->sk_reuse = sk->sk_reuse; newsk->sk_shutdown = sk->sk_shutdown; newsk->sk_destruct = inet_sock_destruct; - newsk->sk_zapped = 0; newsk->sk_family = PF_INET; newsk->sk_protocol = IPPROTO_SCTP; newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; + sock_reset_flag(newsk, SOCK_ZAPPED); newinet = inet_sk(newsk); @@ -586,7 +569,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, newinet->dport = htons(asoc->peer.port); newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; newinet->pmtudisc = inet->pmtudisc; - newinet->id = 0; + newinet->id = asoc->next_tsn ^ jiffies; newinet->uc_ttl = -1; newinet->mc_loop = 1; @@ -594,9 +577,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, newinet->mc_index = 0; newinet->mc_list = NULL; -#ifdef INET_REFCNT_DEBUG - atomic_inc(&inet_sock_nr); -#endif + sk_refcnt_debug_inc(newsk); if (newsk->sk_prot->init(newsk)) { sk_common_release(newsk); @@ -608,7 +589,7 @@ out: } /* Map address, empty for v4 family */ -static void sctp_v4_addr_v4map(struct sctp_opt *sp, union sctp_addr *addr) +static void sctp_v4_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr) { /* Empty */ } @@ -619,18 +600,36 @@ static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) seq_printf(seq, "%d.%d.%d.%d ", NIPQUAD(addr->v4.sin_addr)); } -/* Event handler for inet address addition/deletion events. - * Basically, whenever there is an event, we re-build our local address list. - */ +/* Event handler for inet address addition/deletion events. */ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, void *ptr) { - unsigned long flags; + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct sctp_sockaddr_entry *addr; + struct list_head *pos, *temp; - sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); - __sctp_free_local_addr_list(); - __sctp_get_local_addr_list(); - sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); + switch (ev) { + case NETDEV_UP: + addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); + if (addr) { + addr->a.v4.sin_family = AF_INET; + addr->a.v4.sin_port = 0; + addr->a.v4.sin_addr.s_addr = ifa->ifa_local; + list_add_tail(&addr->list, &sctp_local_addr_list); + } + break; + case NETDEV_DOWN: + list_for_each_safe(pos, temp, &sctp_local_addr_list) { + addr = list_entry(pos, struct sctp_sockaddr_entry, list); + if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { + list_del(pos); + kfree(addr); + break; + } + } + + break; + } return NOTIFY_DONE; } @@ -639,7 +638,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, * Initialize the control inode/socket with a control endpoint data * structure. This endpoint is reserved exclusively for the OOTB processing. */ -int sctp_ctl_sock_init(void) +static int sctp_ctl_sock_init(void) { int err; sa_family_t family; @@ -745,7 +744,7 @@ static void sctp_inet_skb_msgname(struct sk_buff *skb, char *msgname, int *len) } /* Do we support this AF? */ -static int sctp_inet_af_supported(sa_family_t family, struct sctp_opt *sp) +static int sctp_inet_af_supported(sa_family_t family, struct sctp_sock *sp) { /* PF_INET only supports AF_INET addresses. */ return (AF_INET == family); @@ -754,7 +753,7 @@ static int sctp_inet_af_supported(sa_family_t family, struct sctp_opt *sp) /* Address matching with wildcards allowed. */ static int sctp_inet_cmp_addr(const union sctp_addr *addr1, const union sctp_addr *addr2, - struct sctp_opt *opt) + struct sctp_sock *opt) { /* PF_INET only supports AF_INET addresses. */ if (addr1->sa.sa_family != addr2->sa.sa_family) @@ -771,7 +770,7 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1, /* 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) +static int sctp_inet_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) { return sctp_v4_available(addr, opt); } @@ -779,7 +778,7 @@ static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr) /* Verify that sockaddr looks sendable. Common verification has already * been taken care of. */ -static int sctp_inet_send_verify(struct sctp_opt *opt, union sctp_addr *addr) +static int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr) { return 1; } @@ -787,8 +786,8 @@ static int sctp_inet_send_verify(struct sctp_opt *opt, union sctp_addr *addr) /* Fill in Supported Address Type information for INIT and INIT-ACK * chunks. Returns number of addresses supported. */ -static int sctp_inet_supported_addrs(const struct sctp_opt *opt, - __u16 *types) +static int sctp_inet_supported_addrs(const struct sctp_sock *opt, + __be16 *types) { types[0] = SCTP_PARAM_IPV4_ADDRESS; return 1; @@ -808,7 +807,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, return ip_queue_xmit(skb, ipfragok); } -struct sctp_af sctp_ipv4_specific; +static struct sctp_af sctp_ipv4_specific; static struct sctp_pf sctp_pf_inet = { .event_msgname = sctp_inet_event_msgname, @@ -824,30 +823,34 @@ static struct sctp_pf sctp_pf_inet = { }; /* Notifier for inetaddr addition/deletion events. */ -struct notifier_block sctp_inetaddr_notifier = { +static struct notifier_block sctp_inetaddr_notifier = { .notifier_call = sctp_inetaddr_event, }; /* Socket operations. */ -struct proto_ops inet_seqpacket_ops = { - .family = PF_INET, - .owner = THIS_MODULE, - .release = inet_release, /* Needs to be wrapped... */ - .bind = inet_bind, - .connect = inet_dgram_connect, - .socketpair = sock_no_socketpair, - .accept = inet_accept, - .getname = inet_getname, /* Semantics are different. */ - .poll = sctp_poll, - .ioctl = inet_ioctl, - .listen = sctp_inet_listen, - .shutdown = inet_shutdown, /* Looks harmless. */ - .setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem. */ - .getsockopt = sock_common_getsockopt, - .sendmsg = inet_sendmsg, - .recvmsg = sock_common_recvmsg, - .mmap = sock_no_mmap, - .sendpage = sock_no_sendpage, +static const struct proto_ops inet_seqpacket_ops = { + .family = PF_INET, + .owner = THIS_MODULE, + .release = inet_release, /* Needs to be wrapped... */ + .bind = inet_bind, + .connect = inet_dgram_connect, + .socketpair = sock_no_socketpair, + .accept = inet_accept, + .getname = inet_getname, /* Semantics are different. */ + .poll = sctp_poll, + .ioctl = inet_ioctl, + .listen = sctp_inet_listen, + .shutdown = inet_shutdown, /* Looks harmless. */ + .setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem */ + .getsockopt = sock_common_getsockopt, + .sendmsg = inet_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif }; /* Registration with AF_INET family. */ @@ -878,32 +881,36 @@ static struct net_protocol sctp_protocol = { }; /* IPv4 address related functions. */ -struct sctp_af sctp_ipv4_specific = { - .sctp_xmit = sctp_v4_xmit, - .setsockopt = ip_setsockopt, - .getsockopt = ip_getsockopt, - .get_dst = sctp_v4_get_dst, - .get_saddr = sctp_v4_get_saddr, - .copy_addrlist = sctp_v4_copy_addrlist, - .from_skb = sctp_v4_from_skb, - .from_sk = sctp_v4_from_sk, - .to_sk_saddr = sctp_v4_to_sk_saddr, - .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, - .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, - .skb_iif = sctp_v4_skb_iif, - .is_ce = sctp_v4_is_ce, - .seq_dump_addr = sctp_v4_seq_dump_addr, - .net_header_len = sizeof(struct iphdr), - .sockaddr_len = sizeof(struct sockaddr_in), - .sa_family = AF_INET, +static struct sctp_af sctp_ipv4_specific = { + .sa_family = AF_INET, + .sctp_xmit = sctp_v4_xmit, + .setsockopt = ip_setsockopt, + .getsockopt = ip_getsockopt, + .get_dst = sctp_v4_get_dst, + .get_saddr = sctp_v4_get_saddr, + .copy_addrlist = sctp_v4_copy_addrlist, + .from_skb = sctp_v4_from_skb, + .from_sk = sctp_v4_from_sk, + .to_sk_saddr = sctp_v4_to_sk_saddr, + .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, + .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, + .skb_iif = sctp_v4_skb_iif, + .is_ce = sctp_v4_is_ce, + .seq_dump_addr = sctp_v4_seq_dump_addr, + .net_header_len = sizeof(struct iphdr), + .sockaddr_len = sizeof(struct sockaddr_in), +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_ip_setsockopt, + .compat_getsockopt = compat_ip_getsockopt, +#endif }; struct sctp_pf *sctp_get_pf_specific(sa_family_t family) { @@ -959,7 +966,7 @@ static void cleanup_sctp_mibs(void) } /* Initialize the universe into something sensible. */ -__init int sctp_init(void) +SCTP_STATIC __init int sctp_init(void) { int i; int status = -EINVAL; @@ -970,7 +977,7 @@ __init int sctp_init(void) if (!sctp_sanity_check()) goto out; - status = sk_alloc_slab(&sctp_prot, "sctp_sock"); + status = proto_register(&sctp_prot, 1); if (status) goto out; @@ -1031,7 +1038,7 @@ __init int sctp_init(void) sctp_rto_beta = SCTP_RTO_BETA; /* Valid.Cookie.Life - 60 seconds */ - sctp_valid_cookie_life = 60 * HZ; + sctp_valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE; /* Whether Cookie Preservative is enabled(1) or not(0) */ sctp_cookie_preserve_enable = 1; @@ -1047,8 +1054,17 @@ __init int sctp_init(void) sctp_max_retrans_path = 5; sctp_max_retrans_init = 8; + /* Sendbuffer growth - do per-socket accounting */ + sctp_sndbuf_policy = 0; + + /* Rcvbuffer growth - do per-socket accounting */ + sctp_rcvbuf_policy = 0; + /* HB.interval - 30 seconds */ - sctp_hb_interval = 30 * HZ; + sctp_hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; + + /* delayed SACK timeout */ + sctp_sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK; /* Implementation specific variables. */ @@ -1084,7 +1100,7 @@ __init int sctp_init(void) goto err_ahash_alloc; } for (i = 0; i < sctp_assoc_hashsize; i++) { - sctp_assoc_hashtable[i].lock = RW_LOCK_UNLOCKED; + rwlock_init(&sctp_assoc_hashtable[i].lock); sctp_assoc_hashtable[i].chain = NULL; } @@ -1098,7 +1114,7 @@ __init int sctp_init(void) goto err_ehash_alloc; } for (i = 0; i < sctp_ep_hashsize; i++) { - sctp_ep_hashtable[i].lock = RW_LOCK_UNLOCKED; + rwlock_init(&sctp_ep_hashtable[i].lock); sctp_ep_hashtable[i].chain = NULL; } @@ -1117,11 +1133,11 @@ __init int sctp_init(void) goto err_bhash_alloc; } for (i = 0; i < sctp_port_hashsize; i++) { - sctp_port_hashtable[i].lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&sctp_port_hashtable[i].lock); sctp_port_hashtable[i].chain = NULL; } - sctp_port_alloc_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&sctp_port_alloc_lock); sctp_port_rover = sysctl_local_port_range[0] - 1; printk(KERN_INFO "SCTP: Hash tables configured " @@ -1152,19 +1168,16 @@ __init int sctp_init(void) /* Initialize the local address list. */ INIT_LIST_HEAD(&sctp_local_addr_list); - sctp_local_addr_lock = SPIN_LOCK_UNLOCKED; + + sctp_get_local_addr_list(); /* Register notifier for inet address additions/deletions. */ register_inetaddr_notifier(&sctp_inetaddr_notifier); - sctp_get_local_addr_list(); - __unsafe(THIS_MODULE); status = 0; out: return status; -err_add_protocol: - sk_free_slab(&sctp_prot); err_ctl_sock_init: sctp_v6_exit(); err_v6_init: @@ -1192,11 +1205,13 @@ err_bucket_cachep: inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); inet_unregister_protosw(&sctp_seqpacket_protosw); inet_unregister_protosw(&sctp_stream_protosw); +err_add_protocol: + proto_unregister(&sctp_prot); goto out; } /* Exit handler for the SCTP protocol. */ -__exit void sctp_exit(void) +SCTP_STATIC __exit void sctp_exit(void) { /* BUG. This should probably do something useful like clean * up all the remaining associations and all that memory. @@ -1233,12 +1248,17 @@ __exit void sctp_exit(void) inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); inet_unregister_protosw(&sctp_seqpacket_protosw); inet_unregister_protosw(&sctp_stream_protosw); - sk_free_slab(&sctp_prot); + proto_unregister(&sctp_prot); } module_init(sctp_init); module_exit(sctp_exit); +/* + * __stringify doesn't likes enums, so use IPPROTO_SCTP value (132) directly. + */ +MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132"); +MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132"); MODULE_AUTHOR("Linux Kernel SCTP developers "); MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)"); MODULE_LICENSE("GPL");