• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SCTP kernel implementation
2  * Copyright (c) 2003 International Business Machines, Corp.
3  *
4  * This file is part of the SCTP kernel implementation
5  *
6  * These functions manipulate sctp SSN tracker.
7  *
8  * This SCTP implementation is free software;
9  * you can redistribute it and/or modify it under the terms of
10  * the GNU General Public License as published by
11  * the Free Software Foundation; either version 2, or (at your option)
12  * any later version.
13  *
14  * This SCTP implementation is distributed in the hope that it
15  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16  *                 ************************
17  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  * See the GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with GNU CC; see the file COPYING.  If not, see
22  * <http://www.gnu.org/licenses/>.
23  *
24  * Please send any bug reports or fixes you make to the
25  * email address(es):
26  *    lksctp developers <linux-sctp@vger.kernel.org>
27  *
28  * Written or modified by:
29  *    Jon Grimm             <jgrimm@us.ibm.com>
30  */
31 
32 #include <linux/types.h>
33 #include <linux/slab.h>
34 #include <net/sctp/sctp.h>
35 #include <net/sctp/sm.h>
36 
37 static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
38 					    __u16 out);
39 
40 /* Storage size needed for map includes 2 headers and then the
41  * specific needs of in or out streams.
42  */
sctp_ssnmap_size(__u16 in,__u16 out)43 static inline size_t sctp_ssnmap_size(__u16 in, __u16 out)
44 {
45 	return sizeof(struct sctp_ssnmap) + (in + out) * sizeof(__u16);
46 }
47 
48 
49 /* Create a new sctp_ssnmap.
50  * Allocate room to store at least 'len' contiguous TSNs.
51  */
sctp_ssnmap_new(__u16 in,__u16 out,gfp_t gfp)52 struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
53 				    gfp_t gfp)
54 {
55 	struct sctp_ssnmap *retval;
56 	int size;
57 
58 	size = sctp_ssnmap_size(in, out);
59 	if (size <= KMALLOC_MAX_SIZE)
60 		retval = kmalloc(size, gfp);
61 	else
62 		retval = (struct sctp_ssnmap *)
63 			  __get_free_pages(gfp, get_order(size));
64 	if (!retval)
65 		goto fail;
66 
67 	if (!sctp_ssnmap_init(retval, in, out))
68 		goto fail_map;
69 
70 	SCTP_DBG_OBJCNT_INC(ssnmap);
71 
72 	return retval;
73 
74 fail_map:
75 	if (size <= KMALLOC_MAX_SIZE)
76 		kfree(retval);
77 	else
78 		free_pages((unsigned long)retval, get_order(size));
79 fail:
80 	return NULL;
81 }
82 
83 
84 /* Initialize a block of memory as a ssnmap.  */
sctp_ssnmap_init(struct sctp_ssnmap * map,__u16 in,__u16 out)85 static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
86 					    __u16 out)
87 {
88 	memset(map, 0x00, sctp_ssnmap_size(in, out));
89 
90 	/* Start 'in' stream just after the map header. */
91 	map->in.ssn = (__u16 *)&map[1];
92 	map->in.len = in;
93 
94 	/* Start 'out' stream just after 'in'. */
95 	map->out.ssn = &map->in.ssn[in];
96 	map->out.len = out;
97 
98 	return map;
99 }
100 
101 /* Clear out the ssnmap streams.  */
sctp_ssnmap_clear(struct sctp_ssnmap * map)102 void sctp_ssnmap_clear(struct sctp_ssnmap *map)
103 {
104 	size_t size;
105 
106 	size = (map->in.len + map->out.len) * sizeof(__u16);
107 	memset(map->in.ssn, 0x00, size);
108 }
109 
110 /* Dispose of a ssnmap.  */
sctp_ssnmap_free(struct sctp_ssnmap * map)111 void sctp_ssnmap_free(struct sctp_ssnmap *map)
112 {
113 	int size;
114 
115 	if (unlikely(!map))
116 		return;
117 
118 	size = sctp_ssnmap_size(map->in.len, map->out.len);
119 	if (size <= KMALLOC_MAX_SIZE)
120 		kfree(map);
121 	else
122 		free_pages((unsigned long)map, get_order(size));
123 
124 	SCTP_DBG_OBJCNT_DEC(ssnmap);
125 }
126