X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fsctp%2Fprotocol.c;h=0ec234b762c20f3a876e326017df3626a4ee9759;hb=44473d991332053eb3fea1e08f8a6ee2c6fb409c;hp=688546dccd828f0821736a301535049cc3d8ca04;hpb=4c1aa6f8b9686ddc7221f0f3b63f9b7dd1467543;p=linux-2.6 diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 688546dccd..0ec234b762 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -74,7 +74,7 @@ DEFINE_SPINLOCK(sctp_assocs_id_lock); * the Out-of-the-blue (OOTB) packets. A control sock will be created * for this socket at the initialization time. */ -static struct socket *sctp_ctl_socket; +static struct sock *sctp_ctl_sock; static struct sctp_pf *sctp_pf_inet6_specific; static struct sctp_pf *sctp_pf_inet_specific; @@ -91,7 +91,7 @@ int sysctl_sctp_wmem[3]; /* Return the address of the control sock. */ struct sock *sctp_get_ctl_sock(void) { - return sctp_ctl_socket->sk; + return sctp_ctl_sock; } /* Set up the proc fs entry for the SCTP protocol. */ @@ -337,14 +337,14 @@ static int sctp_v4_cmp_addr(const union sctp_addr *addr1, 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; + addr->v4.sin_addr.s_addr = htonl(INADDR_ANY); addr->v4.sin_port = port; } /* Is this a wildcard address? */ static int sctp_v4_is_any(const union sctp_addr *addr) { - return INADDR_ANY == addr->v4.sin_addr.s_addr; + return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr; } /* This function checks if the address is a valid address to be used for @@ -363,7 +363,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr, return 0; /* Is this a broadcast address? */ - if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST) + if (skb && skb->rtable->rt_flags & RTCF_BROADCAST) return 0; return 1; @@ -375,7 +375,7 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr); - if (addr->v4.sin_addr.s_addr != INADDR_ANY && + if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) && ret != RTN_LOCAL && !sp->inet.freebind && !sysctl_ip_nonlocal_bind) @@ -451,7 +451,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, fl.fl4_src = saddr->v4.sin_addr.s_addr; SCTP_DEBUG_PRINTK("%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - ", - __FUNCTION__, NIPQUAD(fl.fl4_dst), + __func__, NIPQUAD(fl.fl4_dst), NIPQUAD(fl.fl4_src)); if (!ip_route_output_key(&init_net, &rt, &fl)) { @@ -539,7 +539,7 @@ static void sctp_v4_get_saddr(struct sctp_association *asoc, /* What interface did this skb arrive on? */ static int sctp_v4_skb_iif(const struct sk_buff *skb) { - return ((struct rtable *)skb->dst)->rt_iif; + return skb->rtable->rt_iif; } /* Was this packet marked by Explicit Congestion Notification? */ @@ -554,7 +554,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk, { struct inet_sock *inet = inet_sk(sk); struct inet_sock *newinet; - struct sock *newsk = sk_alloc(sk->sk_net, PF_INET, GFP_KERNEL, + struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL, sk->sk_prot); if (!newsk) @@ -628,6 +628,10 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; struct sctp_sockaddr_entry *addr = NULL; struct sctp_sockaddr_entry *temp; + int found = 0; + + if (dev_net(ifa->ifa_dev->dev) != &init_net) + return NOTIFY_DONE; switch (ev) { case NETDEV_UP: @@ -646,14 +650,17 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, spin_lock_bh(&sctp_local_addr_lock); list_for_each_entry_safe(addr, temp, &sctp_local_addr_list, list) { - if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { + if (addr->a.sa.sa_family == AF_INET && + addr->a.v4.sin_addr.s_addr == + ifa->ifa_local) { + found = 1; addr->valid = 0; list_del_rcu(&addr->list); break; } } spin_unlock_bh(&sctp_local_addr_lock); - if (addr && !addr->valid) + if (found) call_rcu(&addr->rcu, sctp_local_addr_free); break; } @@ -675,16 +682,13 @@ static int sctp_ctl_sock_init(void) else family = PF_INET; - err = sock_create_kern(family, SOCK_SEQPACKET, IPPROTO_SCTP, - &sctp_ctl_socket); + err = inet_ctl_sock_create(&sctp_ctl_sock, family, + SOCK_SEQPACKET, IPPROTO_SCTP, &init_net); if (err < 0) { printk(KERN_ERR "SCTP: Failed to create the SCTP control socket.\n"); return err; } - sctp_ctl_socket->sk->sk_allocation = GFP_ATOMIC; - inet_sk(sctp_ctl_socket->sk)->uc_ttl = -1; - return 0; } @@ -783,8 +787,8 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1, /* PF_INET only supports AF_INET addresses. */ if (addr1->sa.sa_family != addr2->sa.sa_family) return 0; - if (INADDR_ANY == addr1->v4.sin_addr.s_addr || - INADDR_ANY == addr2->v4.sin_addr.s_addr) + if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr || + htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr) return 1; if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr) return 1; @@ -824,9 +828,9 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, { SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n", - __FUNCTION__, skb, skb->len, - NIPQUAD(((struct rtable *)skb->dst)->rt_src), - NIPQUAD(((struct rtable *)skb->dst)->rt_dst)); + __func__, skb, skb->len, + NIPQUAD(skb->rtable->rt_src), + NIPQUAD(skb->rtable->rt_dst)); SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); return ip_queue_xmit(skb, ipfragok); @@ -970,24 +974,66 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family) return 1; } -static int __init init_sctp_mibs(void) +static inline int init_sctp_mibs(void) { - sctp_statistics[0] = alloc_percpu(struct sctp_mib); - if (!sctp_statistics[0]) - return -ENOMEM; - sctp_statistics[1] = alloc_percpu(struct sctp_mib); - if (!sctp_statistics[1]) { - free_percpu(sctp_statistics[0]); - return -ENOMEM; - } + return snmp_mib_init((void**)sctp_statistics, sizeof(struct sctp_mib)); +} + +static inline void cleanup_sctp_mibs(void) +{ + snmp_mib_free((void**)sctp_statistics); +} + +static void sctp_v4_pf_init(void) +{ + /* Initialize the SCTP specific PF functions. */ + sctp_register_pf(&sctp_pf_inet, PF_INET); + sctp_register_af(&sctp_af_inet); +} + +static void sctp_v4_pf_exit(void) +{ + list_del(&sctp_af_inet.list); +} + +static int sctp_v4_protosw_init(void) +{ + int rc; + + rc = proto_register(&sctp_prot, 1); + if (rc) + return rc; + + /* Register SCTP(UDP and TCP style) with socket layer. */ + inet_register_protosw(&sctp_seqpacket_protosw); + inet_register_protosw(&sctp_stream_protosw); + return 0; +} +static void sctp_v4_protosw_exit(void) +{ + inet_unregister_protosw(&sctp_stream_protosw); + inet_unregister_protosw(&sctp_seqpacket_protosw); + proto_unregister(&sctp_prot); } -static void cleanup_sctp_mibs(void) +static int sctp_v4_add_protocol(void) { - free_percpu(sctp_statistics[0]); - free_percpu(sctp_statistics[1]); + /* Register notifier for inet address additions/deletions. */ + register_inetaddr_notifier(&sctp_inetaddr_notifier); + + /* Register SCTP with inet layer. */ + if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) + return -EAGAIN; + + return 0; +} + +static void sctp_v4_del_protocol(void) +{ + inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); + unregister_inetaddr_notifier(&sctp_inetaddr_notifier); } /* Initialize the universe into something sensible. */ @@ -1033,8 +1079,6 @@ SCTP_STATIC __init int sctp_init(void) /* Initialize object count debugging. */ sctp_dbg_objcnt_init(); - /* Initialize the SCTP specific PF functions. */ - sctp_register_pf(&sctp_pf_inet, PF_INET); /* * 14. Suggested SCTP Protocol Parameter Values */ @@ -1192,19 +1236,22 @@ SCTP_STATIC __init int sctp_init(void) sctp_sysctl_register(); INIT_LIST_HEAD(&sctp_address_families); - sctp_register_af(&sctp_af_inet); + sctp_v4_pf_init(); + sctp_v6_pf_init(); - status = proto_register(&sctp_prot, 1); - if (status) - goto err_proto_register; + /* Initialize the local address list. */ + INIT_LIST_HEAD(&sctp_local_addr_list); + spin_lock_init(&sctp_local_addr_lock); + sctp_get_local_addr_list(); - /* Register SCTP(UDP and TCP style) with socket layer. */ - inet_register_protosw(&sctp_seqpacket_protosw); - inet_register_protosw(&sctp_stream_protosw); + status = sctp_v4_protosw_init(); - status = sctp_v6_init(); if (status) - goto err_v6_init; + goto err_protosw_init; + + status = sctp_v6_protosw_init(); + if (status) + goto err_v6_protosw_init; /* Initialize the control inode/socket for handling OOTB packets. */ if ((status = sctp_ctl_sock_init())) { @@ -1213,19 +1260,9 @@ SCTP_STATIC __init int sctp_init(void) goto err_ctl_sock_init; } - /* Initialize the local address list. */ - INIT_LIST_HEAD(&sctp_local_addr_list); - spin_lock_init(&sctp_local_addr_lock); - sctp_get_local_addr_list(); - - /* Register notifier for inet address additions/deletions. */ - register_inetaddr_notifier(&sctp_inetaddr_notifier); - - /* Register SCTP with inet layer. */ - if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) { - status = -EAGAIN; + status = sctp_v4_add_protocol(); + if (status) goto err_add_protocol; - } /* Register SCTP with inet6 layer. */ status = sctp_v6_add_protocol(); @@ -1236,18 +1273,18 @@ SCTP_STATIC __init int sctp_init(void) out: return status; err_v6_add_protocol: - inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); - unregister_inetaddr_notifier(&sctp_inetaddr_notifier); + sctp_v6_del_protocol(); err_add_protocol: - sctp_free_local_addr_list(); - sock_release(sctp_ctl_socket); + sctp_v4_del_protocol(); + inet_ctl_sock_destroy(sctp_ctl_sock); err_ctl_sock_init: - sctp_v6_exit(); -err_v6_init: - inet_unregister_protosw(&sctp_stream_protosw); - inet_unregister_protosw(&sctp_seqpacket_protosw); - proto_unregister(&sctp_prot); -err_proto_register: + sctp_v6_protosw_exit(); +err_v6_protosw_init: + sctp_v4_protosw_exit(); +err_protosw_init: + sctp_free_local_addr_list(); + sctp_v4_pf_exit(); + sctp_v6_pf_exit(); sctp_sysctl_unregister(); list_del(&sctp_af_inet.list); free_pages((unsigned long)sctp_port_hashtable, @@ -1280,23 +1317,21 @@ SCTP_STATIC __exit void sctp_exit(void) /* Unregister with inet6/inet layers. */ sctp_v6_del_protocol(); - inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); + sctp_v4_del_protocol(); - /* Unregister notifier for inet address additions/deletions. */ - unregister_inetaddr_notifier(&sctp_inetaddr_notifier); + /* Free the control endpoint. */ + inet_ctl_sock_destroy(sctp_ctl_sock); + + /* Free protosw registrations */ + sctp_v6_protosw_exit(); + sctp_v4_protosw_exit(); /* Free the local address list. */ sctp_free_local_addr_list(); - /* Free the control endpoint. */ - sock_release(sctp_ctl_socket); - - /* Cleanup v6 initializations. */ - sctp_v6_exit(); - /* Unregister with socket layer. */ - inet_unregister_protosw(&sctp_stream_protosw); - inet_unregister_protosw(&sctp_seqpacket_protosw); + sctp_v6_pf_exit(); + sctp_v4_pf_exit(); sctp_sysctl_unregister(); list_del(&sctp_af_inet.list); @@ -1315,8 +1350,6 @@ SCTP_STATIC __exit void sctp_exit(void) kmem_cache_destroy(sctp_chunk_cachep); kmem_cache_destroy(sctp_bucket_cachep); - - proto_unregister(&sctp_prot); } module_init(sctp_init);