Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2001-2003 FhG Fokus |
3 | | * Copyright (C) 2006 Voice Sistem SRL |
4 | | * |
5 | | * This file is part of opensips, a free SIP server. |
6 | | * |
7 | | * opensips is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version |
11 | | * |
12 | | * opensips is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU General Public License |
18 | | * along with this program; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | * |
21 | | * History: |
22 | | * -------- |
23 | | * 2003-03-19 replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei) |
24 | | * 2006-12-22 added script flags (bogdan) |
25 | | */ |
26 | | |
27 | | /*! |
28 | | * \file |
29 | | * \brief OpenSIPS configuration flag functions. |
30 | | */ |
31 | | |
32 | | |
33 | | #include "sr_module.h" |
34 | | #include "dprint.h" |
35 | | #include "parser/msg_parser.h" |
36 | | #include "mem/mem.h" |
37 | | #include "ut.h" |
38 | | #include "flags.h" |
39 | | |
40 | | /* several lists of maximum MAX_FLAG flags */ |
41 | | struct flag_entry *flag_lists[FLAG_LIST_COUNT]; |
42 | | |
43 | | /* buffer used to offer string representations of flag bitmasks */ |
44 | | static char print_buffer[PRINT_BUFFER_SIZE]; |
45 | | |
46 | | /*********************** msg flags ****************************/ |
47 | | |
48 | | int setflag(struct sip_msg* msg, flag_t flag) |
49 | 0 | { |
50 | | #ifdef EXTRA_DEBUG |
51 | | LM_DBG("mflags for %p : (%u, %u)\n", msg, flag, msg->flags); |
52 | | #endif |
53 | 0 | msg->flags |= 1 << flag; |
54 | 0 | return 1; |
55 | 0 | } |
56 | | |
57 | | int resetflag(struct sip_msg* msg, flag_t flag) |
58 | 0 | { |
59 | | #ifdef EXTRA_DEBUG |
60 | | LM_DBG("mflags for %p : (%u, %u)\n", msg, flag, msg->flags); |
61 | | #endif |
62 | 0 | msg->flags &= ~ (1 << flag); |
63 | 0 | return 1; |
64 | 0 | } |
65 | | |
66 | | int isflagset(struct sip_msg* msg, flag_t flag) |
67 | 0 | { |
68 | | #ifdef EXTRA_DEBUG |
69 | | LM_DBG("mflags for %p : (%u, %u)\n", msg, flag, msg->flags); |
70 | | #endif |
71 | 0 | return (msg->flags & (1<<flag)) ? 1 : -1; |
72 | 0 | } |
73 | | |
74 | 0 | int flag_in_range( flag_t flag ) { |
75 | 0 | if ( flag > MAX_FLAG ) { |
76 | 0 | LM_ERR("message flag (%d) must be in range %d..%d\n", |
77 | 0 | flag, 1, MAX_FLAG ); |
78 | 0 | return 0; |
79 | 0 | } |
80 | 0 | return 1; |
81 | 0 | } |
82 | | |
83 | | int flag_idx2mask(int *flag) |
84 | 0 | { |
85 | 0 | if (*flag<0) { |
86 | 0 | *flag = 0; |
87 | 0 | } else if (*flag>(int)MAX_FLAG) { |
88 | 0 | LM_ERR("flag %d out of range\n",*flag); |
89 | 0 | return -1; |
90 | 0 | } else { |
91 | 0 | *flag = 1<<(*flag); |
92 | 0 | } |
93 | 0 | return 0; |
94 | 0 | } |
95 | | |
96 | | str bitmask_to_flag_list(enum flag_type type, int bitmask) |
97 | 0 | { |
98 | 0 | struct flag_entry *entry; |
99 | 0 | str ret; |
100 | |
|
101 | | #ifdef EXTRA_DEBUG |
102 | | LM_DBG("bitmask -> %u\n", bitmask); |
103 | | #endif |
104 | 0 | ret.s = print_buffer; |
105 | 0 | ret.len = 0; |
106 | 0 | for (entry = flag_lists[type]; entry; entry = entry->next) { |
107 | |
|
108 | 0 | if (bitmask & (1 << entry->bit)) { |
109 | 0 | memcpy(ret.s + ret.len, entry->name.s, entry->name.len); |
110 | 0 | ret.len += entry->name.len; |
111 | |
|
112 | 0 | ret.s[ret.len++] = FLAG_DELIM; |
113 | 0 | } |
114 | 0 | } |
115 | |
|
116 | 0 | if (ret.len > 0) |
117 | 0 | ret.len--; |
118 | |
|
119 | 0 | return ret; |
120 | 0 | } |
121 | | |
122 | | int flag_list_to_bitmask(const str_const *flags, enum flag_type type, char delim, |
123 | | int init_new_flags) |
124 | 0 | { |
125 | 0 | const char *p, *lim; |
126 | 0 | const char *crt_flag; |
127 | 0 | str_const name; |
128 | 0 | struct flag_entry *e; |
129 | 0 | int ret = 0; |
130 | 0 | int id; |
131 | |
|
132 | 0 | if (flags->len < 0) |
133 | 0 | return 0; |
134 | | |
135 | | #ifdef EXTRA_DEBUG |
136 | | LM_DBG("flag_list -> '%.*s'\n", flags->len, flags->s); |
137 | | #endif |
138 | 0 | lim = flags->s + flags->len; |
139 | 0 | crt_flag = flags->s; |
140 | 0 | for (p = flags->s; p <= lim; p++) { |
141 | |
|
142 | 0 | if (p == lim || *p == delim) { |
143 | |
|
144 | 0 | name.s = crt_flag; |
145 | 0 | name.len = p - crt_flag; |
146 | 0 | for (e = flag_lists[type]; e; e = e->next) { |
147 | 0 | if (e->name.len == p - crt_flag && |
148 | 0 | str_strcmp(&e->name, &name) == 0) { |
149 | |
|
150 | 0 | ret |= 1 << e->bit; |
151 | 0 | break; |
152 | 0 | } |
153 | 0 | } |
154 | |
|
155 | 0 | if (init_new_flags && !e) { |
156 | 0 | id = get_flag_id_by_name(type, (char*)name.s, name.len); |
157 | 0 | if (id >= 0) |
158 | 0 | ret |= 1 << id; |
159 | 0 | } |
160 | |
|
161 | 0 | crt_flag = p + 1; |
162 | 0 | } |
163 | 0 | } |
164 | |
|
165 | 0 | return ret; |
166 | 0 | } |
167 | | |
168 | | /** |
169 | | * The function MUST be called only in the pre-forking phases of OpenSIPS |
170 | | * (mod_init() or in function fixups) |
171 | | */ |
172 | | int get_flag_id_by_name(int flag_type, char *flag_name, int flag_name_len) |
173 | 0 | { |
174 | 0 | struct flag_entry *it, **flag_list; |
175 | 0 | str fn; |
176 | |
|
177 | 0 | if (!flag_name) { |
178 | 0 | LM_DBG("Flag name is null!\n"); |
179 | 0 | return -1; |
180 | 0 | } |
181 | | |
182 | 0 | fn.s = flag_name; |
183 | 0 | fn.len = (flag_name_len<=0)?strlen(flag_name):flag_name_len; |
184 | |
|
185 | 0 | if (fn.len == 0) { |
186 | 0 | LM_WARN("found empty string flag modparam! possible scripting error?\n"); |
187 | 0 | return -1; |
188 | 0 | } |
189 | | |
190 | 0 | if (flag_type < 0 || flag_type >= FLAG_LIST_COUNT) { |
191 | 0 | LM_ERR("Invalid flag list: %d\n", flag_type); |
192 | 0 | return -2; |
193 | 0 | } |
194 | | |
195 | 0 | flag_list = flag_lists + flag_type; |
196 | |
|
197 | 0 | if (*flag_list && (*flag_list)->bit == MAX_FLAG) { |
198 | 0 | LM_CRIT("Maximum number of message flags reached! (32 flags)\n"); |
199 | 0 | return E_CFG; |
200 | 0 | } |
201 | | |
202 | | /* Check if flag has been already defined */ |
203 | 0 | for (it = *flag_list; it; it = it->next) { |
204 | 0 | if (str_strcmp(&it->name, &fn) == 0) { |
205 | |
|
206 | 0 | return it->bit; |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | 0 | if (!(it = pkg_malloc(sizeof(*it) + fn.len))) { |
211 | 0 | LM_CRIT("Out of memory!\n"); |
212 | 0 | return E_OUT_OF_MEM; |
213 | 0 | } |
214 | | |
215 | 0 | it->name.s = (char *)(it + 1); |
216 | 0 | it->name.len = fn.len; |
217 | 0 | memcpy(it->name.s, fn.s, fn.len); |
218 | |
|
219 | 0 | it->bit = (*flag_list ? (*flag_list)->bit + 1 : 0); |
220 | |
|
221 | 0 | it->next = *flag_list; |
222 | 0 | *flag_list = it; |
223 | |
|
224 | 0 | LM_DBG("New flag: [ %.*s : %d ][%d]\n", fn.len, fn.s, it->bit, flag_type); |
225 | 0 | return it->bit; |
226 | 0 | } |
227 | | |
228 | | unsigned int fixup_flag(int flag_type, const str *flag_name) |
229 | 0 | { |
230 | 0 | int ret; |
231 | |
|
232 | 0 | ret = get_flag_id_by_name(flag_type, flag_name->s, flag_name->len); |
233 | |
|
234 | 0 | if (ret < 0) { |
235 | 0 | LM_CRIT("Failed to get a flag id!\n"); |
236 | 0 | return NAMED_FLAG_ERROR; |
237 | 0 | } |
238 | | |
239 | 0 | if (flag_type != FLAG_TYPE_MSG) |
240 | 0 | return 1 << ret; |
241 | | |
242 | 0 | return ret; |
243 | 0 | } |