sctp.h 18.4 KB
Newer Older
1
/* SCTP kernel implementation
Linus Torvalds's avatar
Linus Torvalds committed
2
3
4
5
6
 * (C) Copyright IBM Corp. 2001, 2004
 * Copyright (c) 1999-2000 Cisco, Inc.
 * Copyright (c) 1999-2001 Motorola, Inc.
 * Copyright (c) 2001-2003 Intel Corp.
 *
7
 * This file is part of the SCTP kernel implementation
Linus Torvalds's avatar
Linus Torvalds committed
8
9
10
 *
 * The base lksctp header.
 *
11
 * This SCTP implementation is free software;
Linus Torvalds's avatar
Linus Torvalds committed
12
13
14
15
16
 * you can redistribute it and/or modify it under the terms of
 * the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
17
 * This SCTP implementation is distributed in the hope that it
Linus Torvalds's avatar
Linus Torvalds committed
18
19
20
21
22
23
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 *                 ************************
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
24
25
 * along with GNU CC; see the file COPYING.  If not, see
 * <http://www.gnu.org/licenses/>.
Linus Torvalds's avatar
Linus Torvalds committed
26
27
28
 *
 * Please send any bug reports or fixes you make to the
 * email address(es):
29
 *    lksctp developers <linux-sctp@vger.kernel.org>
Linus Torvalds's avatar
Linus Torvalds committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
 *
 * Written or modified by:
 *    La Monte H.P. Yarroll <piggy@acm.org>
 *    Xingang Guo           <xingang.guo@intel.com>
 *    Jon Grimm             <jgrimm@us.ibm.com>
 *    Daisy Chang           <daisyc@us.ibm.com>
 *    Sridhar Samudrala     <sri@us.ibm.com>
 *    Ardelle Fan           <ardelle.fan@intel.com>
 *    Ryan Layer            <rmlayer@us.ibm.com>
 *    Kevin Gao             <kevin.gao@intel.com> 
 */

#ifndef __net_sctp_h__
#define __net_sctp_h__

/* Header Strategy.
 *    Start getting some control over the header file depencies:
 *       includes
 *       constants
 *       structs
 *       prototypes
 *       macros, externs, and inlines
 *
 *   Move test_frame specific items out of the kernel headers
 *   and into the test frame headers.   This is not perfect in any sense
 *   and will continue to evolve.
 */

#include <linux/types.h>
#include <linux/slab.h>
#include <linux/in.h>
#include <linux/tty.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <linux/idr.h>

67
#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds's avatar
Linus Torvalds committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <net/ipv6.h>
#include <net/ip6_route.h>
#endif

#include <asm/uaccess.h>
#include <asm/page.h>
#include <net/sock.h>
#include <net/snmp.h>
#include <net/sctp/structs.h>
#include <net/sctp/constants.h>

#ifdef CONFIG_IP_SCTP_MODULE
#define SCTP_PROTOSW_FLAG 0
#else /* static! */
#define SCTP_PROTOSW_FLAG INET_PROTOSW_PERMANENT
#endif

85
86
87
88
89
/* Round an int up to the next multiple of 4.  */
#define WORD_ROUND(s) (((s)+3)&~3)
/* Truncate to the previous multiple of 4.  */
#define WORD_TRUNC(s) ((s)&~3)

Linus Torvalds's avatar
Linus Torvalds committed
90
91
92
93
94
95
96
/*
 * Function declarations.
 */

/*
 * sctp/protocol.c
 */
97
98
99
100
101
int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
			      sctp_scope_t, gfp_t gfp, int flags);
struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
int sctp_register_pf(struct sctp_pf *, sa_family_t);
void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int);
Linus Torvalds's avatar
Linus Torvalds committed
102
103
104
105
106
107
108

/*
 * sctp/socket.c
 */
int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
int sctp_inet_listen(struct socket *sock, int backlog);
void sctp_write_space(struct sock *sk);
109
void sctp_data_ready(struct sock *sk);
Linus Torvalds's avatar
Linus Torvalds committed
110
111
unsigned int sctp_poll(struct file *file, struct socket *sock,
		poll_table *wait);
112
void sctp_sock_rfree(struct sk_buff *skb);
113
114
void sctp_copy_sock(struct sock *newsk, struct sock *sk,
		    struct sctp_association *asoc);
115
extern struct percpu_counter sctp_sockets_allocated;
116
int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
117
struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *);
Linus Torvalds's avatar
Linus Torvalds committed
118

119
120
121
122
123
124
125
126
127
128
129
130
131
int sctp_transport_walk_start(struct rhashtable_iter *iter);
void sctp_transport_walk_stop(struct rhashtable_iter *iter);
struct sctp_transport *sctp_transport_get_next(struct net *net,
			struct rhashtable_iter *iter);
struct sctp_transport *sctp_transport_get_idx(struct net *net,
			struct rhashtable_iter *iter, int pos);
int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
				  struct net *net,
				  const union sctp_addr *laddr,
				  const union sctp_addr *paddr, void *p);
int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *),
			    struct net *net, int pos, void *p);
int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), void *p);
132
133
134
int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc,
		       struct sctp_info *info);

Linus Torvalds's avatar
Linus Torvalds committed
135
136
137
/*
 * sctp/primitive.c
 */
138
139
140
141
142
143
int sctp_primitive_ASSOCIATE(struct net *, struct sctp_association *, void *arg);
int sctp_primitive_SHUTDOWN(struct net *, struct sctp_association *, void *arg);
int sctp_primitive_ABORT(struct net *, struct sctp_association *, void *arg);
int sctp_primitive_SEND(struct net *, struct sctp_association *, void *arg);
int sctp_primitive_REQUESTHEARTBEAT(struct net *, struct sctp_association *, void *arg);
int sctp_primitive_ASCONF(struct net *, struct sctp_association *, void *arg);
Linus Torvalds's avatar
Linus Torvalds committed
144
145
146
147
148
149
150
151

/*
 * sctp/input.c
 */
int sctp_rcv(struct sk_buff *skb);
void sctp_v4_err(struct sk_buff *skb, u32 info);
void sctp_hash_endpoint(struct sctp_endpoint *);
void sctp_unhash_endpoint(struct sctp_endpoint *);
152
struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
153
			     struct sctphdr *, struct sctp_association **,
Linus Torvalds's avatar
Linus Torvalds committed
154
			     struct sctp_transport **);
155
void sctp_err_finish(struct sock *, struct sctp_association *);
Linus Torvalds's avatar
Linus Torvalds committed
156
157
void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
			   struct sctp_transport *t, __u32 pmtu);
158
159
void sctp_icmp_redirect(struct sock *, struct sctp_transport *,
			struct sk_buff *);
Linus Torvalds's avatar
Linus Torvalds committed
160
161
162
void sctp_icmp_proto_unreachable(struct sock *sk,
				 struct sctp_association *asoc,
				 struct sctp_transport *t);
163
164
void sctp_backlog_migrate(struct sctp_association *assoc,
			  struct sock *oldsk, struct sock *newsk);
165
166
167
168
169
170
171
172
173
174
175
int sctp_transport_hashtable_init(void);
void sctp_transport_hashtable_destroy(void);
void sctp_hash_transport(struct sctp_transport *t);
void sctp_unhash_transport(struct sctp_transport *t);
struct sctp_transport *sctp_addrs_lookup_transport(
				struct net *net,
				const union sctp_addr *laddr,
				const union sctp_addr *paddr);
struct sctp_transport *sctp_epaddr_lookup_transport(
				const struct sctp_endpoint *ep,
				const union sctp_addr *paddr);
Linus Torvalds's avatar
Linus Torvalds committed
176

Adrian Bunk's avatar
Adrian Bunk committed
177
178
179
/*
 * sctp/proc.c
 */
180
181
182
183
184
185
186
187
int sctp_snmp_proc_init(struct net *net);
void sctp_snmp_proc_exit(struct net *net);
int sctp_eps_proc_init(struct net *net);
void sctp_eps_proc_exit(struct net *net);
int sctp_assocs_proc_init(struct net *net);
void sctp_assocs_proc_exit(struct net *net);
int sctp_remaddr_proc_init(struct net *net);
void sctp_remaddr_proc_exit(struct net *net);
Adrian Bunk's avatar
Adrian Bunk committed
188
189


190
191
192
193
194
195
196
197
198
/*
 * Module global variables
 */

 /*
  * sctp/protocol.c
  */
extern struct kmem_cache *sctp_chunk_cachep __read_mostly;
extern struct kmem_cache *sctp_bucket_cachep __read_mostly;
199
200
201
extern long sysctl_sctp_mem[3];
extern int sysctl_sctp_rmem[3];
extern int sysctl_sctp_wmem[3];
202

Linus Torvalds's avatar
Linus Torvalds committed
203
204
205
206
207
/*
 *  Section:  Macros, externs, and inlines
 */

/* SCTP SNMP MIB stats handlers */
Eric Dumazet's avatar
Eric Dumazet committed
208
209
210
#define SCTP_INC_STATS(net, field)	SNMP_INC_STATS((net)->sctp.sctp_statistics, field)
#define __SCTP_INC_STATS(net, field)	__SNMP_INC_STATS((net)->sctp.sctp_statistics, field)
#define SCTP_DEC_STATS(net, field)	SNMP_DEC_STATS((net)->sctp.sctp_statistics, field)
Linus Torvalds's avatar
Linus Torvalds committed
211

212
/* sctp mib definitions */
Eric Dumazet's avatar
Eric Dumazet committed
213
enum {
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
	SCTP_MIB_NUM = 0,
	SCTP_MIB_CURRESTAB,			/* CurrEstab */
	SCTP_MIB_ACTIVEESTABS,			/* ActiveEstabs */
	SCTP_MIB_PASSIVEESTABS,			/* PassiveEstabs */
	SCTP_MIB_ABORTEDS,			/* Aborteds */
	SCTP_MIB_SHUTDOWNS,			/* Shutdowns */
	SCTP_MIB_OUTOFBLUES,			/* OutOfBlues */
	SCTP_MIB_CHECKSUMERRORS,		/* ChecksumErrors */
	SCTP_MIB_OUTCTRLCHUNKS,			/* OutCtrlChunks */
	SCTP_MIB_OUTORDERCHUNKS,		/* OutOrderChunks */
	SCTP_MIB_OUTUNORDERCHUNKS,		/* OutUnorderChunks */
	SCTP_MIB_INCTRLCHUNKS,			/* InCtrlChunks */
	SCTP_MIB_INORDERCHUNKS,			/* InOrderChunks */
	SCTP_MIB_INUNORDERCHUNKS,		/* InUnorderChunks */
	SCTP_MIB_FRAGUSRMSGS,			/* FragUsrMsgs */
	SCTP_MIB_REASMUSRMSGS,			/* ReasmUsrMsgs */
	SCTP_MIB_OUTSCTPPACKS,			/* OutSCTPPacks */
	SCTP_MIB_INSCTPPACKS,			/* InSCTPPacks */
	SCTP_MIB_T1_INIT_EXPIREDS,
	SCTP_MIB_T1_COOKIE_EXPIREDS,
	SCTP_MIB_T2_SHUTDOWN_EXPIREDS,
	SCTP_MIB_T3_RTX_EXPIREDS,
	SCTP_MIB_T4_RTO_EXPIREDS,
	SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS,
	SCTP_MIB_DELAY_SACK_EXPIREDS,
	SCTP_MIB_AUTOCLOSE_EXPIREDS,
240
	SCTP_MIB_T1_RETRANSMITS,
241
242
243
244
245
246
247
248
249
250
251
252
253
	SCTP_MIB_T3_RETRANSMITS,
	SCTP_MIB_PMTUD_RETRANSMITS,
	SCTP_MIB_FAST_RETRANSMITS,
	SCTP_MIB_IN_PKT_SOFTIRQ,
	SCTP_MIB_IN_PKT_BACKLOG,
	SCTP_MIB_IN_PKT_DISCARDS,
	SCTP_MIB_IN_DATA_CHUNK_DISCARDS,
	__SCTP_MIB_MAX
};

#define SCTP_MIB_MAX    __SCTP_MIB_MAX
struct sctp_mib {
        unsigned long   mibs[SCTP_MIB_MAX];
Eric Dumazet's avatar
Eric Dumazet committed
254
};
255

256
257
258
259
260
261
262
263
264
265
266
267
/* helper function to track stats about max rto and related transport */
static inline void sctp_max_rto(struct sctp_association *asoc,
				struct sctp_transport *trans)
{
	if (asoc->stats.max_obs_rto < (__u64)trans->rto) {
		asoc->stats.max_obs_rto = trans->rto;
		memset(&asoc->stats.obs_rto_ipaddr, 0,
			sizeof(struct sockaddr_storage));
		memcpy(&asoc->stats.obs_rto_ipaddr, &trans->ipaddr,
			trans->af_specific->sockaddr_len);
	}
}
Linus Torvalds's avatar
Linus Torvalds committed
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

/*
 * Macros for keeping a global reference of object allocations.
 */
#ifdef CONFIG_SCTP_DBG_OBJCNT

extern atomic_t sctp_dbg_objcnt_sock;
extern atomic_t sctp_dbg_objcnt_ep;
extern atomic_t sctp_dbg_objcnt_assoc;
extern atomic_t sctp_dbg_objcnt_transport;
extern atomic_t sctp_dbg_objcnt_chunk;
extern atomic_t sctp_dbg_objcnt_bind_addr;
extern atomic_t sctp_dbg_objcnt_bind_bucket;
extern atomic_t sctp_dbg_objcnt_addr;
extern atomic_t sctp_dbg_objcnt_ssnmap;
extern atomic_t sctp_dbg_objcnt_datamsg;
284
extern atomic_t sctp_dbg_objcnt_keys;
Linus Torvalds's avatar
Linus Torvalds committed
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299

/* Macros to atomically increment/decrement objcnt counters.  */
#define SCTP_DBG_OBJCNT_INC(name) \
atomic_inc(&sctp_dbg_objcnt_## name)
#define SCTP_DBG_OBJCNT_DEC(name) \
atomic_dec(&sctp_dbg_objcnt_## name)
#define SCTP_DBG_OBJCNT(name) \
atomic_t sctp_dbg_objcnt_## name = ATOMIC_INIT(0)

/* Macro to help create new entries in in the global array of
 * objcnt counters.
 */
#define SCTP_DBG_OBJCNT_ENTRY(name) \
{.label= #name, .counter= &sctp_dbg_objcnt_## name}

300
301
void sctp_dbg_objcnt_init(struct net *);
void sctp_dbg_objcnt_exit(struct net *);
Linus Torvalds's avatar
Linus Torvalds committed
302
303
304
305
306
307

#else

#define SCTP_DBG_OBJCNT_INC(name)
#define SCTP_DBG_OBJCNT_DEC(name)

308
309
static inline void sctp_dbg_objcnt_init(struct net *net) { return; }
static inline void sctp_dbg_objcnt_exit(struct net *net) { return; }
Linus Torvalds's avatar
Linus Torvalds committed
310
311
312
313
314
315

#endif /* CONFIG_SCTP_DBG_OBJCOUNT */

#if defined CONFIG_SYSCTL
void sctp_sysctl_register(void);
void sctp_sysctl_unregister(void);
316
317
int sctp_sysctl_net_register(struct net *net);
void sctp_sysctl_net_unregister(struct net *net);
Linus Torvalds's avatar
Linus Torvalds committed
318
319
320
#else
static inline void sctp_sysctl_register(void) { return; }
static inline void sctp_sysctl_unregister(void) { return; }
321
322
static inline int sctp_sysctl_net_register(struct net *net) { return 0; }
static inline void sctp_sysctl_net_unregister(struct net *net) { return; }
Linus Torvalds's avatar
Linus Torvalds committed
323
324
325
326
327
#endif

/* Size of Supported Address Parameter for 'x' address types. */
#define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16))

328
#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds's avatar
Linus Torvalds committed
329

330
331
332
333
void sctp_v6_pf_init(void);
void sctp_v6_pf_exit(void);
int sctp_v6_protosw_init(void);
void sctp_v6_protosw_exit(void);
334
335
int sctp_v6_add_protocol(void);
void sctp_v6_del_protocol(void);
Linus Torvalds's avatar
Linus Torvalds committed
336
337
338

#else /* #ifdef defined(CONFIG_IPV6) */

339
static inline void sctp_v6_pf_init(void) { return; }
340
341
342
static inline void sctp_v6_pf_exit(void) { return; }
static inline int sctp_v6_protosw_init(void) { return 0; }
static inline void sctp_v6_protosw_exit(void) { return; }
343
344
static inline int sctp_v6_add_protocol(void) { return 0; }
static inline void sctp_v6_del_protocol(void) { return; }
Linus Torvalds's avatar
Linus Torvalds committed
345
346
347
348
349
350
351

#endif /* #if defined(CONFIG_IPV6) */


/* Map an association to an assoc_id. */
static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc)
{
Eric Dumazet's avatar
Eric Dumazet committed
352
	return asoc ? asoc->assoc_id : 0;
Linus Torvalds's avatar
Linus Torvalds committed
353
354
}

355
356
357
358
359
360
361
362
363
364
365
366
367
static inline enum sctp_sstat_state
sctp_assoc_to_state(const struct sctp_association *asoc)
{
	/* SCTP's uapi always had SCTP_EMPTY(=0) as a dummy state, but we
	 * got rid of it in kernel space. Therefore SCTP_CLOSED et al
	 * start at =1 in user space, but actually as =0 in kernel space.
	 * Now that we can not break user space and SCTP_EMPTY is exposed
	 * there, we need to fix it up with an ugly offset not to break
	 * applications. :(
	 */
	return asoc->state + 1;
}

Linus Torvalds's avatar
Linus Torvalds committed
368
369
370
/* Look up the association by its id.  */
struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);

371
int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp);
Linus Torvalds's avatar
Linus Torvalds committed
372
373
374

/* A macro to walk a list of skbs.  */
#define sctp_skb_for_each(pos, head, tmp) \
375
	skb_queue_walk_safe(head, pos, tmp)
Linus Torvalds's avatar
Linus Torvalds committed
376
377
378
379
380
381
382
383
384
385
386
387
388

/**
 *	sctp_list_dequeue - remove from the head of the queue
 *	@list: list to dequeue from
 *
 *	Remove the head of the list. The head item is
 *	returned or %NULL if the list is empty.
 */

static inline struct list_head *sctp_list_dequeue(struct list_head *list)
{
	struct list_head *result = NULL;

389
	if (!list_empty(list)) {
Linus Torvalds's avatar
Linus Torvalds committed
390
		result = list->next;
391
		list_del_init(result);
Linus Torvalds's avatar
Linus Torvalds committed
392
393
394
395
	}
	return result;
}

396
397
398
399
400
401
402
403
/* SCTP version of skb_set_owner_r.  We need this one because
 * of the way we have to do receive buffer accounting on bundled
 * chunks.
 */
static inline void sctp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
{
	struct sctp_ulpevent *event = sctp_skb2event(skb);

404
	skb_orphan(skb);
405
406
407
	skb->sk = sk;
	skb->destructor = sctp_sock_rfree;
	atomic_add(event->rmem_len, &sk->sk_rmem_alloc);
408
	/*
409
	 * This mimics the behavior of skb_set_owner_r
410
411
	 */
	sk->sk_forward_alloc -= event->rmem_len;
412
413
}

Linus Torvalds's avatar
Linus Torvalds committed
414
415
416
/* Tests if the list has one and only one entry. */
static inline int sctp_list_single_entry(struct list_head *head)
{
Eric Dumazet's avatar
Eric Dumazet committed
417
	return (head->next != head) && (head->next == head->prev);
Linus Torvalds's avatar
Linus Torvalds committed
418
419
420
}

/* Break down data chunks at this point.  */
421
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
Linus Torvalds's avatar
Linus Torvalds committed
422
{
423
	struct sctp_sock *sp = sctp_sk(asoc->base.sk);
Linus Torvalds's avatar
Linus Torvalds committed
424
425
426
427
428
	int frag = pmtu;

	frag -= sp->pf->af->net_header_len;
	frag -= sizeof(struct sctphdr) + sizeof(struct sctp_data_chunk);

429
430
	if (asoc->user_frag)
		frag = min_t(int, frag, asoc->user_frag);
Linus Torvalds's avatar
Linus Torvalds committed
431

432
	frag = WORD_TRUNC(min_t(int, frag, SCTP_MAX_CHUNK_LEN));
Linus Torvalds's avatar
Linus Torvalds committed
433
434
435
436

	return frag;
}

437
static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_association *asoc)
438
439
{

440
	sctp_assoc_sync_pmtu(sk, asoc);
441
442
443
	asoc->pmtu_pending = 0;
}

444
445
446
447
448
static inline bool sctp_chunk_pending(const struct sctp_chunk *chunk)
{
	return !list_empty(&chunk->list);
}

Linus Torvalds's avatar
Linus Torvalds committed
449
450
451
452
453
454
/* Walk through a list of TLV parameters.  Don't trust the
 * individual parameter lengths and instead depend on
 * the chunk length to indicate when to stop.  Make sure
 * there is room for a param header too.
 */
#define sctp_walk_params(pos, chunk, member)\
455
_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member)
Linus Torvalds's avatar
Linus Torvalds committed
456
457
458

#define _sctp_walk_params(pos, chunk, end, member)\
for (pos.v = chunk->member;\
459
     pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\
Linus Torvalds's avatar
Linus Torvalds committed
460
461
462
463
464
465
466
467
468
     ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\
     pos.v += WORD_ROUND(ntohs(pos.p->length)))

#define sctp_walk_errors(err, chunk_hdr)\
_sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length))

#define _sctp_walk_errors(err, chunk_hdr, end)\
for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
	    sizeof(sctp_chunkhdr_t));\
469
     (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\
Linus Torvalds's avatar
Linus Torvalds committed
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
     ntohs(err->length) >= sizeof(sctp_errhdr_t); \
     err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length))))

#define sctp_walk_fwdtsn(pos, chunk)\
_sctp_walk_fwdtsn((pos), (chunk), ntohs((chunk)->chunk_hdr->length) - sizeof(struct sctp_fwdtsn_chunk))

#define _sctp_walk_fwdtsn(pos, chunk, end)\
for (pos = chunk->subh.fwdtsn_hdr->skip;\
     (void *)pos <= (void *)chunk->subh.fwdtsn_hdr->skip + end - sizeof(struct sctp_fwdtsn_skip);\
     pos++)

/* External references. */

extern struct proto sctp_prot;
extern struct proto sctpv6_prot;
void sctp_put_port(struct sock *sk);

extern struct idr sctp_assocs_id;
extern spinlock_t sctp_assocs_id_lock;

/* Static inline functions. */

/* Convert from an IP version number to an Address Family symbol.  */
static inline int ipver2af(__u8 ipver)
{
	switch (ipver) {
	case 4:
	        return  AF_INET;
	case 6:
		return AF_INET6;
	default:
		return 0;
502
	}
Linus Torvalds's avatar
Linus Torvalds committed
503
504
505
}

/* Convert from an address parameter type to an address family.  */
506
static inline int param_type2af(__be16 type)
Linus Torvalds's avatar
Linus Torvalds committed
507
508
509
510
511
512
513
514
{
	switch (type) {
	case SCTP_PARAM_IPV4_ADDRESS:
	        return  AF_INET;
	case SCTP_PARAM_IPV6_ADDRESS:
		return AF_INET6;
	default:
		return 0;
515
	}
Linus Torvalds's avatar
Linus Torvalds committed
516
517
518
519
}

/* Warning: The following hash functions assume a power of two 'size'. */
/* This is the hash function for the SCTP port hash table. */
520
static inline int sctp_phashfn(struct net *net, __u16 lport)
Linus Torvalds's avatar
Linus Torvalds committed
521
{
522
	return (net_hash_mix(net) + lport) & (sctp_port_hashsize - 1);
Linus Torvalds's avatar
Linus Torvalds committed
523
524
525
}

/* This is the hash function for the endpoint hash table. */
526
static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
Linus Torvalds's avatar
Linus Torvalds committed
527
{
528
	return (net_hash_mix(net) + lport) & (sctp_ep_hashsize - 1);
Linus Torvalds's avatar
Linus Torvalds committed
529
530
}

531
532
#define sctp_for_each_hentry(epb, head) \
	hlist_for_each_entry(epb, head, node)
533

Linus Torvalds's avatar
Linus Torvalds committed
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
/* Is a socket of this style? */
#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style)
{
	return sctp_sk(sk)->type == style;
}

/* Is the association in this state? */
#define sctp_state(asoc, state) __sctp_state((asoc), (SCTP_STATE_##state))
static inline int __sctp_state(const struct sctp_association *asoc,
			       sctp_state_t state)
{
	return asoc->state == state;
}

/* Is the socket in this state? */
#define sctp_sstate(sk, state) __sctp_sstate((sk), (SCTP_SS_##state))
static inline int __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
{
	return sk->sk_state == state;
}

/* Map v4-mapped v6 address back to v4 address */
static inline void sctp_v6_map_v4(union sctp_addr *addr)
{
	addr->v4.sin_family = AF_INET;
	addr->v4.sin_port = addr->v6.sin6_port;
	addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3];
}

/* Map v4 address to v4-mapped v6 address */
static inline void sctp_v4_map_v6(union sctp_addr *addr)
{
567
568
569
570
571
	__be16 port;

	port = addr->v4.sin_port;
	addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
	addr->v6.sin6_port = port;
Linus Torvalds's avatar
Linus Torvalds committed
572
	addr->v6.sin6_family = AF_INET6;
573
574
	addr->v6.sin6_flowinfo = 0;
	addr->v6.sin6_scope_id = 0;
Linus Torvalds's avatar
Linus Torvalds committed
575
576
577
578
579
	addr->v6.sin6_addr.s6_addr32[0] = 0;
	addr->v6.sin6_addr.s6_addr32[1] = 0;
	addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
}

580
581
582
583
584
/* The cookie is always 0 since this is how it's used in the
 * pmtu code.
 */
static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
{
585
	if (t->dst && !dst_check(t->dst, t->dst_cookie)) {
586
587
588
589
590
591
592
		dst_release(t->dst);
		t->dst = NULL;
	}

	return t->dst;
}

Linus Torvalds's avatar
Linus Torvalds committed
593
#endif /* __net_sctp_h__ */