📄 proxy.c
字号:
/* -*- Mode: C; c-basic-offset: 3 -*- Copyright (C) 2002 Thomas Ries <tries@gmx.net> This file is part of Siproxd. Siproxd 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. Siproxd 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 Siproxd; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "config.h"#include <stdio.h>#include <time.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <osipparser2/osip_parser.h>#include <osipparser2/sdp_message.h>#include "siproxd.h"#include "log.h"static char const ident[]="$Id: proxy.c,v 1.77 2004/11/03 21:23:34 hb9xar Exp $";/* configuration storage */extern struct siproxd_config configuration; /* defined in siproxd.c */extern struct urlmap_s urlmap[]; /* URL mapping table */extern struct lcl_if_s local_addresses;#define CHAR(i) ((char *)(&i)) unsigned long rv_ntohl(unsigned long net){ unsigned long order = 0x00010203, host=0; int i; for (i = 0; i < 4; i++) { int index = CHAR(order)[i]; CHAR(host)[index] = CHAR(net)[i]; } return host;}void uint32_to_ip(unsigned long addr, char *ip){ char ip_buffer[16]; int curr_num, curr_dig; unsigned long num; char *p = &(ip_buffer[14]); addr = rv_ntohl(addr); strcpy(ip_buffer, "xxx.xxx.xxx.xxx"); for (curr_num = 0; curr_num <= 3; curr_num++) { num = addr & 0xFF; addr >>= 8; for (curr_dig = 0; curr_dig <= 2; curr_dig++) { *p = (char)(((char)(num % 10) + '0')); num /= 10; p--; if (num == 0) break; } if (curr_num < 3) *p-- = '.'; } strcpy(ip,(p+1));}/*if message chough nat*/int sip_change_via_if_nat(sip_ticket_t *ticket) { int i; osip_via_t *via; char *proto = NULL; // char ipaddr[25]; if(ticket == NULL) return -1; i = osip_message_get_via(ticket->sipmsg, 0, &via); if(i != 0) goto error_1; proto = via_get_protocol(via); if(proto == NULL) goto error_1; osip_message_fix_last_via_header(ticket->sipmsg, inet_ntoa (ticket->from.sin_addr), ntohs(ticket->from.sin_port)); return 0; error_1: return -1;}/* * PROXY_REQUEST * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error * * RFC3261 * Section 16.3: Proxy Behavior - Request Validation * 1. Reasonable Syntax * 2. URI scheme * 3. Max-Forwards * 4. (Optional) Loop Detection * 5. Proxy-Require * 6. Proxy-Authorization * * Section 16.6: Proxy Behavior - Request Forwarding * 1. Make a copy of the received request * 2. Update the Request-URI * 3. Update the Max-Forwards header field * 4. Optionally add a Record-route header field value * 5. Optionally add additional header fields * 6. Postprocess routing information * 7. Determine the next-hop address, port, and transport * 8. Add a Via header field value * 9. Add a Content-Length header field if necessary * 10. Forward the new request * 11. Set timer C */int proxy_request (sip_ticket_t *ticket) { int i; int sts; int type; struct in_addr sendto_addr; osip_uri_t *url; int port; char *buffer; osip_message_t *request; struct sockaddr_in *from; DEBUGC(DBCLASS_PROXY,"proxy_request"); if (ticket==NULL) { ERROR("proxy_request: called with NULL ticket"); return STS_FAILURE; } request=ticket->sipmsg; from=&ticket->from; osip_message_fix_last_via_header(ticket->sipmsg, inet_ntoa (from->sin_addr), ntohs(from->sin_port)); /* * RFC 3261, Section 16.4 * Proxy Behavior - Route Information Preprocessing * (process Route header) */ route_preprocess(ticket); /* * figure out whether this is an incoming or outgoing request * by doing a lookup in the registration table. */#define _OLD_DIRECTION_EVALUATION 0#if _OLD_DIRECTION_EVALUATION type = 0; for (i=0; i<URLMAP_SIZE; i++) { if (urlmap[i].active == 0) continue; /* incoming request ('to' == 'masq') || (('to' == 'reg') && !REGISTER)*/ if (((MSG_IS_REGISTER(request)&& compare_url(request->to->url, urlmap[i].masq_url)==STS_SUCCESS)) || (!MSG_IS_REGISTER(request) && (compare_url(request->to->url, urlmap[i].reg_url)==STS_SUCCESS))) { type=REQTYP_INCOMING; DEBUGC(DBCLASS_PROXY,"incoming request from %s@%s from outbound", request->from->url->username? request->from->url->username:"*NULL*", request->from->url->host? request->from->url->host: "*NULL*"); break; } /* outgoing request ('from' == 'reg') */ if (compare_url(request->from->url, urlmap[i].reg_url)==STS_SUCCESS) { type=REQTYP_OUTGOING; DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound", request->from->url->username? request->from->url->username:"*NULL*", request->from->url->host? request->from->url->host: "*NULL*"); break; } }#else type = 0; /* * did I receive the telegram from a REGISTERED host? * -> it must be an OUTGOING request */ for (i=0; i<URLMAP_SIZE; i++) { struct in_addr tmp_addr; if (urlmap[i].active == 0) continue; if (get_ip_by_host(urlmap[i].true_url->host, &tmp_addr) == STS_FAILURE) { DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve host [%s]", urlmap[i].true_url); } else { DEBUGC(DBCLASS_PROXY, "proxy_request: reghost:%s ip:%s", urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr)); if (memcmp(&tmp_addr, &from->sin_addr, sizeof(tmp_addr)) == 0) { type=REQTYP_OUTGOING; break; } } } /* * is the telegram directed to an internally registered host? * -> it must be an INCOMING request */ if (type == 0) { for (i=0; i<URLMAP_SIZE; i++) { if (urlmap[i].active == 0) continue; /* RFC3261: * 'To' contains a display name (Bob) and a SIP or SIPS URI * (sip:bob@biloxi.com) towards which the request was originally * directed. Display names are described in RFC 2822 [3]. */ /* So this means, that we must check the SIP URI supplied with the * INVITE method, as this points to the real wanted target. * Q: does there exist a situation where the SIP URI itself does * point to "somewhere" but the To: points to the correct UA? * So for now, we just look at both of them (SIP URI and To: header) */ /* incoming request (SIP URI == 'masq') || ((SIP URI == 'reg') && !REGISTER)*/ if ((MSG_IS_REGISTER(request)&& (compare_url(request->req_uri, urlmap[i].masq_url)==STS_SUCCESS)) || (!MSG_IS_REGISTER(request) && (compare_url(request->req_uri, urlmap[i].reg_url)==STS_SUCCESS))) { type=REQTYP_INCOMING; break; } /* incoming request ('to' == 'masq') || (('to' == 'reg') && !REGISTER)*/ if ((MSG_IS_REGISTER(request) &&(compare_url(request->to->url, urlmap[i].masq_url)==STS_SUCCESS)) || (!MSG_IS_REGISTER(request) && (compare_url(request->to->url, urlmap[i].reg_url)==STS_SUCCESS))) { type=REQTYP_INCOMING; break; } } }#endif ticket->direction=type; /* * logging of passing calls */ if (configuration.log_calls) { osip_uri_t *cont_url = NULL; if (!osip_list_eol(request->contacts, 0)) cont_url = ((osip_contact_t*)(request->contacts->node->element))->url; /* INVITE */ if (MSG_IS_INVITE(request)) { if (cont_url) { INFO("%s Call from: %s@%s", (type==REQTYP_INCOMING) ? "Incoming":"Outgoing", cont_url->username ? cont_url->username:"*NULL*", cont_url->host ? cont_url->host : "*NULL*"); } else { INFO("%s Call (w/o contact header) from: %s@%s", (type==REQTYP_INCOMING) ? "Incoming":"Outgoing", request->from->url->username ? request->from->url->username:"*NULL*", request->from->url->host ? request->from->url->host : "*NULL*"); } /* BYE / CANCEL */ } else if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) { if (cont_url) { INFO("Ending Call from: %s@%s", cont_url->username ? cont_url->username:"*NULL*", cont_url->host ? cont_url->host : "*NULL*"); } else { INFO("Ending Call (w/o contact header) from: %s@%s", request->from->url->username ? request->from->url->username:"*NULL*", request->from->url->host ? request->from->url->host : "*NULL*"); } }else if(MSG_IS_SUBSCRIBE(request)) { if(cont_url) { INFO("Ending Call from: %s@%s", cont_url->username?cont_url->username:"*NULL", cont_url->host ? cont_url->host:"*NULL"); }else { INFO("Ending Call (w/o contact header) from: %s@%s", request->from->url->username ? request->from->url->username:"*NULL", request->from->url->host ? request->from->url->host : "*NULL"); } } } /* log_calls */ /* * RFC 3261, Section 16.6 step 1 * Proxy Behavior - Request Forwarding - Make a copy */ /* nothing to do here, copy is ready in 'request'*/ /* get destination address */ url=osip_message_get_uri(request); switch (type) { /* * from an external host to the internal masqueraded host */ case REQTYP_INCOMING: DEBUGC(DBCLASS_PROXY,"incoming request from %s@%s from outbound", request->from->url->username? request->from->url->username:"*NULL*", request->from->url->host? request->from->url->host: "*NULL*"); /* * RFC 3261, Section 16.6 step 2 * Proxy Behavior - Request Forwarding - Request-URI * (rewrite request URI to point to the real host) */ /* 'i' still holds the valid index into the URLMAP table */ if (check_rewrite_rq_uri(request) == STS_TRUE) { proxy_rewrite_request_uri(request, i); } /* if this is CANCEL/BYE request, stop RTP proxying */ if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) { /* stop the RTP proxying stream(s) */ rtp_stop_fwd(osip_message_get_call_id(request), DIR_INCOMING); rtp_stop_fwd(osip_message_get_call_id(request), DIR_OUTGOING); /* check for incoming request */ } else if (MSG_IS_INVITE(request)) { /* First, rewrite the body */ if (configuration.rtp_proxy_enable == 1) { sts = proxy_rewrite_invitation_body(request, DIR_INCOMING); } /* * Note: Incoming requests have no need to rewrite Contact * header - as we are not masquerading something there */ }else if(MSG_IS_NOTIFY(request)) { printf("*********** recv notify message! **********\n"); }else if(MSG_IS_SUBSCRIBE(request)) { printf("************ recv subscribe message! ***********\n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -