]> jfr.im git - solanum.git/blame - ircd/capability.c
Merge pull request #313 from edk0/spoof-chban
[solanum.git] / ircd / capability.c
CommitLineData
64b56afd
AC
1/*
2 * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 */
20
21#include "stdinc.h"
22#include "capability.h"
a4bf26dd 23#include "rb_dictionary.h"
77d3d2db 24#include "s_assert.h"
64b56afd 25
885cd603
AC
26static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
27
32df5e96
AC
28struct CapabilityEntry *
29capability_find(struct CapabilityIndex *idx, const char *cap)
30{
31 s_assert(idx != NULL);
32 if (cap == NULL)
33 return NULL;
34
a4bf26dd 35 return rb_dictionary_retrieve(idx->cap_dict, cap);
32df5e96
AC
36}
37
64b56afd 38unsigned int
63b9db96 39capability_get(struct CapabilityIndex *idx, const char *cap, void **ownerdata)
64b56afd
AC
40{
41 struct CapabilityEntry *entry;
42
bde42c60 43 s_assert(idx != NULL);
d7e4ed77
AC
44 if (cap == NULL)
45 return 0;
64b56afd 46
a4bf26dd 47 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
5058c8eb 48 if (entry != NULL && !(entry->flags & CAP_ORPHANED))
63b9db96
AC
49 {
50 if (ownerdata != NULL)
51 *ownerdata = entry->ownerdata;
8bedf01d 52 return (1 << entry->value);
63b9db96 53 }
64b56afd 54
8d20b088 55 return 0;
64b56afd
AC
56}
57
58unsigned int
63b9db96 59capability_put(struct CapabilityIndex *idx, const char *cap, void *ownerdata)
64b56afd
AC
60{
61 struct CapabilityEntry *entry;
62
bde42c60
JT
63 s_assert(idx != NULL);
64 if (!idx->highest_bit)
8bedf01d 65 return 0xFFFFFFFF;
64b56afd 66
a4bf26dd 67 if ((entry = rb_dictionary_retrieve(idx->cap_dict, cap)) != NULL)
64b56afd 68 {
5058c8eb 69 entry->flags &= ~CAP_ORPHANED;
8bedf01d 70 return (1 << entry->value);
64b56afd
AC
71 }
72
73 entry = rb_malloc(sizeof(struct CapabilityEntry));
94afbe9c 74 entry->cap = rb_strdup(cap);
5058c8eb 75 entry->flags = 0;
bde42c60 76 entry->value = idx->highest_bit;
63b9db96 77 entry->ownerdata = ownerdata;
64b56afd 78
a4bf26dd 79 rb_dictionary_add(idx->cap_dict, entry->cap, entry);
64b56afd 80
bde42c60
JT
81 idx->highest_bit++;
82 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
83 idx->highest_bit = 0;
64b56afd 84
8bedf01d 85 return (1 << entry->value);
64b56afd
AC
86}
87
22cae20f
JT
88unsigned int
89capability_put_anonymous(struct CapabilityIndex *idx)
90{
91 unsigned int value;
92
93 s_assert(idx != NULL);
94 if (!idx->highest_bit)
95 return 0xFFFFFFFF;
96 value = 1 << idx->highest_bit;
97 idx->highest_bit++;
98 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
99 idx->highest_bit = 0;
100 return value;
101}
102
64b56afd 103void
bde42c60 104capability_orphan(struct CapabilityIndex *idx, const char *cap)
64b56afd
AC
105{
106 struct CapabilityEntry *entry;
107
bde42c60 108 s_assert(idx != NULL);
64b56afd 109
a4bf26dd 110 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
64b56afd 111 if (entry != NULL)
f01f67f0
AC
112 {
113 entry->flags &= ~CAP_REQUIRED;
5058c8eb 114 entry->flags |= CAP_ORPHANED;
2e4bf32f 115 entry->ownerdata = NULL;
f01f67f0
AC
116 }
117}
118
119void
bde42c60 120capability_require(struct CapabilityIndex *idx, const char *cap)
f01f67f0
AC
121{
122 struct CapabilityEntry *entry;
123
bde42c60 124 s_assert(idx != NULL);
f01f67f0 125
a4bf26dd 126 entry = rb_dictionary_retrieve(idx->cap_dict, cap);
f01f67f0
AC
127 if (entry != NULL)
128 entry->flags |= CAP_REQUIRED;
64b56afd
AC
129}
130
131static void
4177311e 132capability_destroy(rb_dictionary_element *delem, void *privdata)
64b56afd
AC
133{
134 s_assert(delem != NULL);
135
94afbe9c
JV
136 struct CapabilityEntry *entry = delem->data;
137 rb_free((char *)entry->cap);
138 rb_free(entry);
64b56afd
AC
139}
140
141struct CapabilityIndex *
885cd603 142capability_index_create(const char *name)
64b56afd 143{
bde42c60 144 struct CapabilityIndex *idx;
64b56afd 145
bde42c60 146 idx = rb_malloc(sizeof(struct CapabilityIndex));
ba832267 147 idx->name = name;
f956cb0f 148 idx->cap_dict = rb_dictionary_create(name, rb_strcasecmp);
bde42c60 149 idx->highest_bit = 1;
64b56afd 150
885cd603
AC
151 rb_dlinkAdd(idx, &idx->node, &capability_indexes);
152
bde42c60 153 return idx;
64b56afd
AC
154}
155
156void
bde42c60 157capability_index_destroy(struct CapabilityIndex *idx)
64b56afd 158{
bde42c60 159 s_assert(idx != NULL);
64b56afd 160
885cd603
AC
161 rb_dlinkDelete(&idx->node, &capability_indexes);
162
a4bf26dd 163 rb_dictionary_destroy(idx->cap_dict, capability_destroy, NULL);
bde42c60 164 rb_free(idx);
64b56afd 165}
5e773521
AC
166
167const char *
bde42c60 168capability_index_list(struct CapabilityIndex *idx, unsigned int cap_mask)
5e773521 169{
4177311e 170 rb_dictionary_iter iter;
5e773521
AC
171 struct CapabilityEntry *entry;
172 static char buf[BUFSIZE];
173 char *t = buf;
174 int tl;
175
bde42c60 176 s_assert(idx != NULL);
5e773521
AC
177
178 *t = '\0';
179
56f84ded 180 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
5e773521 181 {
33b214fa 182 if ((1 << entry->value) & cap_mask)
5e773521 183 {
5203cba5 184 tl = sprintf(t, "%s ", entry->cap);
5e773521
AC
185 t += tl;
186 }
187 }
188
189 t--;
190 *t = '\0';
191
192 return buf;
193}
ec3a9055
AC
194
195unsigned int
bde42c60 196capability_index_mask(struct CapabilityIndex *idx)
ec3a9055 197{
4177311e 198 rb_dictionary_iter iter;
ec3a9055
AC
199 struct CapabilityEntry *entry;
200 unsigned int mask = 0;
201
bde42c60 202 s_assert(idx != NULL);
ec3a9055 203
56f84ded 204 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
ec3a9055 205 {
0582290f 206 if (!(entry->flags & CAP_ORPHANED))
8bedf01d 207 mask |= (1 << entry->value);
ec3a9055
AC
208 }
209
210 return mask;
211}
f01f67f0
AC
212
213unsigned int
bde42c60 214capability_index_get_required(struct CapabilityIndex *idx)
f01f67f0 215{
4177311e 216 rb_dictionary_iter iter;
f01f67f0
AC
217 struct CapabilityEntry *entry;
218 unsigned int mask = 0;
219
bde42c60 220 s_assert(idx != NULL);
f01f67f0 221
56f84ded 222 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
f01f67f0
AC
223 {
224 if (!(entry->flags & CAP_ORPHANED) && (entry->flags & CAP_REQUIRED))
8bedf01d 225 mask |= (1 << entry->value);
f01f67f0
AC
226 }
227
228 return mask;
229}
a16910aa
AC
230
231void
232capability_index_stats(void (*cb)(const char *line, void *privdata), void *privdata)
233{
234 rb_dlink_node *node;
235 char buf[BUFSIZE];
236
237 RB_DLINK_FOREACH(node, capability_indexes.head)
238 {
239 struct CapabilityIndex *idx = node->data;
4177311e 240 rb_dictionary_iter iter;
a16910aa
AC
241 struct CapabilityEntry *entry;
242
5203cba5 243 snprintf(buf, sizeof buf, "'%s': allocated bits - %d", idx->name, (idx->highest_bit - 1));
a16910aa
AC
244 cb(buf, privdata);
245
56f84ded 246 RB_DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
a16910aa 247 {
5203cba5 248 snprintf(buf, sizeof buf, "bit %d: '%s'", entry->value, entry->cap);
a16910aa
AC
249 cb(buf, privdata);
250 }
251
5203cba5 252 snprintf(buf, sizeof buf, "'%s': remaining bits - %u", idx->name,
0c5e50f4 253 (unsigned int)((sizeof(unsigned int) * 8) - (idx->highest_bit - 1)));
a16910aa
AC
254 cb(buf, privdata);
255 }
256
5203cba5 257 snprintf(buf, sizeof buf, "%ld capability indexes", rb_dlink_list_length(&capability_indexes));
a16910aa
AC
258 cb(buf, privdata);
259}