Coverage Report

Created: 2025-07-09 06:29

/src/opensips/flags.c
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
}