📄 loose.c
字号:
/* * Route & Record-Route module, loose routing support * * $Id: loose.c,v 1.35.2.1 2005/05/31 13:48:30 janakj Exp $ * * Copyright (C) 2001-2004 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: * info@iptel.org * * 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 * * History: * --------- * 2003-02-28 scratchpad compatibility abandoned (jiri) * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) */#include <string.h>#include "../../ut.h"#include "../../str.h"#include "../../dprint.h"#include "../../forward.h"#include "../../data_lump.h"#include "../../parser/parse_rr.h"#include "../../parser/parse_uri.h"#include "../../mem/mem.h"#include "../../dset.h"#include "loose.h"#include "rr_mod.h"#define RR_ERROR -1 /* An error occured while processing route set */#define RR_DRIVEN 1 /* The next hop is determined from the route set */#define NOT_RR_DRIVEN -1 /* The next hop is not determined from the route set */#define ROUTE_PREFIX "Route: <"#define ROUTE_PREFIX_LEN (sizeof(ROUTE_PREFIX)-1)#define ROUTE_SUFFIX ">\r\n"#define ROUTE_SUFFIX_LEN (sizeof(ROUTE_SUFFIX)-1)/* * Test whether we are processing pre-loaded route set * by looking at the To tag */static int is_preloaded(struct sip_msg* msg){ str tag; if (!msg->to && parse_headers(msg, HDR_TO, 0) == -1) { LOG(L_ERR, "is_preloaded: Cannot parse To header field\n"); return -1; } if (!msg->to) { LOG(L_ERR, "is_preloaded: To header field not found\n"); return -1; } tag = get_to(msg)->tag_value; if (tag.s == 0 || tag.len == 0) { DBG("is_preloaded: Yes\n"); return 1; } DBG("is_preloaded: No\n"); return 0;}/* * Parse the message and find first occurrence of * Route header field. The function returns -1 or -2 * on a parser error, 0 if there is a Route HF and * 1 if there is no Route HF. */static inline int find_first_route(struct sip_msg* _m){ if (parse_headers(_m, HDR_ROUTE, 0) == -1) { LOG(L_ERR, "find_first_route: Error while parsing headers\n"); return -1; } else { if (_m->route) { if (parse_rr(_m->route) < 0) { LOG(L_ERR, "find_first_route: Error while parsing Route HF\n"); return -2; } return 0; } else { DBG("find_first_route: No Route headers found\n"); return 1; } }}/* * Find out if a URI contains r2 parameter which indicates * that we put 2 record routes */static inline int is_2rr(str* _params){ str s; int i, state = 0; if (_params->len == 0) return 0; s = *_params; for(i = 0; i < s.len; i++) { switch(state) { case 0: switch(s.s[i]) { case ' ': case '\r': case '\n': case '\t': break; case 'r': case 'R': state = 1; break; default: state = 4; break; } break; case 1: switch(s.s[i]) { case '2': state = 2; break; default: state = 4; break; } break; case 2: switch(s.s[i]) { case ';': return 1; case '=': return 1; case ' ': case '\r': case '\n': case '\t': state = 3; break; default: state = 4; break; } break; case 3: switch(s.s[i]) { case ';': return 1; case '=': return 1; case ' ': case '\r': case '\n': case '\t': break; default: state = 4; break; } break; case 4: switch(s.s[i]) { case '\"': state = 5; break; case ';': state = 0; break; default: break; } break; case 5: switch(s.s[i]) { case '\\': state = 6; break; case '\"': state = 4; break; default: break; } break; case 6: state = 5; break; } } if ((state == 2) || (state == 3)) return 1; else return 0;}/* * Check if URI is myself */#ifdef ENABLE_USER_CHECKstatic inline int is_myself(str *_user, str* _host, unsigned short _port)#elsestatic inline int is_myself(str* _host, unsigned short _port)#endif{ int ret; ret = check_self(_host, _port ? _port : SIP_PORT, 0);/* match all protos*/ if (ret < 0) return 0;#ifdef ENABLE_USER_CHECK if(i_user.len && i_user.len==_user->len && !strncmp(i_user.s, _user->s, _user->len)) { DBG("is_myself: this URI isn't mine\n"); return -1; }#endif return ret;}/* * Find and parse next Route header field */static inline int find_next_route(struct sip_msg* _m, struct hdr_field** _hdr){ struct hdr_field* ptr; ptr = (*_hdr)->next; /* Try to find already parsed Route headers */ while(ptr) { if (ptr->type == HDR_ROUTE) goto found; ptr = ptr->next; } /* There are no already parsed Route headers, try to find next * occurrence of Route header */ if (parse_headers(_m, HDR_ROUTE, 1) == -1) { LOG(L_ERR, "find_next_route: Error while parsing headers\n"); return -1; } if ((_m->last_header->type != HDR_ROUTE) || (_m->last_header == *_hdr)) { DBG("find_next_route: No next Route HF found\n"); return 1; } ptr = _m->last_header; found: if (parse_rr(ptr) < 0) { LOG(L_ERR, "find_next_route: Error while parsing Route body\n"); return -2; } *_hdr = ptr; return 0;}/* * Check if the given uri contains lr parameter which marks loose routers */static inline int is_strict(str* _params){ str s; int i, state = 0; if (_params->len == 0) return 1; s.s = _params->s; s.len = _params->len; for(i = 0; i < s.len; i++) { switch(state) { case 0: switch(s.s[i]) { case ' ': case '\r': case '\n': case '\t': break; case 'l': case 'L': state = 1; break; default: state = 4; break; } break; case 1: switch(s.s[i]) { case 'r': case 'R': state = 2; break; default: state = 4; break; } break; case 2: switch(s.s[i]) { case ';': return 0; case '=': return 0; case ' ': case '\r': case '\n': case '\t': state = 3; break; default: state = 4; break; } break; case 3: switch(s.s[i]) { case ';': return 0; case '=': return 0; case ' ': case '\r': case '\n': case '\t': break; default: state = 4; break; } break; case 4: switch(s.s[i]) { case '\"': state = 5; break; case ';': state = 0; break; default: break; } break; case 5: switch(s.s[i]) { case '\\': state = 6; break; case '\"': state = 4; break; default: break; } break; case 6: state = 5; break; } } if ((state == 2) || (state == 3)) return 0; else return 1;}/* * Put Request-URI as last Route header of a SIP * message, this is necessary when forwarding to * a strict router */static inline int save_ruri(struct sip_msg* _m){ struct lump* anchor; char *s; int len; /* We must parse the whole message header here, * because Request-URI must be saved in last * Route HF in the message */ if (parse_headers(_m, HDR_EOH, 0) == -1) { LOG(L_ERR, "save_ruri: Error while parsing message\n"); return -1; } /* Create an anchor */ anchor = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0); if (anchor == 0) { LOG(L_ERR, "save_ruri: Can't get anchor\n"); return -2; } /* Create buffer for new lump */ len = ROUTE_PREFIX_LEN + _m->first_line.u.request.uri.len + ROUTE_SUFFIX_LEN; s = (char*)pkg_malloc(len); if (!s) { LOG(L_ERR, "save_ruri: No memory left\n"); return -3; } /* Create new header field */ memcpy(s, ROUTE_PREFIX, ROUTE_PREFIX_LEN); memcpy(s + ROUTE_PREFIX_LEN, _m->first_line.u.request.uri.s, _m->first_line.u.request.uri.len); memcpy(s + ROUTE_PREFIX_LEN + _m->first_line.u.request.uri.len, ROUTE_SUFFIX, ROUTE_SUFFIX_LEN); DBG("save_ruri: New header: '%.*s'\n", len, ZSW(s)); /* Insert it */ if (insert_new_lump_before(anchor, s, len, 0) == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -