diff options
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r-- | net/sctp/protocol.c | 100 |
1 files changed, 48 insertions, 52 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index fac7674438a..3a3db56729c 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -79,8 +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 __read_mostly; -kmem_cache_t *sctp_bucket_cachep __read_mostly; +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) @@ -163,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; @@ -179,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; @@ -201,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, 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 @@ -242,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; } @@ -251,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; @@ -259,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)); @@ -272,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; } @@ -291,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; @@ -307,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; @@ -315,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; @@ -338,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; @@ -481,7 +459,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, list); if (!laddr->use_as_src) continue; - sctp_v4_dst_saddr(&dst_saddr, dst, bp->port); + sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port)); if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) goto out_unlock; } @@ -538,7 +516,7 @@ static void sctp_v4_get_saddr(struct sctp_association *asoc, 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; } } @@ -591,7 +569,7 @@ static 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; @@ -622,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. */ 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; } @@ -791,7 +787,7 @@ static int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr) * chunks. Returns number of addresses supported. */ static int sctp_inet_supported_addrs(const struct sctp_sock *opt, - __u16 *types) + __be16 *types) { types[0] = SCTP_PARAM_IPV4_ADDRESS; return 1; @@ -808,7 +804,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, NIPQUAD(((struct rtable *)skb->dst)->rt_dst)); SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); - return ip_queue_xmit(skb, ipfragok); + return ip_queue_xmit(skb, skb->sk, ipfragok); } static struct sctp_af sctp_ipv4_specific; @@ -1172,13 +1168,12 @@ SCTP_STATIC __init int sctp_init(void) /* 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); - sctp_get_local_addr_list(); - __unsafe(THIS_MODULE); status = 0; out: @@ -1263,6 +1258,7 @@ 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 <lksctp-developers@lists.sourceforge.net>"); MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)"); MODULE_LICENSE("GPL"); |