Blame view

net/sctp/protocol.c 43 KB
47505b8bc   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
60c778b25   Vlad Yasevich   [SCTP]: Stop clai...
2
  /* SCTP kernel implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
8
9
   * (C) Copyright IBM Corp. 2001, 2004
   * Copyright (c) 1999-2000 Cisco, Inc.
   * Copyright (c) 1999-2001 Motorola, Inc.
   * Copyright (c) 2001 Intel Corp.
   * Copyright (c) 2001 Nokia, Inc.
   * Copyright (c) 2001 La Monte H.P. Yarroll
   *
60c778b25   Vlad Yasevich   [SCTP]: Stop clai...
10
   * This file is part of the SCTP kernel implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
   *
   * Initialization/cleanup for SCTP protocol support.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
   * Please send any bug reports or fixes you make to the
   * email address(es):
91705c61b   Daniel Borkmann   net: sctp: trivia...
16
   *    lksctp developers <linux-sctp@vger.kernel.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
   * 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>
   *    Ardelle Fan <ardelle.fan@intel.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
   */
145ce502e   Joe Perches   net/sctp: Use pr_...
26
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/netdevice.h>
  #include <linux/inetdevice.h>
  #include <linux/seq_file.h>
57c8a661d   Mike Rapoport   mm: remove includ...
32
  #include <linux/memblock.h>
845525a64   Vlad Yasevich   sctp: Update sctp...
33
34
  #include <linux/highmem.h>
  #include <linux/swap.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
35
  #include <linux/slab.h>
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
36
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
  #include <net/protocol.h>
  #include <net/ip.h>
  #include <net/ipv6.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
40
  #include <net/route.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
  #include <net/sctp/sctp.h>
  #include <net/addrconf.h>
  #include <net/inet_common.h>
  #include <net/inet_ecn.h>
d9749fb59   Neil Horman   sctp: Fix port ha...
45
  #define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  /* Global data structures. */
4cbf1cae9   Brian Haley   [SCTP]: Change gl...
47
  struct sctp_globals sctp_globals __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
  
  struct idr sctp_assocs_id;
  DEFINE_SPINLOCK(sctp_assocs_id_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
  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;
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
55
56
  struct kmem_cache *sctp_chunk_cachep __read_mostly;
  struct kmem_cache *sctp_bucket_cachep __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

8d987e5c7   Eric Dumazet   net: avoid limits...
58
  long sysctl_sctp_mem[3];
007e3936b   Vlad Yasevich   [SCTP]: Move sysc...
59
60
  int sysctl_sctp_rmem[3];
  int sysctl_sctp_wmem[3];
4d93df0ab   Neil Horman   [SCTP]: Rewrite o...
61

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
64
65
66
67
68
69
70
71
72
  /* Private helper to extract ipv4 address and stash them in
   * the protocol structure.
   */
  static void sctp_v4_copy_addrlist(struct list_head *addrlist,
  				  struct net_device *dev)
  {
  	struct in_device *in_dev;
  	struct in_ifaddr *ifa;
  	struct sctp_sockaddr_entry *addr;
  
  	rcu_read_lock();
e5ed63991   Herbert Xu   [IPV4]: Replace _...
73
  	if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
  		rcu_read_unlock();
  		return;
  	}
cd5a411db   Florian Westphal   net: use new in_d...
77
  	in_dev_for_each_ifa_rcu(ifa, in_dev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  		/* Add the address to the local list.  */
939cfa75a   Daniel Borkmann   net: sctp: get ri...
79
  		addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  		if (addr) {
2a6fd78ad   Al Viro   [SCTP] embedded s...
81
  			addr->a.v4.sin_family = AF_INET;
2a6fd78ad   Al Viro   [SCTP] embedded s...
82
  			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
83
84
  			addr->valid = 1;
  			INIT_LIST_HEAD(&addr->list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
88
89
90
91
92
93
94
  			list_add_tail(&addr->list, addrlist);
  		}
  	}
  
  	rcu_read_unlock();
  }
  
  /* Extract our IP addresses from the system and stash them in the
   * protocol structure.
   */
4db67e808   Eric W. Biederman   sctp: Make the ad...
95
  static void sctp_get_local_addr_list(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
  {
  	struct net_device *dev;
  	struct list_head *pos;
  	struct sctp_af *af;
c6d14c845   Eric Dumazet   net: Introduce fo...
100
  	rcu_read_lock();
4db67e808   Eric W. Biederman   sctp: Make the ad...
101
  	for_each_netdev_rcu(net, dev) {
2c0740e4e   Dave Jones   sctp: Convert __l...
102
  		list_for_each(pos, &sctp_address_families) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  			af = list_entry(pos, struct sctp_af, list);
4db67e808   Eric W. Biederman   sctp: Make the ad...
104
  			af->copy_addrlist(&net->sctp.local_addr_list, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  		}
  	}
c6d14c845   Eric Dumazet   net: Introduce fo...
107
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  /* Free the existing local addresses.  */
4db67e808   Eric W. Biederman   sctp: Make the ad...
110
  static void sctp_free_local_addr_list(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
  {
  	struct sctp_sockaddr_entry *addr;
  	struct list_head *pos, *temp;
4db67e808   Eric W. Biederman   sctp: Make the ad...
114
  	list_for_each_safe(pos, temp, &net->sctp.local_addr_list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
119
  		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
  		list_del(pos);
  		kfree(addr);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  /* Copy the local addresses which are valid for 'scope' into 'bp'.  */
4db67e808   Eric W. Biederman   sctp: Make the ad...
121
  int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
1c662018d   Xin Long   sctp: remove the ...
122
  			      enum sctp_scope scope, gfp_t gfp, int copy_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
  {
  	struct sctp_sockaddr_entry *addr;
2e3ce5bc2   Xin Long   sctp: set sin_por...
125
  	union sctp_addr laddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127

293035479   Vlad Yasevich   [SCTP]: Add RCU s...
128
  	rcu_read_lock();
4db67e808   Eric W. Biederman   sctp: Make the ad...
129
  	list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
130
131
  		if (!addr->valid)
  			continue;
165f2cf64   Xin Long   sctp: reduce inde...
132
133
134
135
136
137
138
139
  		if (!sctp_in_scope(net, &addr->a, scope))
  			continue;
  
  		/* Now that the address is in scope, check to see if
  		 * the address type is really supported by the local
  		 * sock as well as the remote peer.
  		 */
  		if (addr->a.sa.sa_family == AF_INET &&
471e39df9   Marcelo Ricardo Leitner   sctp: Don't adver...
140
141
  		    (!(copy_flags & SCTP_ADDR4_ALLOWED) ||
  		     !(copy_flags & SCTP_ADDR4_PEERSUPP)))
165f2cf64   Xin Long   sctp: reduce inde...
142
143
144
145
146
  			continue;
  		if (addr->a.sa.sa_family == AF_INET6 &&
  		    (!(copy_flags & SCTP_ADDR6_ALLOWED) ||
  		     !(copy_flags & SCTP_ADDR6_PEERSUPP)))
  			continue;
2e3ce5bc2   Xin Long   sctp: set sin_por...
147
148
149
150
  		laddr = addr->a;
  		/* also works for setting ipv6 address port */
  		laddr.v4.sin_port = htons(bp->port);
  		if (sctp_bind_addr_state(bp, &laddr) != -1)
b8607805d   Xin Long   sctp: not copying...
151
  			continue;
165f2cf64   Xin Long   sctp: reduce inde...
152
153
154
155
  		error = sctp_add_bind_addr(bp, &addr->a, sizeof(addr->a),
  					   SCTP_ADDR_SRC, GFP_ATOMIC);
  		if (error)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  	}
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
157
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  	return error;
  }
b7e10c25b   Richard Haines   sctp: Add ip opti...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  /* Copy over any ip options */
  static void sctp_v4_copy_ip_options(struct sock *sk, struct sock *newsk)
  {
  	struct inet_sock *newinet, *inet = inet_sk(sk);
  	struct ip_options_rcu *inet_opt, *newopt = NULL;
  
  	newinet = inet_sk(newsk);
  
  	rcu_read_lock();
  	inet_opt = rcu_dereference(inet->inet_opt);
  	if (inet_opt) {
  		newopt = sock_kmalloc(newsk, sizeof(*inet_opt) +
  				      inet_opt->opt.optlen, GFP_ATOMIC);
  		if (newopt)
  			memcpy(newopt, inet_opt, sizeof(*inet_opt) +
  			       inet_opt->opt.optlen);
  		else
  			pr_err("%s: Failed to copy ip options
  ", __func__);
  	}
  	RCU_INIT_POINTER(newinet->inet_opt, newopt);
  	rcu_read_unlock();
  }
  
  /* Account for the IP options */
  static int sctp_v4_ip_options_len(struct sock *sk)
  {
  	struct inet_sock *inet = inet_sk(sk);
  	struct ip_options_rcu *inet_opt;
  	int len = 0;
  
  	rcu_read_lock();
  	inet_opt = rcu_dereference(inet->inet_opt);
  	if (inet_opt)
  		len = inet_opt->opt.optlen;
  
  	rcu_read_unlock();
  	return len;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
  /* 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)
  {
0630c56e4   Marcelo Ricardo Leitner   sctp: simplify ad...
203
204
205
  	/* Always called on head skb, so this is safe */
  	struct sctphdr *sh = sctp_hdr(skb);
  	struct sockaddr_in *sa = &addr->v4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  	addr->v4.sin_family = AF_INET;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  	if (is_saddr) {
0630c56e4   Marcelo Ricardo Leitner   sctp: simplify ad...
209
210
  		sa->sin_port = sh->source;
  		sa->sin_addr.s_addr = ip_hdr(skb)->saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  	} else {
0630c56e4   Marcelo Ricardo Leitner   sctp: simplify ad...
212
213
  		sa->sin_port = sh->dest;
  		sa->sin_addr.s_addr = ip_hdr(skb)->daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  	}
b6f3320b1   Xin Long   sctp: fully initi...
215
  	memset(sa->sin_zero, 0, sizeof(sa->sin_zero));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
221
  }
  
  /* 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;
7dcdbd957   Al Viro   [SCTP]: Don't bot...
222
  	addr->v4.sin_port = 0;
c720c7e83   Eric Dumazet   inet: rename some...
223
  	addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr;
b6f3320b1   Xin Long   sctp: fully initi...
224
  	memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
  }
  
  /* Initialize sk->sk_rcv_saddr from sctp_addr. */
  static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
  {
c720c7e83   Eric Dumazet   inet: rename some...
230
  	inet_sk(sk)->inet_rcv_saddr = addr->v4.sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
  }
  
  /* Initialize sk->sk_daddr from sctp_addr. */
  static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
  {
c720c7e83   Eric Dumazet   inet: rename some...
236
  	inet_sk(sk)->inet_daddr = addr->v4.sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
  }
  
  /* Initialize a sctp_addr from an address parameter. */
  static void sctp_v4_from_addr_param(union sctp_addr *addr,
  				    union sctp_addr_param *param,
dd86d136f   Al Viro   [SCTP]: Switch ->...
242
  				    __be16 port, int iif)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
  {
  	addr->v4.sin_family = AF_INET;
  	addr->v4.sin_port = port;
  	addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
b6f3320b1   Xin Long   sctp: fully initi...
247
  	memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
249
250
251
252
253
254
255
  }
  
  /* Initialize an address parameter from a sctp_addr and return the length
   * of the address parameter.
   */
  static int sctp_v4_to_addr_param(const union sctp_addr *addr,
  				 union sctp_addr_param *param)
  {
a38905e6a   Xin Long   sctp: remove the ...
256
  	int length = sizeof(struct sctp_ipv4addr_param);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
  
  	param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
dbc16db1e   Al Viro   [SCTP]: Trivial s...
259
  	param->v4.param_hdr.length = htons(length);
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
260
  	param->v4.addr.s_addr = addr->v4.sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
  
  	return length;
  }
  
  /* Initialize a sctp_addr from a dst_entry. */
18a353f42   David S. Miller   sctp: Use flowi4'...
266
  static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4,
854d43a46   Al Viro   [SCTP]: Annotate ...
267
  			      __be16 port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  	saddr->v4.sin_family = AF_INET;
  	saddr->v4.sin_port = port;
18a353f42   David S. Miller   sctp: Use flowi4'...
271
  	saddr->v4.sin_addr.s_addr = fl4->saddr;
b6f3320b1   Xin Long   sctp: fully initi...
272
  	memset(saddr->v4.sin_zero, 0, sizeof(saddr->v4.sin_zero));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  }
  
  /* Compare two addresses exactly. */
  static int sctp_v4_cmp_addr(const union sctp_addr *addr1,
  			    const union sctp_addr *addr2)
  {
  	if (addr1->sa.sa_family != addr2->sa.sa_family)
  		return 0;
  	if (addr1->v4.sin_port != addr2->v4.sin_port)
  		return 0;
  	if (addr1->v4.sin_addr.s_addr != addr2->v4.sin_addr.s_addr)
  		return 0;
  
  	return 1;
  }
  
  /* Initialize addr struct to INADDR_ANY. */
6fbfa9f95   Al Viro   [SCTP]: Annotate ...
290
  static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
  {
  	addr->v4.sin_family = AF_INET;
e6f1cebf7   Al Viro   [NET] endianness ...
293
  	addr->v4.sin_addr.s_addr = htonl(INADDR_ANY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
  	addr->v4.sin_port = port;
b6f3320b1   Xin Long   sctp: fully initi...
295
  	memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
  }
  
  /* Is this a wildcard address? */
  static int sctp_v4_is_any(const union sctp_addr *addr)
  {
e6f1cebf7   Al Viro   [NET] endianness ...
301
  	return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
305
306
307
308
309
310
  }
  
  /* This function checks if the address is a valid address to be used for
   * SCTP binding.
   *
   * Output:
   * Return 0 - If the address is a non-unicast or an illegal address.
   * Return 1 - If the address is a unicast.
   */
5636bef73   Vlad Yasevich   [SCTP]: Reject sc...
311
312
313
  static int sctp_v4_addr_valid(union sctp_addr *addr,
  			      struct sctp_sock *sp,
  			      const struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
  {
7dab83de5   Vlad Yasevich   sctp: Support ipv...
315
316
317
  	/* IPv4 addresses not allowed */
  	if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  	/* Is this a non-unicast address or a unusable SCTP address? */
b5cb2bbc4   Joe Perches   [IPV4] sctp: Use ...
319
  	if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  		return 0;
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
321
  	/* Is this a broadcast address? */
511c3f92a   Eric Dumazet   net: skb->rtable ...
322
  	if (skb && skb_rtable(skb)->rt_flags & RTCF_BROADCAST)
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
323
  		return 0;
5636bef73   Vlad Yasevich   [SCTP]: Reject sc...
324

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
329
330
  	return 1;
  }
  
  /* Should this be available for binding?   */
  static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
  {
bb2db45b5   Eric W. Biederman   sctp: Enable sctp...
331
332
  	struct net *net = sock_net(&sp->inet.sk);
  	int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334

e6f1cebf7   Al Viro   [NET] endianness ...
335
  	if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
cdac4e077   Neil Horman   [SCTP] Add suppor...
336
337
  	   ret != RTN_LOCAL &&
  	   !sp->inet.freebind &&
49a601589   Vincent Bernat   net/ipv4: bind ip...
338
  	   !net->ipv4.sysctl_ip_nonlocal_bind)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  		return 0;
cdac4e077   Neil Horman   [SCTP] Add suppor...
340

7dab83de5   Vlad Yasevich   sctp: Support ipv...
341
342
  	if (ipv6_only_sock(sctp_opt2sk(sp)))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
347
348
349
350
351
352
353
354
355
  	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>.
   *
   * Level 0 - unusable SCTP addresses
   * Level 1 - loopback address
   * Level 2 - link-local addresses
   * Level 3 - private addresses.
   * Level 4 - global addresses
   * For INIT and INIT-ACK address list, let L be the level of
93c3216a7   Randy Dunlap   net: sctp: protoc...
356
   * requested destination address, sender and receiver
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
   * SHOULD include all of its addresses with level greater
   * than or equal to L.
723884339   Bhaskar Dutta   sctp: Sysctl conf...
359
360
361
   *
   * IPv4 scoping can be controlled through sysctl option
   * net.sctp.addr_scope_policy
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
   */
1c662018d   Xin Long   sctp: remove the ...
363
  static enum sctp_scope sctp_v4_scope(union sctp_addr *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
  {
1c662018d   Xin Long   sctp: remove the ...
365
  	enum sctp_scope retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
  	/* Check for unusable SCTP addresses. */
b5cb2bbc4   Joe Perches   [IPV4] sctp: Use ...
368
  	if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  		retval =  SCTP_SCOPE_UNUSABLE;
b5cb2bbc4   Joe Perches   [IPV4] sctp: Use ...
370
  	} else if (ipv4_is_loopback(addr->v4.sin_addr.s_addr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
  		retval = SCTP_SCOPE_LOOPBACK;
b5cb2bbc4   Joe Perches   [IPV4] sctp: Use ...
372
  	} else if (ipv4_is_linklocal_169(addr->v4.sin_addr.s_addr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  		retval = SCTP_SCOPE_LINK;
b5cb2bbc4   Joe Perches   [IPV4] sctp: Use ...
374
375
376
  	} else if (ipv4_is_private_10(addr->v4.sin_addr.s_addr) ||
  		   ipv4_is_private_172(addr->v4.sin_addr.s_addr) ||
  		   ipv4_is_private_192(addr->v4.sin_addr.s_addr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
379
380
381
382
383
384
385
386
387
388
  		retval = SCTP_SCOPE_PRIVATE;
  	} else {
  		retval = SCTP_SCOPE_GLOBAL;
  	}
  
  	return retval;
  }
  
  /* Returns a valid dst cache entry for the given source and destination ip
   * 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.
   */
da0420bee   Vlad Yasevich   sctp: clean up ro...
389
390
  static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
  				struct flowi *fl, struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  {
da0420bee   Vlad Yasevich   sctp: clean up ro...
392
  	struct sctp_association *asoc = t->asoc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  	struct rtable *rt;
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
394
395
  	struct flowi _fl;
  	struct flowi4 *fl4 = &_fl.u.ip4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  	struct sctp_bind_addr *bp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  	struct sctp_sockaddr_entry *laddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
  	struct dst_entry *dst = NULL;
da0420bee   Vlad Yasevich   sctp: clean up ro...
399
  	union sctp_addr *daddr = &t->ipaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
  	union sctp_addr dst_saddr;
8a9c58d28   Xin Long   sctp: add support...
401
  	__u8 tos = inet_sk(sk)->tos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402

8a9c58d28   Xin Long   sctp: add support...
403
404
  	if (t->dscp & SCTP_DSCP_SET_MASK)
  		tos = t->dscp & SCTP_DSCP_VAL_MASK;
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
405
  	memset(&_fl, 0x0, sizeof(_fl));
9914ae3ca   Vlad Yasevich   sctp: cache the i...
406
407
408
  	fl4->daddr  = daddr->v4.sin_addr.s_addr;
  	fl4->fl4_dport = daddr->v4.sin_port;
  	fl4->flowi4_proto = IPPROTO_SCTP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
  	if (asoc) {
8a9c58d28   Xin Long   sctp: add support...
410
  		fl4->flowi4_tos = RT_CONN_FLAGS_TOS(asoc->base.sk, tos);
9914ae3ca   Vlad Yasevich   sctp: cache the i...
411
412
  		fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if;
  		fl4->fl4_sport = htons(asoc->base.bind_addr.port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
  	}
6429d3dc4   Wei Yongjun   sctp: missing set...
414
  	if (saddr) {
9914ae3ca   Vlad Yasevich   sctp: cache the i...
415
  		fl4->saddr = saddr->v4.sin_addr.s_addr;
ecf938fe7   Xin Long   sctp: set flow sp...
416
417
  		if (!fl4->fl4_sport)
  			fl4->fl4_sport = saddr->v4.sin_port;
6429d3dc4   Wei Yongjun   sctp: missing set...
418
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419

bb33381d0   Daniel Borkmann   net: sctp: rework...
420
421
  	pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr,
  		 &fl4->saddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422

bb2db45b5   Eric W. Biederman   sctp: Enable sctp...
423
  	rt = ip_route_output_key(sock_net(sk), fl4);
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
424
  	if (!IS_ERR(rt)) {
d8d1f30b9   Changli Gao   net-next: remove ...
425
  		dst = &rt->dst;
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
426
427
428
  		t->dst = dst;
  		memcpy(fl, &_fl, sizeof(_fl));
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
433
434
435
436
  
  	/* If there is no association or if a source address is passed, no
  	 * more validation is required.
  	 */
  	if (!asoc || saddr)
  		goto out;
  
  	bp = &asoc->base.bind_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
439
440
441
  
  	if (dst) {
  		/* Walk through the bind address list and look for a bind
  		 * address that matches the source address of the returned dst.
  		 */
18a353f42   David S. Miller   sctp: Use flowi4'...
442
  		sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port));
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
443
444
  		rcu_read_lock();
  		list_for_each_entry_rcu(laddr, &bp->address_list, list) {
8a07eb0a5   Michio Honda   sctp: Add ASCONF ...
445
446
447
  			if (!laddr->valid || (laddr->state == SCTP_ADDR_DEL) ||
  			    (laddr->state != SCTP_ADDR_SRC &&
  			    !asoc->src_out_of_asoc_ok))
dc022a987   Sridhar Samudrala   [SCTP]: ADDIP: Do...
448
  				continue;
854d43a46   Al Viro   [SCTP]: Annotate ...
449
  			if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
  				goto out_unlock;
  		}
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
452
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
459
460
461
462
463
  
  		/* None of the bound addresses match the source address of the
  		 * dst. So release it.
  		 */
  		dst_release(dst);
  		dst = NULL;
  	}
  
  	/* Walk through the bind address list and try to get a dst that
  	 * matches a bind address as the source address.
  	 */
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
464
465
  	rcu_read_lock();
  	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
0ca50d12f   Marcelo Ricardo Leitner   sctp: fix src add...
466
  		struct net_device *odev;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
467
468
  		if (!laddr->valid)
  			continue;
07868284e   Marcelo Ricardo Leitner   sctp: reduce inde...
469
470
471
472
473
474
475
  		if (laddr->state != SCTP_ADDR_SRC ||
  		    AF_INET != laddr->a.sa.sa_family)
  			continue;
  
  		fl4->fl4_sport = laddr->a.v4.sin_port;
  		flowi4_update_output(fl4,
  				     asoc->base.sk->sk_bound_dev_if,
8a9c58d28   Xin Long   sctp: add support...
476
  				     RT_CONN_FLAGS_TOS(asoc->base.sk, tos),
07868284e   Marcelo Ricardo Leitner   sctp: reduce inde...
477
478
479
480
481
482
  				     daddr->v4.sin_addr.s_addr,
  				     laddr->a.v4.sin_addr.s_addr);
  
  		rt = ip_route_output_key(sock_net(sk), fl4);
  		if (IS_ERR(rt))
  			continue;
0ca50d12f   Marcelo Ricardo Leitner   sctp: fix src add...
483
484
485
486
487
  		/* Ensure the src address belongs to the output
  		 * interface.
  		 */
  		odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr,
  				     false);
d82f0f1fc   Marcelo Ricardo Leitner   sctp: fix dst leak
488
  		if (!odev || odev->ifindex != fl4->flowi4_oif) {
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
489
  			if (!dst) {
4a31a6b19   Tommi Rantala   sctp: fix dst ref...
490
  				dst = &rt->dst;
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
491
492
493
  				t->dst = dst;
  				memcpy(fl, &_fl, sizeof(_fl));
  			} else {
410f03831   Marcelo Ricardo Leitner   sctp: add routing...
494
  				dst_release(&rt->dst);
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
495
  			}
0ca50d12f   Marcelo Ricardo Leitner   sctp: fix src add...
496
  			continue;
d82f0f1fc   Marcelo Ricardo Leitner   sctp: fix dst leak
497
  		}
0ca50d12f   Marcelo Ricardo Leitner   sctp: fix src add...
498

4a31a6b19   Tommi Rantala   sctp: fix dst ref...
499
  		dst_release(dst);
07868284e   Marcelo Ricardo Leitner   sctp: reduce inde...
500
  		dst = &rt->dst;
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
501
502
  		t->dst = dst;
  		memcpy(fl, &_fl, sizeof(_fl));
07868284e   Marcelo Ricardo Leitner   sctp: reduce inde...
503
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
  	}
  
  out_unlock:
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
507
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
  out:
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
509
  	if (dst) {
bb33381d0   Daniel Borkmann   net: sctp: rework...
510
511
  		pr_debug("rt_dst:%pI4, rt_src:%pI4
  ",
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
512
513
514
  			 &fl->u.ip4.daddr, &fl->u.ip4.saddr);
  	} else {
  		t->dst = NULL;
bb33381d0   Daniel Borkmann   net: sctp: rework...
515
516
  		pr_debug("no route
  ");
582eea230   Marcelo Ricardo Leitner   sctp: fix possibl...
517
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
521
522
  }
  
  /* 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.
   */
e51171019   YOSHIFUJI Hideaki   [SCTP]: Fix NULL ...
523
  static void sctp_v4_get_saddr(struct sctp_sock *sk,
9914ae3ca   Vlad Yasevich   sctp: cache the i...
524
  			      struct sctp_transport *t,
9914ae3ca   Vlad Yasevich   sctp: cache the i...
525
  			      struct flowi *fl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
  {
9914ae3ca   Vlad Yasevich   sctp: cache the i...
527
528
  	union sctp_addr *saddr = &t->saddr;
  	struct rtable *rt = (struct rtable *)t->dst;
23ec47a08   Vladislav Yasevich   [SCTP]: Fix poten...
529

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
  	if (rt) {
  		saddr->v4.sin_family = AF_INET;
902ebd3e0   David S. Miller   sctp: Remove rt->...
532
  		saddr->v4.sin_addr.s_addr = fl->u.ip4.saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
535
536
537
538
  	}
  }
  
  /* What interface did this skb arrive on? */
  static int sctp_v4_skb_iif(const struct sk_buff *skb)
  {
92101b3b2   David S. Miller   ipv4: Prepare for...
539
  	return inet_iif(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
543
544
  }
  
  /* Was this packet marked by Explicit Congestion Notification? */
  static int sctp_v4_is_ce(const struct sk_buff *skb)
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
545
  	return INET_ECN_is_ce(ip_hdr(skb)->tos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
549
  }
  
  /* Create and initialize a new sk for the socket returned by accept(). */
  static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
cdfbabfb2   David Howells   net: Work around ...
550
551
  					     struct sctp_association *asoc,
  					     bool kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
553
  	struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL,
cdfbabfb2   David Howells   net: Work around ...
554
  			sk->sk_prot, kern);
914e1c8b6   Vlad Yasevich   sctp: Inherit all...
555
  	struct inet_sock *newinet;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
558
559
560
  
  	if (!newsk)
  		goto out;
  
  	sock_init_data(NULL, newsk);
914e1c8b6   Vlad Yasevich   sctp: Inherit all...
561
  	sctp_copy_sock(newsk, sk, asoc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  	sock_reset_flag(newsk, SOCK_ZAPPED);
b7e10c25b   Richard Haines   sctp: Add ip opti...
563
  	sctp_v4_copy_ip_options(sk, newsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  	newinet = inet_sk(newsk);
c720c7e83   Eric Dumazet   inet: rename some...
565
  	newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566

e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
567
  	sk_refcnt_debug_inc(newsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
570
571
572
573
574
575
576
  
  	if (newsk->sk_prot->init(newsk)) {
  		sk_common_release(newsk);
  		newsk = NULL;
  	}
  
  out:
  	return newsk;
  }
299ee123e   Jason Gunthorpe   sctp: Fixup v4map...
577
  static int sctp_v4_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
  {
299ee123e   Jason Gunthorpe   sctp: Fixup v4map...
579
  	/* No address mapping for V4 sockets */
09279e615   Xin Long   sctp: initialize ...
580
  	memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
299ee123e   Jason Gunthorpe   sctp: Fixup v4map...
581
  	return sizeof(struct sockaddr_in);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
585
586
  }
  
  /* Dump the v4 addr to the seq file. */
  static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
  {
21454aaad   Harvey Harrison   net: replace NIPQ...
587
  	seq_printf(seq, "%pI4 ", &addr->v4.sin_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
  }
b9031d9d8   Vlad Yasevich   sctp: Fix ECN mar...
589
590
591
592
  static void sctp_v4_ecn_capable(struct sock *sk)
  {
  	INET_ECN_xmit(sk);
  }
9c3b57518   Kees Cook   net: sctp: Conver...
593
  static void sctp_addr_wq_timeout_handler(struct timer_list *t)
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
594
  {
9c3b57518   Kees Cook   net: sctp: Conver...
595
  	struct net *net = from_timer(net, t, sctp.addr_wq_timer);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
596
597
  	struct sctp_sockaddr_entry *addrw, *temp;
  	struct sctp_sock *sp;
4db67e808   Eric W. Biederman   sctp: Make the ad...
598
  	spin_lock_bh(&net->sctp.addr_wq_lock);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
599

4db67e808   Eric W. Biederman   sctp: Make the ad...
600
  	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
bb33381d0   Daniel Borkmann   net: sctp: rework...
601
602
603
604
  		pr_debug("%s: the first ent in wq:%p is addr:%pISc for cmd:%d at "
  			 "entry:%p
  ", __func__, &net->sctp.addr_waitq, &addrw->a.sa,
  			 addrw->state, addrw);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
605

dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
606
  #if IS_ENABLED(CONFIG_IPV6)
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
607
608
609
610
611
612
613
614
615
616
  		/* Now we send an ASCONF for each association */
  		/* Note. we currently don't handle link local IPv6 addressees */
  		if (addrw->a.sa.sa_family == AF_INET6) {
  			struct in6_addr *in6;
  
  			if (ipv6_addr_type(&addrw->a.v6.sin6_addr) &
  			    IPV6_ADDR_LINKLOCAL)
  				goto free_next;
  
  			in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
4db67e808   Eric W. Biederman   sctp: Make the ad...
617
  			if (ipv6_chk_addr(net, in6, NULL, 0) == 0 &&
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
618
619
  			    addrw->state == SCTP_ADDR_NEW) {
  				unsigned long timeo_val;
bb33381d0   Daniel Borkmann   net: sctp: rework...
620
621
622
623
  				pr_debug("%s: this is on DAD, trying %d sec "
  					 "later
  ", __func__,
  					 SCTP_ADDRESS_TICK_DELAY);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
624
625
  				timeo_val = jiffies;
  				timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
4db67e808   Eric W. Biederman   sctp: Make the ad...
626
  				mod_timer(&net->sctp.addr_wq_timer, timeo_val);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
627
628
629
  				break;
  			}
  		}
5d0c90cf4   David S. Miller   sctp: Guard IPV6 ...
630
  #endif
4db67e808   Eric W. Biederman   sctp: Make the ad...
631
  		list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) {
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
632
633
634
635
636
637
  			struct sock *sk;
  
  			sk = sctp_opt2sk(sp);
  			/* ignore bound-specific endpoints */
  			if (!sctp_is_ep_boundall(sk))
  				continue;
5bc1d1b4a   wangweidong   sctp: remove macr...
638
  			bh_lock_sock(sk);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
639
  			if (sctp_asconf_mgmt(sp, addrw) < 0)
bb33381d0   Daniel Borkmann   net: sctp: rework...
640
641
  				pr_debug("%s: sctp_asconf_mgmt failed
  ", __func__);
5bc1d1b4a   wangweidong   sctp: remove macr...
642
  			bh_unlock_sock(sk);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
643
  		}
39d84a58a   Daniel Halperin   sctp: fix warning...
644
  #if IS_ENABLED(CONFIG_IPV6)
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
645
  free_next:
39d84a58a   Daniel Halperin   sctp: fix warning...
646
  #endif
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
647
648
649
  		list_del(&addrw->list);
  		kfree(addrw);
  	}
4db67e808   Eric W. Biederman   sctp: Make the ad...
650
  	spin_unlock_bh(&net->sctp.addr_wq_lock);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
651
  }
4db67e808   Eric W. Biederman   sctp: Make the ad...
652
  static void sctp_free_addr_wq(struct net *net)
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
653
654
655
  {
  	struct sctp_sockaddr_entry *addrw;
  	struct sctp_sockaddr_entry *temp;
4db67e808   Eric W. Biederman   sctp: Make the ad...
656
657
658
  	spin_lock_bh(&net->sctp.addr_wq_lock);
  	del_timer(&net->sctp.addr_wq_timer);
  	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
659
660
661
  		list_del(&addrw->list);
  		kfree(addrw);
  	}
4db67e808   Eric W. Biederman   sctp: Make the ad...
662
  	spin_unlock_bh(&net->sctp.addr_wq_lock);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
663
664
665
666
667
  }
  
  /* lookup the entry for the same address in the addr_waitq
   * sctp_addr_wq MUST be locked
   */
4db67e808   Eric W. Biederman   sctp: Make the ad...
668
669
  static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net,
  					struct sctp_sockaddr_entry *addr)
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
670
671
  {
  	struct sctp_sockaddr_entry *addrw;
4db67e808   Eric W. Biederman   sctp: Make the ad...
672
  	list_for_each_entry(addrw, &net->sctp.addr_waitq, list) {
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
673
674
675
676
677
678
679
680
681
682
683
684
685
686
  		if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
  			continue;
  		if (addrw->a.sa.sa_family == AF_INET) {
  			if (addrw->a.v4.sin_addr.s_addr ==
  			    addr->a.v4.sin_addr.s_addr)
  				return addrw;
  		} else if (addrw->a.sa.sa_family == AF_INET6) {
  			if (ipv6_addr_equal(&addrw->a.v6.sin6_addr,
  			    &addr->a.v6.sin6_addr))
  				return addrw;
  		}
  	}
  	return NULL;
  }
4db67e808   Eric W. Biederman   sctp: Make the ad...
687
  void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd)
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
688
689
690
691
692
693
694
695
696
  {
  	struct sctp_sockaddr_entry *addrw;
  	unsigned long timeo_val;
  
  	/* first, we check if an opposite message already exist in the queue.
  	 * If we found such message, it is removed.
  	 * This operation is a bit stupid, but the DHCP client attaches the
  	 * new address after a couple of addition and deletion of that address
  	 */
4db67e808   Eric W. Biederman   sctp: Make the ad...
697
  	spin_lock_bh(&net->sctp.addr_wq_lock);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
698
  	/* Offsets existing events in addr_wq */
4db67e808   Eric W. Biederman   sctp: Make the ad...
699
  	addrw = sctp_addr_wq_lookup(net, addr);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
700
701
  	if (addrw) {
  		if (addrw->state != cmd) {
bb33381d0   Daniel Borkmann   net: sctp: rework...
702
703
704
705
  			pr_debug("%s: offsets existing entry for %d, addr:%pISc "
  				 "in wq:%p
  ", __func__, addrw->state, &addrw->a.sa,
  				 &net->sctp.addr_waitq);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
706
707
708
  			list_del(&addrw->list);
  			kfree(addrw);
  		}
4db67e808   Eric W. Biederman   sctp: Make the ad...
709
  		spin_unlock_bh(&net->sctp.addr_wq_lock);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
710
711
712
713
714
715
  		return;
  	}
  
  	/* OK, we have to add the new address to the wait queue */
  	addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
  	if (addrw == NULL) {
4db67e808   Eric W. Biederman   sctp: Make the ad...
716
  		spin_unlock_bh(&net->sctp.addr_wq_lock);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
717
718
719
  		return;
  	}
  	addrw->state = cmd;
4db67e808   Eric W. Biederman   sctp: Make the ad...
720
  	list_add_tail(&addrw->list, &net->sctp.addr_waitq);
bb33381d0   Daniel Borkmann   net: sctp: rework...
721
722
723
724
  
  	pr_debug("%s: add new entry for cmd:%d, addr:%pISc in wq:%p
  ",
  		 __func__, addrw->state, &addrw->a.sa, &net->sctp.addr_waitq);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
725

4db67e808   Eric W. Biederman   sctp: Make the ad...
726
  	if (!timer_pending(&net->sctp.addr_wq_timer)) {
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
727
728
  		timeo_val = jiffies;
  		timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
4db67e808   Eric W. Biederman   sctp: Make the ad...
729
  		mod_timer(&net->sctp.addr_wq_timer, timeo_val);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
730
  	}
4db67e808   Eric W. Biederman   sctp: Make the ad...
731
  	spin_unlock_bh(&net->sctp.addr_wq_lock);
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
732
  }
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
733
734
735
736
737
738
  /* Event handler for inet address addition/deletion events.
   * The sctp_local_addr_list needs to be protocted by a spin lock since
   * multiple notifiers (say IPv4 and IPv6) may be running at the same
   * time and thus corrupt the list.
   * The reader side is protected with RCU.
   */
24123186f   Adrian Bunk   [SCTP]: make 2 fu...
739
740
  static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
  			       void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  {
29c7cf961   Sridhar Samudrala   [SCTP]: Handle ad...
742
  	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
743
744
  	struct sctp_sockaddr_entry *addr = NULL;
  	struct sctp_sockaddr_entry *temp;
4db67e808   Eric W. Biederman   sctp: Make the ad...
745
  	struct net *net = dev_net(ifa->ifa_dev->dev);
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
746
  	int found = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747

29c7cf961   Sridhar Samudrala   [SCTP]: Handle ad...
748
749
  	switch (ev) {
  	case NETDEV_UP:
400b8b9a2   Xin Long   sctp: allocate sc...
750
  		addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
29c7cf961   Sridhar Samudrala   [SCTP]: Handle ad...
751
752
  		if (addr) {
  			addr->a.v4.sin_family = AF_INET;
29c7cf961   Sridhar Samudrala   [SCTP]: Handle ad...
753
  			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
754
  			addr->valid = 1;
4db67e808   Eric W. Biederman   sctp: Make the ad...
755
756
757
758
  			spin_lock_bh(&net->sctp.local_addr_lock);
  			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
  			sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
  			spin_unlock_bh(&net->sctp.local_addr_lock);
29c7cf961   Sridhar Samudrala   [SCTP]: Handle ad...
759
760
761
  		}
  		break;
  	case NETDEV_DOWN:
4db67e808   Eric W. Biederman   sctp: Make the ad...
762
  		spin_lock_bh(&net->sctp.local_addr_lock);
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
763
  		list_for_each_entry_safe(addr, temp,
4db67e808   Eric W. Biederman   sctp: Make the ad...
764
  					&net->sctp.local_addr_list, list) {
a40a7d15b   Pavel Emelyanov   [SCTP]: IPv4 vs I...
765
766
767
  			if (addr->a.sa.sa_family == AF_INET &&
  					addr->a.v4.sin_addr.s_addr ==
  					ifa->ifa_local) {
4db67e808   Eric W. Biederman   sctp: Make the ad...
768
  				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
769
  				found = 1;
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
770
771
  				addr->valid = 0;
  				list_del_rcu(&addr->list);
29c7cf961   Sridhar Samudrala   [SCTP]: Handle ad...
772
773
774
  				break;
  			}
  		}
4db67e808   Eric W. Biederman   sctp: Make the ad...
775
  		spin_unlock_bh(&net->sctp.local_addr_lock);
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
776
  		if (found)
1231f0baa   Lai Jiangshan   net,rcu: convert ...
777
  			kfree_rcu(addr, rcu);
29c7cf961   Sridhar Samudrala   [SCTP]: Handle ad...
778
779
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780
781
782
783
784
785
786
787
  
  	return NOTIFY_DONE;
  }
  
  /*
   * Initialize the control inode/socket with a control endpoint data
   * structure.  This endpoint is reserved exclusively for the OOTB processing.
   */
2ce955035   Eric W. Biederman   sctp: Make the ct...
788
  static int sctp_ctl_sock_init(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
790
  {
  	int err;
fb13d9f9e   Brian Haley   SCTP: change sctp...
791
  	sa_family_t family = PF_INET;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
794
  
  	if (sctp_get_pf_specific(PF_INET6))
  		family = PF_INET6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795

2ce955035   Eric W. Biederman   sctp: Make the ct...
796
797
  	err = inet_ctl_sock_create(&net->sctp.ctl_sock, family,
  				   SOCK_SEQPACKET, IPPROTO_SCTP, net);
fb13d9f9e   Brian Haley   SCTP: change sctp...
798
799
800
  
  	/* If IPv6 socket could not be created, try the IPv4 socket */
  	if (err < 0 && family == PF_INET6)
2ce955035   Eric W. Biederman   sctp: Make the ct...
801
  		err = inet_ctl_sock_create(&net->sctp.ctl_sock, AF_INET,
fb13d9f9e   Brian Haley   SCTP: change sctp...
802
  					   SOCK_SEQPACKET, IPPROTO_SCTP,
2ce955035   Eric W. Biederman   sctp: Make the ct...
803
  					   net);
fb13d9f9e   Brian Haley   SCTP: change sctp...
804

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
  	if (err < 0) {
145ce502e   Joe Perches   net/sctp: Use pr_...
806
807
  		pr_err("Failed to create the SCTP control socket
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
809
  		return err;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
  	return 0;
  }
  
  /* Register address family specific functions. */
  int sctp_register_af(struct sctp_af *af)
  {
  	switch (af->sa_family) {
  	case AF_INET:
  		if (sctp_af_v4_specific)
  			return 0;
  		sctp_af_v4_specific = af;
  		break;
  	case AF_INET6:
  		if (sctp_af_v6_specific)
  			return 0;
  		sctp_af_v6_specific = af;
  		break;
  	default:
  		return 0;
  	}
  
  	INIT_LIST_HEAD(&af->list);
  	list_add_tail(&af->list, &sctp_address_families);
  	return 1;
  }
  
  /* Get the table of functions for manipulating a particular address
   * family.
   */
  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;
  	}
  }
  
  /* Common code to initialize a AF_INET msg_name. */
  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(struct sctp_ulpevent *event, char *msgname,
  				    int *addr_len)
  {
  	struct sockaddr_in *sin, *sinfrom;
  
  	if (msgname) {
  		struct sctp_association *asoc;
  
  		asoc = event->asoc;
  		sctp_inet_msgname(msgname, addr_len);
  		sin = (struct sockaddr_in *)msgname;
  		sinfrom = &asoc->peer.primary_addr.v4;
  		sin->sin_port = htons(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 *len)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
  	if (msgname) {
2c0fd387b   Arnaldo Carvalho de Melo   [SCTP]: Introduce...
884
885
  		struct sctphdr *sh = sctp_hdr(skb);
  		struct sockaddr_in *sin = (struct sockaddr_in *)msgname;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
  		sctp_inet_msgname(msgname, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
  		sin->sin_port = sh->source;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
888
  		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
891
892
893
894
895
  	}
  }
  
  /* Do we support this AF? */
  static int sctp_inet_af_supported(sa_family_t family, struct sctp_sock *sp)
  {
  	/* PF_INET only supports AF_INET addresses. */
a02cec215   Eric Dumazet   net: return opera...
896
  	return AF_INET == family;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
901
902
903
904
905
906
  }
  
  /* Address matching with wildcards allowed. */
  static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
  			      const union sctp_addr *addr2,
  			      struct sctp_sock *opt)
  {
  	/* PF_INET only supports AF_INET addresses. */
  	if (addr1->sa.sa_family != addr2->sa.sa_family)
  		return 0;
e6f1cebf7   Al Viro   [NET] endianness ...
907
908
  	if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr ||
  	    htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
  		return 1;
  	if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr)
  		return 1;
  
  	return 0;
  }
  
  /* Verify that provided sockaddr looks bindable.  Common verification has
   * already been taken care of.
   */
  static int sctp_inet_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
  {
  	return sctp_v4_available(addr, opt);
  }
  
  /* Verify that sockaddr looks sendable.  Common verification has already
   * been taken care of.
   */
  static int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
  {
  	return 1;
  }
  
  /* 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_sock *opt,
3dbe86566   Al Viro   [SCTP]: Annotate ...
936
  				     __be16 *types)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
938
939
940
941
942
943
  {
  	types[0] = SCTP_PARAM_IPV4_ADDRESS;
  	return 1;
  }
  
  /* Wrapper routine that calls the ip transmit routine. */
  static inline int sctp_v4_xmit(struct sk_buff *skb,
f880374c2   Herbert Xu   sctp: Drop ipfarg...
944
  			       struct sctp_transport *transport)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945
  {
f880374c2   Herbert Xu   sctp: Drop ipfarg...
946
  	struct inet_sock *inet = inet_sk(skb->sk);
8a9c58d28   Xin Long   sctp: add support...
947
  	__u8 dscp = inet->tos;
f880374c2   Herbert Xu   sctp: Drop ipfarg...
948

bb33381d0   Daniel Borkmann   net: sctp: rework...
949
950
  	pr_debug("%s: skb:%p, len:%d, src:%pI4, dst:%pI4
  ", __func__, skb,
8a9c58d28   Xin Long   sctp: add support...
951
952
953
954
955
  		 skb->len, &transport->fl.u.ip4.saddr,
  		 &transport->fl.u.ip4.daddr);
  
  	if (transport->dscp & SCTP_DSCP_SET_MASK)
  		dscp = transport->dscp & SCTP_DSCP_VAL_MASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956

f880374c2   Herbert Xu   sctp: Drop ipfarg...
957
958
  	inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ?
  			 IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
b01a24078   Eric W. Biederman   sctp: Make the mi...
959
  	SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS);
bb33381d0   Daniel Borkmann   net: sctp: rework...
960

8a9c58d28   Xin Long   sctp: add support...
961
  	return __ip_queue_xmit(&inet->sk, skb, &transport->fl, dscp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
  }
15efbe763   Neil Horman   [SCTP]: Clean up ...
963
  static struct sctp_af sctp_af_inet;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
965
966
967
968
969
970
971
972
973
  
  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,
  	.send_verify   = sctp_inet_send_verify,
  	.supported_addrs = sctp_inet_supported_addrs,
  	.create_accept_sk = sctp_v4_create_accept_sk,
299ee123e   Jason Gunthorpe   sctp: Fixup v4map...
974
975
976
  	.addr_to_user  = sctp_v4_addr_to_user,
  	.to_sk_saddr   = sctp_v4_to_sk_saddr,
  	.to_sk_daddr   = sctp_v4_to_sk_daddr,
b7e10c25b   Richard Haines   sctp: Add ip opti...
977
  	.copy_ip_options = sctp_v4_copy_ip_options,
15efbe763   Neil Horman   [SCTP]: Clean up ...
978
  	.af            = &sctp_af_inet
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
980
981
982
983
984
985
986
  };
  
  /* Notifier for inetaddr addition/deletion events.  */
  static struct notifier_block sctp_inetaddr_notifier = {
  	.notifier_call = sctp_inetaddr_event,
  };
  
  /* Socket operations.  */
90ddc4f04   Eric Dumazet   [NET]: move struc...
987
  static const struct proto_ops inet_seqpacket_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
988
989
990
991
  	.family		   = PF_INET,
  	.owner		   = THIS_MODULE,
  	.release	   = inet_release,	/* Needs to be wrapped... */
  	.bind		   = inet_bind,
644fbdeac   Xin Long   sctp: fix the iss...
992
  	.connect	   = sctp_inet_connect,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
993
994
995
  	.socketpair	   = sock_no_socketpair,
  	.accept		   = inet_accept,
  	.getname	   = inet_getname,	/* Semantics are different.  */
a11e1d432   Linus Torvalds   Revert changes to...
996
  	.poll		   = sctp_poll,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
997
  	.ioctl		   = inet_ioctl,
c7cbdbf29   Arnd Bergmann   net: rework SIOCG...
998
  	.gettstamp	   = sock_gettstamp,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
999
1000
1001
1002
1003
  	.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,
fd2d180a2   Xin Long   sctp: use inet_re...
1004
  	.recvmsg	   = inet_recvmsg,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1005
1006
  	.mmap		   = sock_no_mmap,
  	.sendpage	   = sock_no_sendpage,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
1009
1010
1011
1012
1013
1014
  };
  
  /* Registration with AF_INET family.  */
  static struct inet_protosw sctp_seqpacket_protosw = {
  	.type       = SOCK_SEQPACKET,
  	.protocol   = IPPROTO_SCTP,
  	.prot       = &sctp_prot,
  	.ops        = &inet_seqpacket_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
1018
1019
1020
1021
  	.flags      = SCTP_PROTOSW_FLAG
  };
  static struct inet_protosw sctp_stream_protosw = {
  	.type       = SOCK_STREAM,
  	.protocol   = IPPROTO_SCTP,
  	.prot       = &sctp_prot,
  	.ops        = &inet_seqpacket_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
1024
1025
  	.flags      = SCTP_PROTOSW_FLAG
  };
  
  /* Register with IP layer.  */
32613090a   Alexey Dobriyan   net: constify str...
1026
  static const struct net_protocol sctp_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
1028
1029
  	.handler     = sctp_rcv,
  	.err_handler = sctp_v4_err,
  	.no_policy   = 1,
bb2db45b5   Eric W. Biederman   sctp: Enable sctp...
1030
  	.netns_ok    = 1,
8ed1dc44d   Hannes Frederic Sowa   ipv4: introduce h...
1031
  	.icmp_strict_tag_validation = 1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
1033
1034
  };
  
  /* IPv4 address related functions.  */
15efbe763   Neil Horman   [SCTP]: Clean up ...
1035
  static struct sctp_af sctp_af_inet = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1036
1037
1038
1039
1040
1041
1042
1043
1044
  	.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,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1045
1046
  	.from_addr_param   = sctp_v4_from_addr_param,
  	.to_addr_param	   = sctp_v4_to_addr_param,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1047
1048
1049
1050
1051
1052
1053
1054
1055
  	.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,
b9031d9d8   Vlad Yasevich   sctp: Fix ECN mar...
1056
  	.ecn_capable	   = sctp_v4_ecn_capable,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1057
1058
  	.net_header_len	   = sizeof(struct iphdr),
  	.sockaddr_len	   = sizeof(struct sockaddr_in),
b7e10c25b   Richard Haines   sctp: Add ip opti...
1059
  	.ip_options_len	   = sctp_v4_ip_options_len,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
  };
8d72651d8   wangweidong   sctp: fix checkpa...
1061
1062
  struct sctp_pf *sctp_get_pf_specific(sa_family_t family)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
  	switch (family) {
  	case PF_INET:
  		return sctp_pf_inet_specific;
  	case PF_INET6:
  		return sctp_pf_inet6_specific;
  	default:
  		return NULL;
  	}
  }
  
  /* 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:
  		return 0;
  	}
  	return 1;
  }
b01a24078   Eric W. Biederman   sctp: Make the mi...
1092
  static inline int init_sctp_mibs(struct net *net)
996b1dbad   YOSHIFUJI Hideaki   [SCTP]: Use snmp_...
1093
  {
698365fa1   WANG Cong   net: clean up snm...
1094
1095
1096
1097
  	net->sctp.sctp_statistics = alloc_percpu(struct sctp_mib);
  	if (!net->sctp.sctp_statistics)
  		return -ENOMEM;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1098
  }
b01a24078   Eric W. Biederman   sctp: Make the mi...
1099
  static inline void cleanup_sctp_mibs(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
  {
698365fa1   WANG Cong   net: clean up snm...
1101
  	free_percpu(net->sctp.sctp_statistics);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1102
  }
270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
  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 int sctp_v4_add_protocol(void)
  {
  	/* 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);
  }
8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1154
  static int __net_init sctp_defaults_init(struct net *net)
4db67e808   Eric W. Biederman   sctp: Make the ad...
1155
  {
2ce955035   Eric W. Biederman   sctp: Make the ct...
1156
  	int status;
e1fc3b14f   Eric W. Biederman   sctp: Make sysctl...
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
  	/*
  	 * 14. Suggested SCTP Protocol Parameter Values
  	 */
  	/* The following protocol parameters are RECOMMENDED:  */
  	/* RTO.Initial              - 3  seconds */
  	net->sctp.rto_initial			= SCTP_RTO_INITIAL;
  	/* RTO.Min                  - 1  second */
  	net->sctp.rto_min	 		= SCTP_RTO_MIN;
  	/* RTO.Max                 -  60 seconds */
  	net->sctp.rto_max 			= SCTP_RTO_MAX;
  	/* RTO.Alpha                - 1/8 */
  	net->sctp.rto_alpha			= SCTP_RTO_ALPHA;
  	/* RTO.Beta                 - 1/4 */
  	net->sctp.rto_beta			= SCTP_RTO_BETA;
  
  	/* Valid.Cookie.Life        - 60  seconds */
  	net->sctp.valid_cookie_life		= SCTP_DEFAULT_COOKIE_LIFE;
  
  	/* Whether Cookie Preservative is enabled(1) or not(0) */
  	net->sctp.cookie_preserve_enable 	= 1;
3c68198e7   Neil Horman   sctp: Make hmac a...
1177
  	/* Default sctp sockets to use md5 as their hmac alg */
0d0863b02   Neil Horman   sctp: Change defa...
1178
  #if defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5)
3c68198e7   Neil Horman   sctp: Make hmac a...
1179
  	net->sctp.sctp_hmac_alg			= "md5";
0d0863b02   Neil Horman   sctp: Change defa...
1180
  #elif defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1)
3c68198e7   Neil Horman   sctp: Make hmac a...
1181
1182
1183
1184
  	net->sctp.sctp_hmac_alg			= "sha1";
  #else
  	net->sctp.sctp_hmac_alg			= NULL;
  #endif
e1fc3b14f   Eric W. Biederman   sctp: Make sysctl...
1185
1186
  	/* Max.Burst		    - 4 */
  	net->sctp.max_burst			= SCTP_DEFAULT_MAX_BURST;
34515e94c   Xin Long   sctp: add support...
1187
1188
  	/* Disable of Primary Path Switchover by default */
  	net->sctp.ps_retrans = SCTP_PS_RETRANS_MAX;
566178f85   Zhu Yanjun   net: sctp: dynami...
1189
1190
  	/* Enable pf state by default */
  	net->sctp.pf_enable = 1;
aef587be4   Xin Long   sctp: add pf_expo...
1191
1192
  	/* Ignore pf exposure feature by default */
  	net->sctp.pf_expose = SCTP_PF_EXPOSE_UNSET;
e1fc3b14f   Eric W. Biederman   sctp: Make sysctl...
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
  	/* Association.Max.Retrans  - 10 attempts
  	 * Path.Max.Retrans         - 5  attempts (per destination address)
  	 * Max.Init.Retransmits     - 8  attempts
  	 */
  	net->sctp.max_retrans_association	= 10;
  	net->sctp.max_retrans_path		= 5;
  	net->sctp.max_retrans_init		= 8;
  
  	/* Sendbuffer growth	    - do per-socket accounting */
  	net->sctp.sndbuf_policy			= 0;
  
  	/* Rcvbuffer growth	    - do per-socket accounting */
  	net->sctp.rcvbuf_policy			= 0;
  
  	/* HB.interval              - 30 seconds */
  	net->sctp.hb_interval			= SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
  
  	/* delayed SACK timeout */
  	net->sctp.sack_timeout			= SCTP_DEFAULT_TIMEOUT_SACK;
  
  	/* Disable ADDIP by default. */
  	net->sctp.addip_enable = 0;
  	net->sctp.addip_noauth = 0;
  	net->sctp.default_auto_asconf = 0;
  
  	/* Enable PR-SCTP by default. */
  	net->sctp.prsctp_enable = 1;
c28445c3c   Xin Long   sctp: add reconf_...
1220
1221
  	/* Disable RECONF by default. */
  	net->sctp.reconf_enable = 0;
e1fc3b14f   Eric W. Biederman   sctp: Make sysctl...
1222
1223
  	/* Disable AUTH by default. */
  	net->sctp.auth_enable = 0;
1b0b8114b   Xin Long   sctp: make ecn fl...
1224
1225
  	/* Enable ECN by default. */
  	net->sctp.ecn_enable = 1;
e1fc3b14f   Eric W. Biederman   sctp: Make sysctl...
1226
1227
1228
1229
1230
1231
1232
1233
  	/* Set SCOPE policy to enabled */
  	net->sctp.scope_policy = SCTP_SCOPE_POLICY_ENABLE;
  
  	/* Set the default rwnd update threshold */
  	net->sctp.rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT;
  
  	/* Initialize maximum autoclose timeout. */
  	net->sctp.max_autoclose		= INT_MAX / HZ;
ebb7e95d9   Eric W. Biederman   sctp: Add infrast...
1234
1235
1236
  	status = sctp_sysctl_net_register(net);
  	if (status)
  		goto err_sysctl_register;
b01a24078   Eric W. Biederman   sctp: Make the mi...
1237
1238
1239
1240
  	/* Allocate and initialise sctp mibs.  */
  	status = init_sctp_mibs(net);
  	if (status)
  		goto err_init_mibs;
d47d08c8c   Al Viro   sctp: use proc_re...
1241
  #ifdef CONFIG_PROC_FS
13d782f6b   Eric W. Biederman   sctp: Make the pr...
1242
1243
1244
1245
  	/* Initialize proc fs directory.  */
  	status = sctp_proc_init(net);
  	if (status)
  		goto err_init_proc;
d47d08c8c   Al Viro   sctp: use proc_re...
1246
  #endif
13d782f6b   Eric W. Biederman   sctp: Make the pr...
1247
1248
  
  	sctp_dbg_objcnt_init(net);
4db67e808   Eric W. Biederman   sctp: Make the ad...
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  	/* Initialize the local address list. */
  	INIT_LIST_HEAD(&net->sctp.local_addr_list);
  	spin_lock_init(&net->sctp.local_addr_lock);
  	sctp_get_local_addr_list(net);
  
  	/* Initialize the address event list */
  	INIT_LIST_HEAD(&net->sctp.addr_waitq);
  	INIT_LIST_HEAD(&net->sctp.auto_asconf_splist);
  	spin_lock_init(&net->sctp.addr_wq_lock);
  	net->sctp.addr_wq_timer.expires = 0;
9c3b57518   Kees Cook   net: sctp: Conver...
1259
  	timer_setup(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler, 0);
4db67e808   Eric W. Biederman   sctp: Make the ad...
1260
1261
  
  	return 0;
2ce955035   Eric W. Biederman   sctp: Make the ct...
1262

7ae665f13   Arnd Bergmann   sctp: fix unused ...
1263
  #ifdef CONFIG_PROC_FS
13d782f6b   Eric W. Biederman   sctp: Make the pr...
1264
  err_init_proc:
b01a24078   Eric W. Biederman   sctp: Make the mi...
1265
  	cleanup_sctp_mibs(net);
7ae665f13   Arnd Bergmann   sctp: fix unused ...
1266
  #endif
b01a24078   Eric W. Biederman   sctp: Make the mi...
1267
  err_init_mibs:
ebb7e95d9   Eric W. Biederman   sctp: Add infrast...
1268
1269
  	sctp_sysctl_net_unregister(net);
  err_sysctl_register:
2ce955035   Eric W. Biederman   sctp: Make the ct...
1270
  	return status;
4db67e808   Eric W. Biederman   sctp: Make the ad...
1271
  }
8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1272
  static void __net_exit sctp_defaults_exit(struct net *net)
4db67e808   Eric W. Biederman   sctp: Make the ad...
1273
1274
1275
1276
  {
  	/* Free the local address list */
  	sctp_free_addr_wq(net);
  	sctp_free_local_addr_list(net);
2ce955035   Eric W. Biederman   sctp: Make the ct...
1277

d47d08c8c   Al Viro   sctp: use proc_re...
1278
1279
1280
1281
  #ifdef CONFIG_PROC_FS
  	remove_proc_subtree("sctp", net->proc_net);
  	net->sctp.proc_net_sctp = NULL;
  #endif
b01a24078   Eric W. Biederman   sctp: Make the mi...
1282
  	cleanup_sctp_mibs(net);
ebb7e95d9   Eric W. Biederman   sctp: Add infrast...
1283
  	sctp_sysctl_net_unregister(net);
4db67e808   Eric W. Biederman   sctp: Make the ad...
1284
  }
8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
  static struct pernet_operations sctp_defaults_ops = {
  	.init = sctp_defaults_init,
  	.exit = sctp_defaults_exit,
  };
  
  static int __net_init sctp_ctrlsock_init(struct net *net)
  {
  	int status;
  
  	/* Initialize the control inode/socket for handling OOTB packets.  */
  	status = sctp_ctl_sock_init(net);
  	if (status)
  		pr_err("Failed to initialize the SCTP control sock
  ");
  
  	return status;
  }
b456d7241   Christophe JAILLET   sctp: Fix the lin...
1302
  static void __net_exit sctp_ctrlsock_exit(struct net *net)
8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1303
1304
1305
1306
1307
1308
1309
1310
  {
  	/* Free the control endpoint.  */
  	inet_ctl_sock_destroy(net->sctp.ctl_sock);
  }
  
  static struct pernet_operations sctp_ctrlsock_ops = {
  	.init = sctp_ctrlsock_init,
  	.exit = sctp_ctrlsock_exit,
4db67e808   Eric W. Biederman   sctp: Make the ad...
1311
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1312
  /* Initialize the universe into something sensible.  */
dda919285   Daniel Borkmann   net: sctp: remove...
1313
  static __init int sctp_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
  {
ca79b0c21   Arun KS   mm: convert total...
1315
  	unsigned long nr_pages = totalram_pages();
623b57bec   Colin Ian King   sctp: remove redu...
1316
1317
1318
1319
  	unsigned long limit;
  	unsigned long goal;
  	int max_entry_order;
  	int num_entries;
4d93df0ab   Neil Horman   [SCTP]: Rewrite o...
1320
  	int max_share;
623b57bec   Colin Ian King   sctp: remove redu...
1321
  	int status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
  	int order;
623b57bec   Colin Ian King   sctp: remove redu...
1323
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324

b4772ef87   Eyal Birger   net: use common m...
1325
  	sock_skb_cb_check_size(sizeof(struct sctp_ulpevent));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326

827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1327
  	/* Allocate bind_bucket and chunk caches. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
1329
1330
1331
  	status = -ENOBUFS;
  	sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
  					       sizeof(struct sctp_bind_bucket),
  					       0, SLAB_HWCACHE_ALIGN,
20c2df83d   Paul Mundt   mm: Remove slab d...
1332
  					       NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
  	if (!sctp_bucket_cachep)
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1334
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
1336
1337
1338
  
  	sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
  					       sizeof(struct sctp_chunk),
  					       0, SLAB_HWCACHE_ALIGN,
20c2df83d   Paul Mundt   mm: Remove slab d...
1339
  					       NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
1341
  	if (!sctp_chunk_cachep)
  		goto err_chunk_cachep;
908c7f194   Tejun Heo   percpu_counter: a...
1342
  	status = percpu_counter_init(&sctp_sockets_allocated, 0, GFP_KERNEL);
632c928a6   Eric W. Biederman   sctp: Move the pe...
1343
1344
  	if (status)
  		goto err_percpu_counter_init;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
1346
1347
1348
1349
1350
1351
1352
  	/* Implementation specific variables. */
  
  	/* Initialize default stream count setup information. */
  	sctp_max_instreams    		= SCTP_DEFAULT_INSTREAMS;
  	sctp_max_outstreams   		= SCTP_DEFAULT_OUTSTREAMS;
  
  	/* Initialize handle used for association ids. */
  	idr_init(&sctp_assocs_id);
f03d78db6   Eric Dumazet   net: refine {udp|...
1353
  	limit = nr_free_buffer_pages() / 8;
4d93df0ab   Neil Horman   [SCTP]: Rewrite o...
1354
1355
1356
1357
1358
1359
1360
1361
  	limit = max(limit, 128UL);
  	sysctl_sctp_mem[0] = limit / 4 * 3;
  	sysctl_sctp_mem[1] = limit;
  	sysctl_sctp_mem[2] = sysctl_sctp_mem[0] * 2;
  
  	/* Set per-socket limits to no more than 1/128 the pressure threshold*/
  	limit = (sysctl_sctp_mem[1]) << (PAGE_SHIFT - 7);
  	max_share = min(4UL*1024*1024, limit);
845525a64   Vlad Yasevich   sctp: Update sctp...
1362
  	sysctl_sctp_rmem[0] = SK_MEM_QUANTUM; /* give each asoc 1 page min */
87fb4b7b5   Eric Dumazet   net: more accurat...
1363
  	sysctl_sctp_rmem[1] = 1500 * SKB_TRUESIZE(1);
4d93df0ab   Neil Horman   [SCTP]: Rewrite o...
1364
  	sysctl_sctp_rmem[2] = max(sysctl_sctp_rmem[1], max_share);
3ab224be6   Hideo Aoki   [NET] CORE: Intro...
1365
  	sysctl_sctp_wmem[0] = SK_MEM_QUANTUM;
4d93df0ab   Neil Horman   [SCTP]: Rewrite o...
1366
1367
  	sysctl_sctp_wmem[1] = 16*1024;
  	sysctl_sctp_wmem[2] = max(64*1024, max_share);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
1369
  	/* Size and allocate the association hash table.
  	 * The methodology is similar to that of the tcp hash tables.
d9749fb59   Neil Horman   sctp: Fix port ha...
1370
  	 * Though not identical.  Start by getting a goal size
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
  	 */
3d6357de8   Arun KS   mm: reference tot...
1372
1373
  	if (nr_pages >= (128 * 1024))
  		goal = nr_pages >> (22 - PAGE_SHIFT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374
  	else
3d6357de8   Arun KS   mm: reference tot...
1375
  		goal = nr_pages >> (24 - PAGE_SHIFT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376

d9749fb59   Neil Horman   sctp: Fix port ha...
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
  	/* Then compute the page order for said goal */
  	order = get_order(goal);
  
  	/* Now compute the required page order for the maximum sized table we
  	 * want to create
  	 */
  	max_entry_order = get_order(MAX_SCTP_PORT_HASH_ENTRIES *
  				    sizeof(struct sctp_bind_hashbucket));
  
  	/* Limit the page order by that maximum hash table size */
  	order = min(order, max_entry_order);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1389
1390
  	/* Allocate and initialize the endpoint hash table.  */
  	sctp_ep_hashsize = 64;
3b77d6617   Zhang Yanfei   net: sctp: remove...
1391
  	sctp_ep_hashtable =
6da2ec560   Kees Cook   treewide: kmalloc...
1392
  		kmalloc_array(64, sizeof(struct sctp_hashbucket), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
  	if (!sctp_ep_hashtable) {
145ce502e   Joe Perches   net/sctp: Use pr_...
1394
1395
  		pr_err("Failed endpoint_hash alloc
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
1397
1398
1399
1400
  		status = -ENOMEM;
  		goto err_ehash_alloc;
  	}
  	for (i = 0; i < sctp_ep_hashsize; i++) {
  		rwlock_init(&sctp_ep_hashtable[i].lock);
d970dbf84   Vlad Yasevich   SCTP: Convert cus...
1401
  		INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402
  	}
d9749fb59   Neil Horman   sctp: Fix port ha...
1403
1404
1405
1406
1407
  	/* Allocate and initialize the SCTP port hash table.
  	 * Note that order is initalized to start at the max sized
  	 * table we want to support.  If we can't get that many pages
  	 * reduce the order and try again
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1408
  	do {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
  		sctp_port_hashtable = (struct sctp_bind_hashbucket *)
6857a02af   Eric Dumazet   sctp: use GFP_KER...
1410
  			__get_free_pages(GFP_KERNEL | __GFP_NOWARN, order);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
  	} while (!sctp_port_hashtable && --order > 0);
d9749fb59   Neil Horman   sctp: Fix port ha...
1412

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413
  	if (!sctp_port_hashtable) {
145ce502e   Joe Perches   net/sctp: Use pr_...
1414
1415
  		pr_err("Failed bind hash alloc
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1416
1417
1418
  		status = -ENOMEM;
  		goto err_bhash_alloc;
  	}
d9749fb59   Neil Horman   sctp: Fix port ha...
1419
1420
1421
1422
1423
1424
  
  	/* Now compute the number of entries that will fit in the
  	 * port hash space we allocated
  	 */
  	num_entries = (1UL << order) * PAGE_SIZE /
  		      sizeof(struct sctp_bind_hashbucket);
93c3216a7   Randy Dunlap   net: sctp: protoc...
1425
1426
  	/* And finish by rounding it down to the nearest power of two.
  	 * This wastes some memory of course, but it's needed because
d9749fb59   Neil Horman   sctp: Fix port ha...
1427
  	 * the hash function operates based on the assumption that
93c3216a7   Randy Dunlap   net: sctp: protoc...
1428
  	 * the number of entries is a power of two.
d9749fb59   Neil Horman   sctp: Fix port ha...
1429
1430
  	 */
  	sctp_port_hashsize = rounddown_pow_of_two(num_entries);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1431
1432
  	for (i = 0; i < sctp_port_hashsize; i++) {
  		spin_lock_init(&sctp_port_hashtable[i].lock);
d970dbf84   Vlad Yasevich   SCTP: Convert cus...
1433
  		INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1434
  	}
a5e27d18f   Wei Yongjun   sctp: fix error r...
1435
1436
  	status = sctp_transport_hashtable_init();
  	if (status)
4f0087812   Xin Long   sctp: apply rhash...
1437
  		goto err_thash_alloc;
d9749fb59   Neil Horman   sctp: Fix port ha...
1438
1439
1440
  	pr_info("Hash tables configured (bind %d/%d)
  ", sctp_port_hashsize,
  		num_entries);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1442
1443
1444
  	sctp_sysctl_register();
  
  	INIT_LIST_HEAD(&sctp_address_families);
270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1445
1446
  	sctp_v4_pf_init();
  	sctp_v6_pf_init();
1ba896f6f   Xin Long   sctp: remove exte...
1447
  	sctp_sched_ops_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448

8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1449
1450
1451
  	status = register_pernet_subsys(&sctp_defaults_ops);
  	if (status)
  		goto err_register_defaults;
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1452

8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1453
  	status = sctp_v4_protosw_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
  	if (status)
270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1455
1456
1457
1458
1459
  		goto err_protosw_init;
  
  	status = sctp_v6_protosw_init();
  	if (status)
  		goto err_v6_protosw_init;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460

8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1461
  	status = register_pernet_subsys(&sctp_ctrlsock_ops);
4db67e808   Eric W. Biederman   sctp: Make the ad...
1462
  	if (status)
8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1463
  		goto err_register_ctrlsock;
4db67e808   Eric W. Biederman   sctp: Make the ad...
1464

270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1465
1466
  	status = sctp_v4_add_protocol();
  	if (status)
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1467
  		goto err_add_protocol;
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1468
1469
1470
1471
1472
  
  	/* Register SCTP with inet6 layer.  */
  	status = sctp_v6_add_protocol();
  	if (status)
  		goto err_v6_add_protocol;
90017accf   Marcelo Ricardo Leitner   sctp: Add GSO sup...
1473
1474
1475
  	if (sctp_offload_init() < 0)
  		pr_crit("%s: Cannot add SCTP protocol offload
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
1477
  out:
  	return status;
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1478
  err_v6_add_protocol:
270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1479
  	sctp_v4_del_protocol();
d1dd52478   Vlad Yasevich   sctp: fix crash d...
1480
  err_add_protocol:
8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1481
1482
  	unregister_pernet_subsys(&sctp_ctrlsock_ops);
  err_register_ctrlsock:
270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1483
1484
1485
1486
  	sctp_v6_protosw_exit();
  err_v6_protosw_init:
  	sctp_v4_protosw_exit();
  err_protosw_init:
8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1487
1488
  	unregister_pernet_subsys(&sctp_defaults_ops);
  err_register_defaults:
270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1489
1490
  	sctp_v4_pf_exit();
  	sctp_v6_pf_exit();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1491
  	sctp_sysctl_unregister();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1492
1493
1494
1495
  	free_pages((unsigned long)sctp_port_hashtable,
  		   get_order(sctp_port_hashsize *
  			     sizeof(struct sctp_bind_hashbucket)));
  err_bhash_alloc:
4f0087812   Xin Long   sctp: apply rhash...
1496
1497
  	sctp_transport_hashtable_destroy();
  err_thash_alloc:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
1499
  	kfree(sctp_ep_hashtable);
  err_ehash_alloc:
632c928a6   Eric W. Biederman   sctp: Move the pe...
1500
1501
  	percpu_counter_destroy(&sctp_sockets_allocated);
  err_percpu_counter_init:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1502
1503
1504
  	kmem_cache_destroy(sctp_chunk_cachep);
  err_chunk_cachep:
  	kmem_cache_destroy(sctp_bucket_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505
1506
1507
1508
  	goto out;
  }
  
  /* Exit handler for the SCTP protocol.  */
dda919285   Daniel Borkmann   net: sctp: remove...
1509
  static __exit void sctp_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1510
1511
1512
1513
  {
  	/* BUG.  This should probably do something useful like clean
  	 * up all the remaining associations and all that memory.
  	 */
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1514
1515
  	/* Unregister with inet6/inet layers. */
  	sctp_v6_del_protocol();
270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1516
  	sctp_v4_del_protocol();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517

8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1518
  	unregister_pernet_subsys(&sctp_ctrlsock_ops);
4db67e808   Eric W. Biederman   sctp: Make the ad...
1519

270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1520
1521
1522
  	/* Free protosw registrations */
  	sctp_v6_protosw_exit();
  	sctp_v4_protosw_exit();
8e2d61e0a   Marcelo Ricardo Leitner   sctp: fix race on...
1523
  	unregister_pernet_subsys(&sctp_defaults_ops);
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1524
  	/* Unregister with socket layer. */
270637abf   Vlad Yasevich   [SCTP]: Fix a rac...
1525
1526
  	sctp_v6_pf_exit();
  	sctp_v4_pf_exit();
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1527

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1528
  	sctp_sysctl_unregister();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1529

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1530
1531
1532
  	free_pages((unsigned long)sctp_port_hashtable,
  		   get_order(sctp_port_hashsize *
  			     sizeof(struct sctp_bind_hashbucket)));
b5eff7128   Xin Long   sctp: drop the ol...
1533
  	kfree(sctp_ep_hashtable);
4f0087812   Xin Long   sctp: apply rhash...
1534
  	sctp_transport_hashtable_destroy();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1535

632c928a6   Eric W. Biederman   sctp: Move the pe...
1536
  	percpu_counter_destroy(&sctp_sockets_allocated);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537

eaa184a1a   Jesper Dangaard Brouer   sctp: protocol.c ...
1538
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
827bf1223   Sridhar Samudrala   [SCTP]: Re-order ...
1539
1540
  	kmem_cache_destroy(sctp_chunk_cachep);
  	kmem_cache_destroy(sctp_bucket_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541
1542
1543
1544
  }
  
  module_init(sctp_init);
  module_exit(sctp_exit);
bb97d31f5   Arnaldo Carvalho de Melo   [INET]: Make inet...
1545
1546
1547
1548
  /*
   * __stringify doesn't likes enums, so use IPPROTO_SCTP value (132) directly.
   */
  MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132");
882a382c3   Sridhar Samudrala   [SCTP]: Enable au...
1549
  MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132");
91705c61b   Daniel Borkmann   net: sctp: trivia...
1550
  MODULE_AUTHOR("Linux Kernel SCTP developers <linux-sctp@vger.kernel.org>");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1551
  MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
71acc0ddd   David S. Miller   Revert "net: sctp...
1552
1553
  module_param_named(no_checksums, sctp_checksum_disable, bool, 0644);
  MODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
  MODULE_LICENSE("GPL");