| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- /*
- * $Id$
- *
- * Route & Record-Route header field parser
- *
- * Copyright (C) 2001-2003 Fhg Fokus
- *
- * This file is part of ser, a free SIP server.
- *
- * ser is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * For a license to use the ser software under conditions
- * other than those described here, or to purchase support for this
- * software, please contact iptel.org by e-mail at the following addresses:
- * [email protected]
- *
- * ser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <string.h>
- #include "parse_rr.h"
- #include "../mem/mem.h"
- #include "../mem/shm_mem.h"
- #include "../dprint.h"
- #include "../trim.h"
- #include "../ut.h"
- /*
- * Parse Route and Record-Route header fields
- */
- int parse_rr(struct hdr_field* _h)
- {
- rr_t* r, *last;
- str s;
- param_hooks_t hooks;
- if (!_h) {
- LOG(L_ERR, "parse_rr(): Invalid parameter value\n");
- return -1;
- }
- if (_h->parsed) {
- /* Already parsed, return */
- return 0;
- }
- /* Make a temporary copy of the string pointer */
- s.s = _h->body.s;
- s.len = _h->body.len;
- trim_leading(&s);
- last = 0;
- while(1) {
- /* Allocate and clear rr stucture */
- r = (rr_t*)pkg_malloc(sizeof(rr_t));
- if (!r) {
- LOG(L_ERR, "parse_rr(): No memory left\n");
- goto error;
- }
- memset(r, 0, sizeof(rr_t));
-
- /* Parse name-addr part of the header */
- if (parse_nameaddr(&s, &r->nameaddr) < 0) {
- LOG(L_ERR, "parse_rr(): Error while parsing name-addr\n");
- goto error;
- }
- r->len = r->nameaddr.len;
- /* Shift just behind the closing > */
- s.s = r->nameaddr.name.s + r->nameaddr.len; /* Point just behind > */
- s.len -= r->nameaddr.len;
- trim_leading(&s); /* Skip any whitechars */
-
- /* Nothing left, finish */
- if (s.len == 0) goto ok;
-
- if (s.s[0] == ';') { /* Contact parameter found */
- s.s++;
- s.len--;
- trim_leading(&s);
-
- if (s.len == 0) {
- LOG(L_ERR, "parse_rr(): Error while parsing params\n");
- goto error;
- }
- /* Parse all parameters */
- if (parse_params(&s, CLASS_ANY, &hooks, &r->params) < 0) {
- LOG(L_ERR, "parse_rr(): Error while parsing params\n");
- goto error;
- }
- r->len = r->params->name.s + r->params->len - r->nameaddr.name.s;
- /* Copy hooks */
- /*r->r2 = hooks.rr.r2; */
- trim_leading(&s);
- if (s.len == 0) goto ok;
- }
- if (s.s[0] != ',') {
- LOG(L_ERR, "parse_rr(): Invalid character '%c', comma expected\n", s.s[0]);
- goto error;
- }
- /* Next character is comma or end of header*/
- s.s++;
- s.len--;
- trim_leading(&s);
- if (s.len == 0) {
- LOG(L_ERR, "parse_rr(): Text after comma missing\n");
- goto error;
- }
- /* Append the structure as last parameter of the linked list */
- if (!_h->parsed) _h->parsed = (void*)r;
- if (last) last->next = r;
- last = r;
- }
- error:
- if (r) pkg_free(r);
- free_rr((rr_t**)&_h->parsed); /* Free any contacts created so far */
- return -1;
- ok:
- if (!_h->parsed) _h->parsed = (void*)r;
- if (last) last->next = r;
- return 0;
- }
- /*
- * Free list of rrs
- * _r is head of the list
- */
- static inline void do_free_rr(rr_t** _r, int _shm)
- {
- rr_t* ptr;
- while(*_r) {
- ptr = *_r;
- *_r = (*_r)->next;
- if (ptr->params) {
- if (_shm) shm_free_params(ptr->params);
- else free_params(ptr->params);
- }
- if (_shm) shm_free(ptr);
- else pkg_free(ptr);
- }
- }
- /*
- * Free list of rrs
- * _r is head of the list
- */
- void free_rr(rr_t** _r)
- {
- do_free_rr(_r, 0);
- }
- /*
- * Free list of rrs
- * _r is head of the list
- */
- void shm_free_rr(rr_t** _r)
- {
- do_free_rr(_r, 1);
- }
- /*
- * Print list of RRs, just for debugging
- */
- void print_rr(FILE* _o, rr_t* _r)
- {
- rr_t* ptr;
- ptr = _r;
- while(ptr) {
- fprintf(_o, "---RR---\n");
- print_nameaddr(_o, &ptr->nameaddr);
- fprintf(_o, "r2 : %p\n", ptr->r2);
- if (ptr->params) {
- print_params(_o, ptr->params);
- }
- fprintf(_o, "len: %d\n", ptr->len);
- fprintf(_o, "---/RR---\n");
- ptr = ptr->next;
- }
- }
- /*
- * Translate all pointers in the structure and also
- * in all parameters in the list
- */
- static inline void xlate_pointers(rr_t* _orig, rr_t* _r)
- {
- param_t* ptr;
- _r->nameaddr.uri.s = translate_pointer(_r->nameaddr.name.s, _orig->nameaddr.name.s, _r->nameaddr.uri.s);
-
- ptr = _r->params;
- while(ptr) {
- /* if (ptr->type == P_R2) _r->r2 = ptr; */
- ptr->name.s = translate_pointer(_r->nameaddr.name.s, _orig->nameaddr.name.s, ptr->name.s);
- ptr->body.s = translate_pointer(_r->nameaddr.name.s, _orig->nameaddr.name.s, ptr->body.s);
- ptr = ptr->next;
- }
- }
- /*
- * Duplicate a single rr_t structure using pkg_malloc or shm_malloc
- */
- static inline int do_duplicate_rr(rr_t** _new, rr_t* _r, int _shm)
- {
- int len, ret;
- rr_t* res;
- if (!_new || !_r) {
- LOG(L_ERR, "duplicate_rr(): Invalid parameter value\n");
- return -1;
- }
- if (_r->params) {
- len = _r->params->name.s + _r->params->len - _r->nameaddr.name.s;
- } else {
- len = _r->nameaddr.len;
- }
- if (_shm) res = shm_malloc(sizeof(rr_t) + len);
- else res = pkg_malloc(sizeof(rr_t) + len);
- if (!res) {
- LOG(L_ERR, "duplicate_rr(): No memory left\n");
- return -2;
- }
- memcpy(res, _r, sizeof(rr_t));
- res->nameaddr.name.s = (char*)res + sizeof(rr_t);
- memcpy(res->nameaddr.name.s, _r->nameaddr.name.s, len);
- if (_shm) {
- ret = shm_duplicate_params(&res->params, _r->params);
- } else {
- ret = duplicate_params(&res->params, _r->params);
- }
- if (ret < 0) {
- LOG(L_ERR, "Error while duplicating parameters\n");
- if (_shm) shm_free(res);
- else pkg_free(res);
- return -3;
- }
- xlate_pointers(_r, res);
- *_new = res;
- return 0;
- }
- /*
- * Duplicate a single rr_t structure using pkg_malloc
- */
- int duplicate_rr(rr_t** _new, rr_t* _r)
- {
- return do_duplicate_rr(_new, _r, 0);
- }
- /*
- * Duplicate a single rr_t structure using pkg_malloc
- */
- int shm_duplicate_rr(rr_t** _new, rr_t* _r)
- {
- return do_duplicate_rr(_new, _r, 1);
- }
|