sctp.h 18.5 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
/* Round an int up to the next multiple of 4.  */
86
#define SCTP_PAD4(s) (((s)+3)&~3)
87
/* Truncate to the previous multiple of 4.  */
88
#define SCTP_TRUNC4(s) ((s)&~3)
89

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_transport *);
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
int sctp_transport_hashtable_init(void);
void sctp_transport_hashtable_destroy(void);
167
int sctp_hash_transport(struct sctp_transport *t);
168
169
170
171
172
173
174
175
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
/*
 * sctp/offload.c
 */
int sctp_offload_init(void);
Adrian Bunk's avatar
Adrian Bunk committed
193

194
195
196
197
198
199
200
201
202
/*
 * Module global variables
 */

 /*
  * sctp/protocol.c
  */
extern struct kmem_cache *sctp_chunk_cachep __read_mostly;
extern struct kmem_cache *sctp_bucket_cachep __read_mostly;
203
204
205
extern long sysctl_sctp_mem[3];
extern int sysctl_sctp_rmem[3];
extern int sysctl_sctp_wmem[3];
206

Linus Torvalds's avatar
Linus Torvalds committed
207
208
209
210
211
/*
 *  Section:  Macros, externs, and inlines
 */

/* SCTP SNMP MIB stats handlers */
Eric Dumazet's avatar
Eric Dumazet committed
212
213
214
#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
215

216
/* sctp mib definitions */
Eric Dumazet's avatar
Eric Dumazet committed
217
enum {
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
	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,
244
	SCTP_MIB_T1_RETRANSMITS,
245
246
247
248
249
250
251
252
253
254
255
256
257
	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
258
};
259

260
261
262
263
264
265
266
267
268
269
270
271
/* 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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287

/*
 * 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;
288
extern atomic_t sctp_dbg_objcnt_keys;
Linus Torvalds's avatar
Linus Torvalds committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

/* 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}

304
305
void sctp_dbg_objcnt_init(struct net *);
void sctp_dbg_objcnt_exit(struct net *);
Linus Torvalds's avatar
Linus Torvalds committed
306
307
308
309
310
311

#else

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

312
313
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
314
315
316
317
318
319

#endif /* CONFIG_SCTP_DBG_OBJCOUNT */

#if defined CONFIG_SYSCTL
void sctp_sysctl_register(void);
void sctp_sysctl_unregister(void);
320
321
int sctp_sysctl_net_register(struct net *net);
void sctp_sysctl_net_unregister(struct net *net);
Linus Torvalds's avatar
Linus Torvalds committed
322
323
324
#else
static inline void sctp_sysctl_register(void) { return; }
static inline void sctp_sysctl_unregister(void) { return; }
325
326
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
327
328
329
330
331
#endif

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

332
#if IS_ENABLED(CONFIG_IPV6)
Linus Torvalds's avatar
Linus Torvalds committed
333

334
335
336
337
void sctp_v6_pf_init(void);
void sctp_v6_pf_exit(void);
int sctp_v6_protosw_init(void);
void sctp_v6_protosw_exit(void);
338
339
int sctp_v6_add_protocol(void);
void sctp_v6_del_protocol(void);
Linus Torvalds's avatar
Linus Torvalds committed
340
341
342

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

343
static inline void sctp_v6_pf_init(void) { return; }
344
345
346
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; }
347
348
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
349
350
351
352
353
354
355

#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
356
	return asoc ? asoc->assoc_id : 0;
Linus Torvalds's avatar
Linus Torvalds committed
357
358
}

359
360
361
362
363
364
365
366
367
368
369
370
371
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
372
373
374
/* Look up the association by its id.  */
struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);

375
int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp);
Linus Torvalds's avatar
Linus Torvalds committed
376
377
378

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

/**
 *	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;

393
	if (!list_empty(list)) {
Linus Torvalds's avatar
Linus Torvalds committed
394
		result = list->next;
395
		list_del_init(result);
Linus Torvalds's avatar
Linus Torvalds committed
396
397
398
399
	}
	return result;
}

400
401
402
403
404
405
406
407
/* 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);

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

Linus Torvalds's avatar
Linus Torvalds committed
418
419
420
/* 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
421
	return (head->next != head) && (head->next == head->prev);
Linus Torvalds's avatar
Linus Torvalds committed
422
423
424
}

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

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

433
434
	if (asoc->user_frag)
		frag = min_t(int, frag, asoc->user_frag);
Linus Torvalds's avatar
Linus Torvalds committed
435

436
	frag = SCTP_TRUNC4(min_t(int, frag, SCTP_MAX_CHUNK_LEN));
Linus Torvalds's avatar
Linus Torvalds committed
437
438
439
440

	return frag;
}

441
static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_association *asoc)
442
443
{

444
	sctp_assoc_sync_pmtu(sk, asoc);
445
446
447
	asoc->pmtu_pending = 0;
}

448
449
450
451
452
static inline bool sctp_chunk_pending(const struct sctp_chunk *chunk)
{
	return !list_empty(&chunk->list);
}

Linus Torvalds's avatar
Linus Torvalds committed
453
454
455
456
457
458
/* 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)\
459
_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member)
Linus Torvalds's avatar
Linus Torvalds committed
460
461
462

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

#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));\
473
     (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\
Linus Torvalds's avatar
Linus Torvalds committed
474
     ntohs(err->length) >= sizeof(sctp_errhdr_t); \
475
     err = (sctp_errhdr_t *)((void *)err + SCTP_PAD4(ntohs(err->length))))
Linus Torvalds's avatar
Linus Torvalds committed
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
502
503
504
505

#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;
506
	}
Linus Torvalds's avatar
Linus Torvalds committed
507
508
509
}

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

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

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

535
536
#define sctp_for_each_hentry(epb, head) \
	hlist_for_each_entry(epb, head, node)
537

Linus Torvalds's avatar
Linus Torvalds committed
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
567
568
569
570
/* 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)
{
571
572
573
574
575
	__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
576
	addr->v6.sin6_family = AF_INET6;
577
578
	addr->v6.sin6_flowinfo = 0;
	addr->v6.sin6_scope_id = 0;
Linus Torvalds's avatar
Linus Torvalds committed
579
580
581
582
583
	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);
}

584
585
586
587
588
/* 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)
{
589
	if (t->dst && !dst_check(t->dst, t->dst_cookie)) {
590
591
592
593
594
595
596
		dst_release(t->dst);
		t->dst = NULL;
	}

	return t->dst;
}

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