00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <string.h>
00030 #include "../str.h"
00031 #include "../ut.h"
00032 #include "../dprint.h"
00033 #include "../trim.h"
00034 #include "../mem/mem.h"
00035 #include "../mem/shm_mem.h"
00036 #include "parse_param.h"
00037
00038
00039
00040
00041
00042
00043 static inline void parse_contact_class(param_hooks_t* _h, param_t* _p)
00044 {
00045
00046 if (!_p->name.s) {
00047 LM_ERR("empty value\n");
00048 return;
00049 }
00050 switch(_p->name.s[0]) {
00051 case 'q':
00052 case 'Q':
00053 if (_p->name.len == 1) {
00054 _p->type = P_Q;
00055 _h->contact.q = _p;
00056 }
00057 break;
00058
00059 case 'e':
00060 case 'E':
00061 if ((_p->name.len == 7) &&
00062 (!strncasecmp(_p->name.s + 1, "xpires", 6))) {
00063 _p->type = P_EXPIRES;
00064 _h->contact.expires = _p;
00065 }
00066 break;
00067
00068 case 'm':
00069 case 'M':
00070 if ((_p->name.len == 7) &&
00071 (!strncasecmp(_p->name.s + 1, "ethods", 6))) {
00072 _p->type = P_METHODS;
00073 _h->contact.methods = _p;
00074 }
00075 break;
00076
00077 case 'r':
00078 case 'R':
00079 if ((_p->name.len == 8) &&
00080 (!strncasecmp(_p->name.s + 1, "eceived", 7))) {
00081 _p->type = P_RECEIVED;
00082 _h->contact.received = _p;
00083 }
00084 break;
00085 }
00086 }
00087
00088
00089
00090
00091
00092
00093 static inline void parse_uri_class(param_hooks_t* _h, param_t* _p)
00094 {
00095
00096 if (!_p->name.s) {
00097 LM_ERR("empty value\n");
00098 return;
00099 }
00100 switch(_p->name.s[0]) {
00101 case 't':
00102 case 'T':
00103 if ((_p->name.len == 9) &&
00104 (!strncasecmp(_p->name.s + 1, "ransport", 8))) {
00105 _p->type = P_TRANSPORT;
00106 _h->uri.transport = _p;
00107 } else if (_p->name.len == 2) {
00108 if (((_p->name.s[1] == 't') || (_p->name.s[1] == 'T')) &&
00109 ((_p->name.s[2] == 'l') || (_p->name.s[2] == 'L'))) {
00110 _p->type = P_TTL;
00111 _h->uri.ttl = _p;
00112 }
00113 }
00114 break;
00115
00116 case 'l':
00117 case 'L':
00118 if ((_p->name.len == 2) && ((_p->name.s[1] == 'r') || (_p->name.s[1] == 'R'))) {
00119 _p->type = P_LR;
00120 _h->uri.lr = _p;
00121 }
00122 break;
00123
00124 case 'r':
00125 case 'R':
00126 if ((_p->name.len == 2) && (_p->name.s[1] == '2')) {
00127 _p->type = P_R2;
00128 _h->uri.r2 = _p;
00129 }
00130 break;
00131
00132 case 'm':
00133 case 'M':
00134 if ((_p->name.len == 5) &&
00135 (!strncasecmp(_p->name.s + 1, "addr", 4))) {
00136 _p->type = P_MADDR;
00137 _h->uri.maddr = _p;
00138 }
00139 break;
00140
00141 case 'd':
00142 case 'D':
00143 if ((_p->name.len == 5) &&
00144 (!strncasecmp(_p->name.s + 1, "stip", 4))) {
00145 _p->type = P_DSTIP;
00146 _h->uri.dstip = _p;
00147 } else if ((_p->name.len == 7) &&
00148 (!strncasecmp(_p->name.s + 1, "stport", 6))) {
00149 _p->type = P_DSTPORT;
00150 _h->uri.dstport = _p;
00151 }
00152 break;
00153 }
00154
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 static inline int parse_quoted_param(str* _s, str* _r)
00166 {
00167 char* end_quote;
00168
00169
00170
00171
00172 if (_s->len < 2) {
00173 return -1;
00174 }
00175
00176
00177 _s->s++;
00178 _s->len--;
00179
00180
00181
00182 end_quote = memchr(_s->s, '\"', _s->len);
00183
00184
00185 if (!end_quote) {
00186 return -2;
00187 }
00188
00189
00190
00191
00192 _r->s = _s->s;
00193 _r->len = end_quote - _s->s;
00194
00195
00196
00197
00198 _s->len -= (end_quote - _s->s + 1);
00199 _s->s = end_quote + 1;
00200
00201
00202 return 0;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211 static inline int parse_token_param(str* _s, str* _r)
00212 {
00213 int i;
00214
00215
00216
00217
00218 if (_s->len == 0) {
00219 return -1;
00220 }
00221
00222
00223
00224
00225 _r->s = _s->s;
00226
00227
00228
00229
00230 for(i = 0; i < _s->len; i++) {
00231
00232
00233
00234
00235 switch(_s->s[i]) {
00236 case ' ':
00237 case '\t':
00238 case '\r':
00239 case '\n':
00240 case ',':
00241 case ';':
00242
00243
00244
00245
00246 goto out;
00247 }
00248 }
00249 out:
00250 if (i == 0) {
00251 return -1;
00252 }
00253
00254
00255 _r->len = i;
00256
00257
00258
00259
00260 _s->s = _s->s + i;
00261 _s->len -= i;
00262
00263
00264 return 0;
00265 }
00266
00267
00268
00269
00270
00271 static inline void parse_param_name(str* _s, pclass_t _c, param_hooks_t* _h, param_t* _p)
00272 {
00273
00274 if (!_s->s) {
00275 LM_DBG("empty parameter\n");
00276 return;
00277 }
00278
00279 _p->name.s = _s->s;
00280
00281 while(_s->len) {
00282 switch(_s->s[0]) {
00283 case ' ':
00284 case '\t':
00285 case '\r':
00286 case '\n':
00287 case ';':
00288 case ',':
00289 case '=':
00290 goto out;
00291 }
00292 _s->s++;
00293 _s->len--;
00294 }
00295
00296 out:
00297 _p->name.len = _s->s - _p->name.s;
00298
00299 switch(_c) {
00300 case CLASS_CONTACT: parse_contact_class(_h, _p); break;
00301 case CLASS_URI: parse_uri_class(_h, _p); break;
00302 default: break;
00303 }
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 static inline int parse_param_body(str* _s, param_t* _c)
00315 {
00316 if (_s->s[0] == '\"') {
00317 if (parse_quoted_param(_s, &(_c->body)) < 0) {
00318 LM_ERR("failed to parse quoted string\n");
00319 return -2;
00320 }
00321 } else {
00322 if (parse_token_param(_s, &(_c->body)) < 0) {
00323 LM_ERR("failed to parse token\n");
00324 return -3;
00325 }
00326 }
00327
00328 return 0;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 int parse_params(str* _s, pclass_t _c, param_hooks_t* _h, param_t** _p)
00342 {
00343 param_t* t;
00344
00345 if (!_s || !_h || !_p) {
00346 LM_ERR("invalid parameter value\n");
00347 return -1;
00348 }
00349
00350 memset(_h, 0, sizeof(param_hooks_t));
00351 *_p = 0;
00352
00353 if (!_s->s) {
00354 LM_DBG("empty uri params, skipping\n");
00355 return 0;
00356 }
00357
00358 while(1) {
00359 t = (param_t*)pkg_malloc(sizeof(param_t));
00360 if (t == 0) {
00361 LM_ERR("no pkg memory left\n");
00362 goto error;
00363 }
00364 memset(t, 0, sizeof(param_t));
00365
00366 parse_param_name(_s, _c, _h, t);
00367 trim_leading(_s);
00368
00369 if (_s->len == 0) {
00370 t->len = t->name.len;
00371 goto ok;
00372 }
00373
00374 if (_s->s[0] == '=') {
00375 _s->s++;
00376 _s->len--;
00377 trim_leading(_s);
00378
00379 if (_s->len == 0) {
00380 LM_ERR("body missing\n");
00381 goto error;
00382 }
00383
00384 if (parse_param_body(_s, t) < 0) {
00385 LM_ERR("failed to parse param body\n");
00386 goto error;
00387 }
00388
00389 t->len = _s->s - t->name.s;
00390
00391 trim_leading(_s);
00392 if (_s->len == 0) {
00393 goto ok;
00394 }
00395 } else {
00396 t->len = t->name.len;
00397 }
00398
00399 if (_s->s[0] == ',') goto ok;
00400 if (_s->s[0] == '>') goto ok;
00401
00402 if (_s->s[0] != ';') {
00403 LM_ERR("invalid character [%c] - expected ;\n", _s->s[0]);
00404 goto error;
00405 }
00406
00407 _s->s++;
00408 _s->len--;
00409 trim_leading(_s);
00410
00411 if (_s->len == 0) {
00412 LM_ERR("param name missing after ;\n");
00413 goto error;
00414 }
00415
00416 t->next = *_p;
00417 *_p = t;
00418 }
00419
00420 error:
00421 if (t) pkg_free(t);
00422 free_params(*_p);
00423 *_p = 0;
00424 return -2;
00425
00426 ok:
00427 t->next = *_p;
00428 *_p = t;
00429 return 0;
00430 }
00431
00432
00433
00434
00435
00436 static inline void do_free_params(param_t* _p, int _shm)
00437 {
00438 param_t* ptr;
00439
00440 while(_p) {
00441 ptr = _p;
00442 _p = _p->next;
00443 if (_shm) shm_free(ptr);
00444 else pkg_free(ptr);
00445 }
00446 }
00447
00448
00449
00450
00451
00452 void free_params(param_t* _p)
00453 {
00454 do_free_params(_p, 0);
00455 }
00456
00457
00458
00459
00460
00461 void shm_free_params(param_t* _p)
00462 {
00463 do_free_params(_p, 1);
00464 }
00465
00466
00467
00468
00469
00470 static inline void print_param(FILE* _o, param_t* _p)
00471 {
00472 char* type;
00473
00474 fprintf(_o, "---param(%p)---\n", _p);
00475
00476 switch(_p->type) {
00477 case P_OTHER: type = "P_OTHER"; break;
00478 case P_Q: type = "P_Q"; break;
00479 case P_EXPIRES: type = "P_EXPIRES"; break;
00480 case P_METHODS: type = "P_METHODS"; break;
00481 case P_TRANSPORT: type = "P_TRANSPORT"; break;
00482 case P_LR: type = "P_LR"; break;
00483 case P_R2: type = "P_R2"; break;
00484 case P_MADDR: type = "P_MADDR"; break;
00485 case P_TTL: type = "P_TTL"; break;
00486 case P_RECEIVED: type = "P_RECEIVED"; break;
00487 case P_DSTIP: type = "P_DSTIP"; break;
00488 case P_DSTPORT: type = "P_DSTPORT"; break;
00489 default: type = "UNKNOWN"; break;
00490 }
00491
00492 fprintf(_o, "type: %s\n", type);
00493 fprintf(_o, "name: \'%.*s\'\n", _p->name.len, _p->name.s);
00494 fprintf(_o, "body: \'%.*s\'\n", _p->body.len, _p->body.s);
00495 fprintf(_o, "len : %d\n", _p->len);
00496 fprintf(_o, "---/param---\n");
00497 }
00498
00499
00500
00501
00502
00503 void print_params(FILE* _o, param_t* _p)
00504 {
00505 param_t* ptr;
00506
00507 ptr = _p;
00508 while(ptr) {
00509 print_param(_o, ptr);
00510 ptr = ptr->next;
00511 }
00512 }
00513
00514
00515
00516
00517
00518 static inline int do_duplicate_params(param_t** _n, param_t* _p, int _shm)
00519 {
00520 param_t* last, *ptr, *t;
00521
00522 if (!_n) {
00523 LM_ERR("invalid parameter value\n");
00524 return -1;
00525 }
00526
00527 last = 0;
00528 *_n = 0;
00529 ptr = _p;
00530 while(ptr) {
00531 if (_shm) {
00532 t = (param_t*)shm_malloc(sizeof(param_t));
00533 } else {
00534 t = (param_t*)pkg_malloc(sizeof(param_t));
00535 }
00536 if (!t) {
00537 LM_ERR("no more pkg memory\n");
00538 goto err;
00539 }
00540 memcpy(t, ptr, sizeof(param_t));
00541 t->next = 0;
00542
00543 if (!*_n) *_n = t;
00544 if (last) last->next = t;
00545 last = t;
00546
00547 ptr = ptr->next;
00548 }
00549 return 0;
00550
00551 err:
00552 do_free_params(*_n, _shm);
00553 return -2;
00554 }
00555
00556
00557
00558
00559
00560 int duplicate_params(param_t** _n, param_t* _p)
00561 {
00562 return do_duplicate_params(_n, _p, 0);
00563 }
00564
00565
00566
00567
00568
00569 int shm_duplicate_params(param_t** _n, param_t* _p)
00570 {
00571 return do_duplicate_params(_n, _p, 1);
00572 }