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
44#define MAX_KMALLOC_SIZE 131072
45
46static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
47 __u16 out);
48
49
50
51
52static inline size_t sctp_ssnmap_size(__u16 in, __u16 out)
53{
54 return sizeof(struct sctp_ssnmap) + (in + out) * sizeof(__u16);
55}
56
57
58
59
60
61struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
62 gfp_t gfp)
63{
64 struct sctp_ssnmap *retval;
65 int size;
66
67 size = sctp_ssnmap_size(in, out);
68 if (size <= MAX_KMALLOC_SIZE)
69 retval = kmalloc(size, gfp);
70 else
71 retval = (struct sctp_ssnmap *)
72 __get_free_pages(gfp, get_order(size));
73 if (!retval)
74 goto fail;
75
76 if (!sctp_ssnmap_init(retval, in, out))
77 goto fail_map;
78
79 retval->malloced = 1;
80 SCTP_DBG_OBJCNT_INC(ssnmap);
81
82 return retval;
83
84fail_map:
85 if (size <= MAX_KMALLOC_SIZE)
86 kfree(retval);
87 else
88 free_pages((unsigned long)retval, get_order(size));
89fail:
90 return NULL;
91}
92
93
94
95static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
96 __u16 out)
97{
98 memset(map, 0x00, sctp_ssnmap_size(in, out));
99
100
101 map->in.ssn = (__u16 *)&map[1];
102 map->in.len = in;
103
104
105 map->out.ssn = &map->in.ssn[in];
106 map->out.len = out;
107
108 return map;
109}
110
111
112void sctp_ssnmap_clear(struct sctp_ssnmap *map)
113{
114 size_t size;
115
116 size = (map->in.len + map->out.len) * sizeof(__u16);
117 memset(map->in.ssn, 0x00, size);
118}
119
120
121void sctp_ssnmap_free(struct sctp_ssnmap *map)
122{
123 if (map && map->malloced) {
124 int size;
125
126 size = sctp_ssnmap_size(map->in.len, map->out.len);
127 if (size <= MAX_KMALLOC_SIZE)
128 kfree(map);
129 else
130 free_pages((unsigned long)map, get_order(size));
131 SCTP_DBG_OBJCNT_DEC(ssnmap);
132 }
133}
134