📄 record.c
字号:
/* * $Id: record.c,v 1.5 2006/02/14 16:38:33 bogdan_iancu Exp $ * * Route & Record-Route module * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of openser, a free SIP server. * * openser 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 * * openser 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 * * History: * ------- * 2003-04-04 Extracted from common.[ch] (janakj) * 2005-04-10 add_rr_param() function and all corresponing hooks added (bogdan) * 2006-02-14 record_route may take as param a string to be used as RR param; * record_route and record_route_preset accept pseudo-variables in * parameters; add_rr_param may be called from BRANCH and FAILURE * routes (bogdan) */#include <string.h>#include "../../mem/mem.h"#include "../../dprint.h"#include "../../parser/parse_uri.h"#include "../../parser/parse_from.h"#include "../../str.h"#include "../../data_lump.h"#include "record.h"#include "rr_mod.h"#define RR_PREFIX "Record-Route: <sip:"#define RR_PREFIX_LEN (sizeof(RR_PREFIX)-1)#define RR_LR ";lr"#define RR_LR_LEN (sizeof(RR_LR)-1)#define RR_LR_FULL ";lr=on"#define RR_LR_FULL_LEN (sizeof(RR_LR_FULL)-1)#define RR_FROMTAG ";ftag="#define RR_FROMTAG_LEN (sizeof(RR_FROMTAG)-1)#define RR_R2 ";r2=on"#define RR_R2_LEN (sizeof(RR_R2)-1)#define RR_TERM ">"CRLF#define RR_TERM_LEN (sizeof(RR_TERM)-1)#define INBOUND 1 /* Insert inbound Record-Route */#define OUTBOUND 0 /* Insert outbound Record-Route */#define RR_PARAM_BUF_SIZE 512/* RR param buffer - usd for storing RR param which are * added before RR insertion -bogdan */static char rr_param_buf_ptr[RR_PARAM_BUF_SIZE];static str rr_param_buf = {rr_param_buf_ptr,0};static unsigned int rr_param_msg;/* * Extract username from the Request URI * First try to look at the original Request URI and if there * is no username use the new Request URI */static inline int get_username(struct sip_msg* _m, str* _user){ struct sip_uri puri; /* first try to look at r-uri for a username */ if (parse_uri(_m->first_line.u.request.uri.s, _m->first_line.u.request.uri.len, &puri) < 0) { LOG(L_ERR, "get_username(): Error while parsing R-URI\n"); return -1; } /* no username in original uri -- hmm; maybe it is a uri * with just host address and username is in a preloaded route, * which is now no rewritten r-uri (assumed rewriteFromRoute * was called somewhere in script's beginning) */ if (!puri.user.len && _m->new_uri.s) { if (parse_uri(_m->new_uri.s, _m->new_uri.len, &puri) < 0) { LOG(L_ERR, "get_username(): Error while parsing new_uri\n"); return -2; } } _user->s = puri.user.s; _user->len = puri.user.len; return 0;}static inline struct lump *insert_rr_param_lump(struct lump *before, char *s, int l){ struct lump *rrp_l; char *s1; /* duplicate data in pkg mem */ s1 = (char*)pkg_malloc(l); if (s1==0) { LOG(L_ERR,"ERROR:rr:insert_r_param_lump: no more pkg mem (%d)\n",l); return 0; } memcpy( s1, s, l); /* add lump */ rrp_l = insert_new_lump_before( before, s1, l, HDR_RECORDROUTE_T); if (rrp_l==0) { LOG(L_ERR,"ERROR:rr:insert_r_param_lump: failed to add before lump\n"); pkg_free(s1); return 0; } return rrp_l;}/* * build a Record-Route header field */static inline int build_rr(struct lump* _l, struct lump* _l2, str* user, str *tag, str *params, int _inbound){ char* prefix, *suffix, *term, *r2; int suffix_len, prefix_len; char *p; prefix_len = RR_PREFIX_LEN + (user->len ? (user->len + 1) : 0); if (enable_full_lr) { suffix_len = RR_LR_FULL_LEN + (params?params->len:0) + ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0); } else { suffix_len = RR_LR_LEN + (params?params->len:0) + ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0); } prefix = pkg_malloc(prefix_len); suffix = pkg_malloc(suffix_len); term = pkg_malloc(RR_TERM_LEN); r2 = pkg_malloc(RR_R2_LEN); if (!prefix || !suffix || !term || !r2) { LOG(L_ERR, "build_rr(): No memory left\n"); if (suffix) pkg_free(suffix); if (prefix) pkg_free(prefix); if (term) pkg_free(term); if (r2) pkg_free(r2); return -3; } memcpy(prefix, RR_PREFIX, RR_PREFIX_LEN); if (user->len) { memcpy(prefix + RR_PREFIX_LEN, user->s, user->len);#ifdef ENABLE_USER_CHECK /* don't add the ignored user into a RR */ if(i_user.len && i_user.len == user->len && !strncmp(i_user.s, user->s, i_user.len)) { if(prefix[RR_PREFIX_LEN]=='x') prefix[RR_PREFIX_LEN]='y'; else prefix[RR_PREFIX_LEN]='x'; }#endif prefix[RR_PREFIX_LEN + user->len] = '@'; } p = suffix; if (enable_full_lr) { memcpy( p, RR_LR_FULL, RR_LR_FULL_LEN); p += RR_LR_FULL_LEN; } else { memcpy( p, RR_LR, RR_LR_LEN); p += RR_LR_LEN; } if (tag && tag->len) { memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN); p += RR_FROMTAG_LEN; memcpy(p, tag->s, tag->len); p += tag->len; } if (params && params->len) { memcpy(p, params->s, params->len); p += params->len; } memcpy(term, RR_TERM, RR_TERM_LEN); memcpy(r2, RR_R2, RR_R2_LEN); if (!(_l = insert_new_lump_after(_l, prefix, prefix_len, 0))) goto lump_err; prefix = 0; _l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_ALL:SUBST_SND_ALL, 0); if (_l ==0 ) goto lump_err; if (enable_double_rr) { if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_REALMS, 0))) goto lump_err; if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0))) goto lump_err; r2 = 0; } else { pkg_free(r2); r2 = 0; } _l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T); if (_l2 == 0) goto lump_err; if (rr_param_buf.len) { _l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len); if (_l2 == 0) goto lump_err; } suffix = 0; if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0))) goto lump_err; term = 0; return 0; lump_err: LOG(L_ERR, "build_rr(): Error while inserting lumps\n"); if (prefix) pkg_free(prefix); if (suffix) pkg_free(suffix); if (r2) pkg_free(r2); if (term) pkg_free(term); return -4;}/* * Insert a new Record-Route header field * And also 2nd one if it is enabled and realm changed so * the 2nd record-route header will be necessary */int record_route(struct sip_msg* _m, str *params){ struct lump* l, *l2; str user; struct to_body* from; str* tag; from = 0; /* Makes gcc happy */ user.len = 0; if (add_username) { if (get_username(_m, &user) < 0) { LOG(L_ERR, "insert_RR(): Error while extracting username\n"); return -1; } } if (append_fromtag) { if (parse_from_header(_m) < 0) { LOG(L_ERR, "insert_RR(): From parsing failed\n"); return -2; } from = (struct to_body*)_m->from->parsed; tag = &from->tag_value; } else { tag = 0; } if (rr_param_buf.len && rr_param_msg!=_m->id) { /* rr_params were set for a different message -> reset buffer */ rr_param_buf.len = 0; } if (enable_double_rr) { l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LOG(L_ERR, "insert_RR(): Error while creating an anchor\n"); return -5; } l = insert_cond_lump_after(l, COND_IF_DIFF_REALMS, 0); l2 = insert_cond_lump_before(l2, COND_IF_DIFF_REALMS, 0); if (!l || !l2) { LOG(L_ERR,"insert_RR(): Error while inserting conditional lump\n"); return -6; } if (build_rr(l, l2, &user, tag, params, OUTBOUND) < 0) { LOG(L_ERR, "insert_RR(): Error while inserting outbound " "Record-Route\n"); return -7; } } l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l || !l2) { LOG(L_ERR, "insert_RR(): Error while creating an anchor\n"); return -3; } if (build_rr(l, l2, &user, tag, params, INBOUND) < 0) { LOG(L_ERR,"insert_RR(): Error while inserting inbound Record-Route\n"); return -4; } /* reset the rr_param buffer */ rr_param_buf.len = 0; return 0;}/* * Insert manually created Record-Route header, no checks, no restrictions, * always adds lr parameter, only fromtag is added automatically when requested */int record_route_preset(struct sip_msg* _m, str* _data){ str user; struct to_body* from; struct lump* l; char* hdr, *p; int hdr_len; from = 0; user.len = 0; user.s = 0; if (add_username) { if (get_username(_m, &user) < 0) { LOG(L_ERR, "ERROR:rr:record_route_preset: failed to " "extract username\n"); return -1; } } if (append_fromtag) { if (parse_from_header(_m) < 0) { LOG(L_ERR, "ERROR:rr:record_route_preset: From parsing failed\n"); return -2; } from = (struct to_body*)_m->from->parsed; } l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0); if (!l) { LOG(L_ERR, "ERROR:rr:record_route_preset: failed to create " "lump anchor\n"); return -3; } hdr_len = RR_PREFIX_LEN; if (user.len) hdr_len += user.len + 1; /* @ */ hdr_len += _data->len; if (append_fromtag && from->tag_value.len) { hdr_len += RR_FROMTAG_LEN + from->tag_value.len; } if (enable_full_lr) { hdr_len += RR_LR_FULL_LEN; } else { hdr_len += RR_LR_LEN; } hdr_len += RR_TERM_LEN; hdr = pkg_malloc(hdr_len); if (!hdr) { LOG(L_ERR, "ERROR:rr:record_route_preset: no pkg memory left\n"); return -4; } p = hdr; memcpy(p, RR_PREFIX, RR_PREFIX_LEN); p += RR_PREFIX_LEN; if (user.len) { memcpy(p, user.s, user.len); p += user.len; *p = '@'; p++; } memcpy(p, _data->s, _data->len); p += _data->len; if (append_fromtag && from->tag_value.len) { memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN); p += RR_FROMTAG_LEN; memcpy(p, from->tag_value.s, from->tag_value.len); p += from->tag_value.len; } if (enable_full_lr) { memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN); p += RR_LR_FULL_LEN; } else { memcpy(p, RR_LR, RR_LR_LEN); p += RR_LR_LEN; } memcpy(p, RR_TERM, RR_TERM_LEN); if (!insert_new_lump_after(l, hdr, hdr_len, 0)) { LOG(L_ERR, "record_route_preset(): Error while inserting new lump\n"); pkg_free(hdr); return -5; } return 1;}static struct lump *get_rr_param_lump( struct lump** root){ struct lump *r, *crt, *last; /* look on the "before" branch for the last added lump */ last = 0; for( crt=*root ; crt && !last ; crt=crt->next,(*root)=crt ) { /* check on before list */ for( r=crt->before ; r ; r=r->before ) { if ( r->type==HDR_RECORDROUTE_T ) last = r; } } return last;}/* * Appends a new Record-Route parameter */int add_rr_param(struct sip_msg* msg, str* rr_param){ struct lump *last_param; struct lump *root; root = msg->add_rm; last_param = get_rr_param_lump( &root ); if (last_param) { /* RR was already done -> have to add a new lump before this one */ if (insert_rr_param_lump( last_param, rr_param->s, rr_param->len)==0) { LOG(L_ERR,"ERROR:rr:add_rr_param: failed to add lump\n"); goto error; } /* double routing enabled? */ if (enable_double_rr) { if (root==0 || (last_param=get_rr_param_lump(&root))==0) { LOG(L_CRIT,"BUG:rr:add_rr_param: failed to locate " "double RR lump\n"); goto error; } if (insert_rr_param_lump(last_param,rr_param->s,rr_param->len)==0){ LOG(L_ERR,"ERROR:rr:add_rr_param: failed to add 2nd lump\n"); goto error; } } } else { /* RR not done yet -> store the param in the static buffer */ if (rr_param_msg!=msg->id) { /* it's about a different message -> reset buffer */ rr_param_buf.len = 0; rr_param_msg = msg->id; } if (rr_param_buf.len+rr_param->len>RR_PARAM_BUF_SIZE) { LOG(L_ERR,"ERROR:rr:add_rr_param: maximum size of " "rr_param_buf exceeded\n"); goto error; } memcpy( rr_param_buf.s+rr_param_buf.len, rr_param->s, rr_param->len); rr_param_buf.len += rr_param->len; DBG("DEBUG:rr:add_rr_param: rr_param_buf=<%.*s>\n",rr_param_buf.len, rr_param_buf.s); } return 0;error: return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -