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