1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39#include <linux/types.h>
40#include <linux/slab.h>
41#include <net/sctp/sctp.h>
42#include <net/sctp/sm.h>
43
44static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
45 __u16 out);
46
47
48
49
50static inline size_t sctp_ssnmap_size(__u16 in, __u16 out)
51{
52 return sizeof(struct sctp_ssnmap) + (in + out) * sizeof(__u16);
53}
54
55
56
57
58
59struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
60 gfp_t gfp)
61{
62 struct sctp_ssnmap *retval;
63 int size;
64
65 size = sctp_ssnmap_size(in, out);
66 if (size <= KMALLOC_MAX_SIZE)
67 retval = kmalloc(size, gfp);
68 else
69 retval = (struct sctp_ssnmap *)
70 __get_free_pages(gfp, get_order(size));
71 if (!retval)
72 goto fail;
73
74 if (!sctp_ssnmap_init(retval, in, out))
75 goto fail_map;
76
77 SCTP_DBG_OBJCNT_INC(ssnmap);
78
79 return retval;
80
81fail_map:
82 if (size <= KMALLOC_MAX_SIZE)
83 kfree(retval);
84 else
85 free_pages((unsigned long)retval, get_order(size));
86fail:
87 return NULL;
88}
89
90
91
92static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
93 __u16 out)
94{
95 memset(map, 0x00, sctp_ssnmap_size(in, out));
96
97
98 map->in.ssn = (__u16 *)&map[1];
99 map->in.len = in;
100
101
102 map->out.ssn = &map->in.ssn[in];
103 map->out.len = out;
104
105 return map;
106}
107
108
109void sctp_ssnmap_clear(struct sctp_ssnmap *map)
110{
111 size_t size;
112
113 size = (map->in.len + map->out.len) * sizeof(__u16);
114 memset(map->in.ssn, 0x00, size);
115}
116
117
118void sctp_ssnmap_free(struct sctp_ssnmap *map)
119{
120 int size;
121
122 if (unlikely(!map))
123 return;
124
125 size = sctp_ssnmap_size(map->in.len, map->out.len);
126 if (size <= KMALLOC_MAX_SIZE)
127 kfree(map);
128 else
129 free_pages((unsigned long)map, get_order(size));
130
131 SCTP_DBG_OBJCNT_DEC(ssnmap);
132}
133