/* * SIP_ADD_MYVIA * * interface == IF_OUTBOUND, IF_INBOUND * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */ int sip_add_myvia (sip_ticket_t *ticket, int interface, struct in_addr *local_ip) { struct in_addr addr; char tmp[URL_STRING_SIZE] = {0}; osip_via_t *via; int sts; char branch_id[VIA_BRANCH_SIZE]; if (local_ip == NULL) { if (interface == IF_OUTBOUND) { if (get_ip_by_ifname(configuration.outbound_if, &addr) != STS_SUCCESS) { ERROR("can't find interface %s - configuration error?", configuration.outbound_if); return STS_FAILURE; } } else { if (get_ip_by_ifname(configuration.inbound_if, &addr) != STS_SUCCESS) { ERROR("can't find inbound interface %s - configuration error?", configuration.inbound_if); return STS_FAILURE; } } } else { addr = *local_ip; } sts = sip_calculate_branch_id(ticket, branch_id); snprintf(tmp,URL_STRING_SIZE, "SIP/2.0/UDP %s:%i;branch=%s;", utils_inet_ntoa(addr), configuration.sip_listen_port, branch_id); DEBUGC(DBCLASS_BABBLE,"adding VIA:%s",tmp); sts = osip_via_init(&via); if (sts!=0) return STS_FAILURE; /* allocation failed */ sts = osip_via_parse(via, tmp); if (sts!=0) return STS_FAILURE; osip_list_add(ticket->sipmsg->vias,via,0); return STS_SUCCESS; }
/* * get_interface_real_ip: * fetches the real IP address of my interface INBOUND/OUTBOUND * * STS_SUCCESS on returning a valid IP and interface is UP * STS_FAILURE if interface is DOWN or other problem */ int get_interface_real_ip(int interface, struct in_addr *retaddr) { int sts=STS_FAILURE; char *tmp=NULL; if (interface == IF_INBOUND) { tmp = configuration.inbound_if; } else if (interface == IF_OUTBOUND) { tmp = configuration.outbound_if; } if (tmp && (strcmp(tmp, "")!=0)) { DEBUGC(DBCLASS_DNS, "fetching interface IP by INTERFACE [%i]", interface); sts = get_ip_by_ifname(tmp, retaddr); if (sts != STS_SUCCESS) { ERROR("can't find interface %s - configuration error?", tmp); } } else { ERROR("Don't know what interface to look for - configuration error?"); } return sts; }
/* * check if a given request is addressed to local. I.e. it is addressed * to the proxy itself (IP of my inbound or outbound interface, same port) * * RETURNS * STS_TRUE if the request is addressed local * STS_FALSE otherwise */ int is_sipuri_local (sip_ticket_t *ticket) { osip_message_t *sip=ticket->sipmsg; int found; struct in_addr addr_uri, addr_myself; char *my_interfaces[]= { configuration.inbound_if, configuration.outbound_if, (char*)-1 }; int port; int i; char *ptr; if (sip==NULL) { ERROR("called is_sipuri_local with NULL sip"); return STS_FALSE; } if (!sip || !sip->req_uri) { ERROR("is_sipuri_local: no request URI present"); return STS_FALSE; } DEBUGC(DBCLASS_DNS,"check for local SIP URI %s:%s", sip->req_uri->host? sip->req_uri->host : "*NULL*", sip->req_uri->port? sip->req_uri->port : "*NULL*"); if (utils_inet_aton(sip->req_uri->host, &addr_uri) == 0) { /* need name resolution */ get_ip_by_host(sip->req_uri->host, &addr_uri); } found=0; for (i=0; ; i++) { /* * try to search by interface name first */ ptr=my_interfaces[i]; if (ptr==(char*)-1) break; /* end of list mark */ if (ptr) { DEBUGC(DBCLASS_BABBLE,"resolving IP of interface %s",ptr); if (get_ip_by_ifname(ptr, &addr_myself) != STS_SUCCESS) { ERROR("can't find interface %s - configuration error?", ptr); continue; } } /* check the extracted HOST against my own host addresses */ if (sip->req_uri->port) { port=atoi(sip->req_uri->port); } else { port=SIP_PORT; } if ( (memcmp(&addr_myself, &addr_uri, sizeof(addr_myself))==0) && (port == configuration.sip_listen_port) ) { DEBUG("address match [%s]", utils_inet_ntoa(addr_uri)); found=1; break; } } DEBUGC(DBCLASS_DNS, "SIP URI is %slocal", found? "":"not "); return (found)? STS_TRUE : STS_FALSE; }
/* * check if a given osip_via_t is local. I.e. its address is owned * by my inbound or outbound interface * * RETURNS * STS_TRUE if the given VIA is one of my interfaces * STS_FALSE otherwise */ int is_via_local (osip_via_t *via, struct in_addr *local_ip) { int sts, found; struct in_addr addr_via, addr_myself; char *my_interfaces[]= { configuration.inbound_if, configuration.outbound_if, (char*)-1 }; int port; int i; char *ptr; if (via==NULL) { ERROR("called is_via_local with NULL via"); return STS_FALSE; } DEBUGC(DBCLASS_BABBLE,"via name %s",via->host); if (utils_inet_aton(via->host,&addr_via) == 0) { /* need name resolution */ sts=get_ip_by_host(via->host, &addr_via); if (sts == STS_FAILURE) { DEBUGC(DBCLASS_DNS, "is_via_local: cannot resolve VIA [%s]", via->host); return STS_FAILURE; } } /* check the extracted VIA against my own host addresses */ if (via->port) port=atoi(via->port); else port=SIP_PORT; /* Check local_ip if defined */ if (local_ip) { if ( (memcmp(&addr_via, local_ip, sizeof(addr_via))==0) && (port == configuration.sip_listen_port) ) { DEBUGC(DBCLASS_BABBLE,"via is local due to local_ip"); return STS_TRUE; } } found=0; for (i=0; ; i++) { /* * try to search by interface name first */ ptr=my_interfaces[i]; if (ptr==(char*)-1) break; /* end of list mark */ if (ptr) { DEBUGC(DBCLASS_BABBLE,"resolving IP of interface %s",ptr); if (get_ip_by_ifname(ptr, &addr_myself) != STS_SUCCESS) { ERROR("can't find interface %s - configuration error?", ptr); continue; } } if ( (memcmp(&addr_myself, &addr_via, sizeof(addr_myself))==0) && (port == configuration.sip_listen_port) ) { DEBUG("got address match [%s]", utils_inet_ntoa(addr_via)); found=1; break; } } return (found)? STS_TRUE : STS_FALSE; }
int main (int argc, char *argv[]) #endif { int sts; int i; int access; char buff [BUFFER_SIZE]; sip_ticket_t ticket; extern char *optarg; /* Defined in libc getopt and unistd.h */ int ch1; char configfile[64]="siproxd"; /* basename of configfile */ int config_search=1; /* search the config file */ int cmdline_debuglevel=0; char *pidfilename=NULL; struct sigaction act; log_set_stderr(1); /* * setup signal handlers */ act.sa_handler=sighandler; sigemptyset(&act.sa_mask); act.sa_flags=SA_RESTART; if (sigaction(SIGTERM, &act, NULL)) { ERROR("Failed to install SIGTERM handler"); } if (sigaction(SIGINT, &act, NULL)) { ERROR("Failed to install SIGINT handler"); } if (sigaction(SIGUSR2, &act, NULL)) { ERROR("Failed to install SIGUSR2 handler"); } /* * prepare default configuration */ make_default_config(); log_set_pattern(configuration.debuglevel); /* * open a the pwfile instance, so we still have access after * we possibly have chroot()ed to somewhere. */ if (configuration.proxy_auth_pwfile) { siproxd_passwordfile = fopen(configuration.proxy_auth_pwfile, "r"); } else { siproxd_passwordfile = NULL; } /* * parse command line */ { #ifdef HAVE_GETOPT_LONG int option_index = 0; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"config", required_argument, NULL, 'c'}, {"debug", required_argument, NULL, 'd'}, {"pid-file", required_argument, NULL,'p'}, {0,0,0,0} }; while ((ch1 = getopt_long(argc, argv, "hc:d:p:", long_options, &option_index)) != -1) { #else /* ! HAVE_GETOPT_LONG */ while ((ch1 = getopt(argc, argv, "hc:d:p:")) != -1) { #endif switch (ch1) { case 'h': /* help */ DEBUGC(DBCLASS_CONFIG,"option: help"); fprintf(stderr,str_helpmsg); exit(0); break; case 'c': /* load config file */ DEBUGC(DBCLASS_CONFIG,"option: config file=%s",optarg); i=sizeof(configfile)-1; strncpy(configfile,optarg,i-1); configfile[i]='\0'; config_search=0; break; case 'd': /* set debug level */ DEBUGC(DBCLASS_CONFIG,"option: set debug level: %s",optarg); cmdline_debuglevel=atoi(optarg); log_set_pattern(cmdline_debuglevel); break; case 'p': pidfilename = optarg; break; default: DEBUGC(DBCLASS_CONFIG,"no command line options"); break; } } } /* * Init stuff */ INFO(PACKAGE"-"VERSION"-"BUILDSTR" "UNAME" starting up"); /* read the config file */ if (read_config(configfile, config_search) == STS_FAILURE) exit(1); /* if a debug level > 0 has been given on the commandline use its value and not what is in the config file */ if (cmdline_debuglevel != 0) { configuration.debuglevel=cmdline_debuglevel; } /* set debug level as desired */ log_set_pattern(configuration.debuglevel); log_set_listen_port(configuration.debugport); /* change user and group IDs */ secure_enviroment(); /* daemonize if requested to */ if (configuration.daemonize) { DEBUGC(DBCLASS_CONFIG,"daemonizing"); if (fork()!=0) exit(0); setsid(); if (fork()!=0) exit(0); log_set_stderr(0); INFO("daemonized, pid=%i", getpid()); } /* write PID file of main thread */ if (pidfilename == NULL) pidfilename = configuration.pid_file; if (pidfilename) { FILE *pidfile; DEBUGC(DBCLASS_CONFIG,"creating PID file [%s]", pidfilename); sts=unlink(configuration.pid_file); if ((sts==0) ||(errno == ENOENT)) { if ((pidfile=fopen(pidfilename, "w"))) { fprintf(pidfile,"%i\n",(int)getpid()); fclose(pidfile); } else { WARN("couldn't create new PID file: %s", strerror(errno)); } } else { WARN("couldn't delete old PID file: %s", strerror(errno)); } } /* initialize the RTP proxy */ sts=rtpproxy_init(); if (sts != STS_SUCCESS) { ERROR("unable to initialize RTP proxy - aborting"); exit(1); } /* init the oSIP parser */ parser_init(); /* listen for incoming messages */ sts=sipsock_listen(); if (sts == STS_FAILURE) { /* failure to allocate SIP socket... */ ERROR("unable to bind to SIP listening socket - aborting"); exit(1); } /* initialize the registration facility */ register_init(); /* * silence the log - if so required... */ log_set_silence(configuration.silence_log); INFO(PACKAGE"-"VERSION"-"BUILDSTR" "UNAME" started"); /* * Main loop */ while (!exit_program) { DEBUGC(DBCLASS_BABBLE,"going into sipsock_wait\n"); while (sipsock_wait()<=0) { /* got no input, here by timeout. do aging */ register_agemap(); /* TCP log: check for a connection */ log_tcp_connect(); /* dump memory stats if requested to do so */ if (dmalloc_dump) { dmalloc_dump=0; #ifdef DMALLOC INFO("SIGUSR2 - DMALLOC statistics is dumped"); dmalloc_log_stats(); dmalloc_log_unfreed(); #else INFO("SIGUSR2 - DMALLOC support is not compiled in"); #endif } if (exit_program) goto exit_prg; } /* got input, process */ DEBUGC(DBCLASS_BABBLE,"back from sipsock_wait"); i=sipsock_read(&buff, sizeof(buff)-1, &ticket.from, &ticket.protocol); buff[i]='\0'; /* evaluate the access lists (IP based filter)*/ access=accesslist_check(ticket.from); if (access == 0) { DEBUGC(DBCLASS_ACCESS,"access for this packet was denied"); continue; /* there are no resources to free */ } /* integrity checks */ sts=security_check_raw(buff, i); if (sts != STS_SUCCESS) { DEBUGC(DBCLASS_SIP,"security check (raw) failed"); continue; /* there are no resources to free */ } /* init sip_msg */ sts=osip_message_init(&ticket.sipmsg); ticket.sipmsg->message=NULL; if (sts != 0) { ERROR("osip_message_init() failed... this is not good"); continue; /* skip, there are no resources to free */ } /* * RFC 3261, Section 16.3 step 1 * Proxy Behavior - Request Validation - Reasonable Syntax * (parse the received message) */ sts=osip_message_parse(ticket.sipmsg, buff); if (sts != 0) { ERROR("osip_message_parse() failed... this is not good"); DUMP_BUFFER(-1, buff, i); goto end_loop; /* skip and free resources */ } /* integrity checks - parsed buffer*/ sts=security_check_sip(&ticket); if (sts != STS_SUCCESS) { ERROR("security_check_sip() failed... this is not good"); DUMP_BUFFER(-1, buff, i); goto end_loop; /* skip and free resources */ } /* * RFC 3261, Section 16.3 step 2 * Proxy Behavior - Request Validation - URI scheme * (check request URI and refuse with 416 if not understood) */ /* NOT IMPLEMENTED */ /* * RFC 3261, Section 16.3 step 3 * Proxy Behavior - Request Validation - Max-Forwards check * (check Max-Forwards header and refuse with 483 if too many hops) */ { osip_header_t *max_forwards; int forwards_count = DEFAULT_MAXFWD; osip_message_get_max_forwards(ticket.sipmsg, 0, &max_forwards); if (max_forwards && max_forwards->hvalue) { forwards_count = atoi(max_forwards->hvalue); } DEBUGC(DBCLASS_PROXY,"checking Max-Forwards (=%i)",forwards_count); if (forwards_count <= 0) { DEBUGC(DBCLASS_SIP, "Forward count reached 0 -> 483 response"); sip_gen_response(&ticket, 483 /*Too many hops*/); goto end_loop; /* skip and free resources */ } } /* * RFC 3261, Section 16.3 step 4 * Proxy Behavior - Request Validation - Loop Detection check * (check for loop and return 482 if a loop is detected) */ if (check_vialoop(&ticket) == STS_TRUE) { /* make sure we don't end up in endless loop when detecting * an loop in an "loop detected" message - brrr */ if (MSG_IS_RESPONSE(ticket.sipmsg) && MSG_TEST_CODE(ticket.sipmsg, 482)) { DEBUGC(DBCLASS_SIP,"loop in loop-response detected, ignoring"); } else { DEBUGC(DBCLASS_SIP,"via loop detected, ignoring request"); sip_gen_response(&ticket, 482 /*Loop detected*/); } goto end_loop; /* skip and free resources */ } /* * RFC 3261, Section 16.3 step 5 * Proxy Behavior - Request Validation - Proxy-Require check * (check Proxy-Require header and return 420 if unsupported option) */ /* NOT IMPLEMENTED */ /* * RFC 3261, Section 16.5 * Proxy Behavior - Determining Request Targets */ /* NOT IMPLEMENTED */ DEBUGC(DBCLASS_SIP,"received SIP type %s:%s", (MSG_IS_REQUEST(ticket.sipmsg))? "REQ" : "RES", (MSG_IS_REQUEST(ticket.sipmsg) ? ((ticket.sipmsg->sip_method)? ticket.sipmsg->sip_method : "NULL") : ((ticket.sipmsg->reason_phrase) ? ticket.sipmsg->reason_phrase : "NULL"))); /* * if an REQ REGISTER, check if it is directed to myself, * or am I just the outbound proxy but no registrar. * - If I'm the registrar, register & generate answer * - If I'm just the outbound proxy, register, rewrite & forward */ if (MSG_IS_REGISTER(ticket.sipmsg) && MSG_IS_REQUEST(ticket.sipmsg)) { if (access & ACCESSCTL_REG) { osip_uri_t *url; struct in_addr addr1, addr2, addr3; int dest_port; url = osip_message_get_uri(ticket.sipmsg); dest_port= (url->port)?atoi(url->port):SIP_PORT; if ( (get_ip_by_host(url->host, &addr1) == STS_SUCCESS) && (get_ip_by_ifname(configuration.inbound_if,&addr2) == STS_SUCCESS) && (get_ip_by_ifname(configuration.outbound_if,&addr3) == STS_SUCCESS)) { if ((configuration.sip_listen_port == dest_port) && ((memcmp(&addr1, &addr2, sizeof(addr1)) == 0) || (memcmp(&addr1, &addr3, sizeof(addr1)) == 0))) { /* I'm the registrar, send response myself */ sts = register_client(&ticket, 0); sts = register_response(&ticket, sts); } else { /* I'm just the outbound proxy */ DEBUGC(DBCLASS_SIP,"proxying REGISTER request to:%s", url->host); sts = register_client(&ticket, 1); sts = proxy_request(&ticket); } } else { if (MSG_IS_REQUEST(ticket.sipmsg)) { sip_gen_response(&ticket, 408 /*request timeout*/); } } } else { WARN("non-authorized registration attempt from %s", utils_inet_ntoa(ticket.from.sin_addr)); } /* * check if outbound interface is UP. * If not, send back error to UA and * skip any proxying attempt */ } else if (get_ip_by_ifname(configuration.outbound_if,NULL) != STS_SUCCESS) { DEBUGC(DBCLASS_SIP, "got a %s to proxy, but outbound interface " "is down", (MSG_IS_REQUEST(ticket.sipmsg))? "REQ" : "RES"); if (MSG_IS_REQUEST(ticket.sipmsg)) sip_gen_response(&ticket, 408 /*request timeout*/); /* * MSG is a request, add current via entry, * do a lookup in the URLMAP table and * send to the final destination */ } else if (MSG_IS_REQUEST(ticket.sipmsg)) { if (access & ACCESSCTL_SIP) { sts = proxy_request(&ticket); } else { INFO("non-authorized request received from %s", utils_inet_ntoa(ticket.from.sin_addr)); } /* * MSG is a response, remove current via and * send to the next VIA in chain */ } else if (MSG_IS_RESPONSE(ticket.sipmsg)) { if (access & ACCESSCTL_SIP) { sts = proxy_response(&ticket); } else { INFO("non-authorized response received from %s", utils_inet_ntoa(ticket.from.sin_addr)); } /* * unsupported message */ } else { ERROR("received unsupported SIP type %s %s", (MSG_IS_REQUEST(ticket.sipmsg))? "REQ" : "RES", ticket.sipmsg->sip_method); } /* * free the SIP message buffers */ end_loop: osip_message_free(ticket.sipmsg); } /* while TRUE */ exit_prg: /* dump current known SIP registrations */ register_shut(); INFO("properly terminating siproxd"); /* remove PID file */ if (pidfilename) { DEBUGC(DBCLASS_CONFIG,"deleting PID file [%s]", pidfilename); sts=unlink(pidfilename); if (sts != 0) { WARN("couldn't delete old PID file: %s", strerror(errno)); } } /* END */ return 0; } /* main */ /* * Signal handler * * this one is called asynchronously whevener a registered * signal is applied. Just set a flag and don't do any funny * things here. */ static void sighandler(int sig) { if (sig==SIGTERM) exit_program=1; if (sig==SIGINT) exit_program=1; if (sig==SIGUSR2) dmalloc_dump=1; return; }
/* * binds to SIP UDP socket for listening to incoming packets * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */ int sipsock_listen (void) { struct in_addr ipaddr; /* start of AU4D00875 by d00107688 to support bind 2008-10-15*/ struct in_addr wanipaddr; /* end of AU4D00875 by d00107688 to support bind 2008-10-15*/ int i = 0; memset(&ipaddr, 0, sizeof(ipaddr)); /* start of AU4D00875 by d00107688 to support bind 2008-10-15*/ memset(&wanipaddr, 0, sizeof(wanipaddr)); if (STS_FAILURE == get_ip_by_ifname(configuration.outbound_if, &wanipaddr)) { ERROR("%s ip: %s", configuration.inbound_if, utils_inet_ntoa(wanipaddr)); ERROR("can not get the ip , please check it......."); } else { g_lsockFlg = 1; } /* end of AU4D00875 by d00107688 to support bind 2008-10-15*/ /* start of AU4D00875 by d00107688 to support bind 2008-10-15*/ if (1 == g_lsockFlg) { sip_udp_socket = sockbind(ipaddr, configuration.sip_listen_port, 1); sip_udp_wan_socket = sockbind(wanipaddr, wanport, 1); if (0 == sip_udp_wan_socket) { for (i = 0; i < 5; i++) { wanport += (i * 10 + i); sip_udp_wan_socket = sockbind(wanipaddr, wanport, 1); if (0 == sip_udp_wan_socket) { ERROR("bind in port: %d error", wanport); continue; } else { break; } } } if ((0 == sip_udp_socket) || (0 == sip_udp_wan_socket)) { ERROR("socket bind error"); return STS_FAILURE; /* failure */ } } else { sip_udp_socket = sockbind(ipaddr, configuration.sip_listen_port, 1); if (sip_udp_socket == 0) return STS_FAILURE; /* failure*/ } INFO("bound to port %i", configuration.sip_listen_port); DEBUGC(DBCLASS_NET,"bound socket %i",sip_udp_socket); /* end of AU4D00875 by d00107688 to support bind 2008-10-15*/ return STS_SUCCESS; }
/* * sends an UDP datagram to the specified destination * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error * 函数修改说明: * 修改人: l67187 * 修改目的: 解决代理和绑定时没有默认路由,sip alg无法工作的问题 * 修改方案: 在报文发送时,bind上网关发送侧的ip地址,使用网关源地址路由 * 具体修改: 原alg 使用 初始化时创建的 sip_udp_socket,绑定了空地址 * 无法再次绑定,修改后,在该函数中不在使用 sip_udp_socket发送报文 * 而是重新创建一个socket发送,之后就关闭释放资源 */ int sipsock_send(struct in_addr addr, int port, int protocol, char *buffer, int size) { struct sockaddr_in dst_addr; struct sockaddr_in stLocalAddr; int sock; int sts = -1; /* first time: allocate a socket for sending if (sip_udp_socket == 0) { ERROR("SIP socket not allocated"); return STS_FAILURE; } */ if (buffer == NULL) { ERROR("sipsock_send got NULL buffer"); return STS_FAILURE; } if (protocol != PROTO_UDP) { ERROR("sipsock_send: only UDP supported by now"); return STS_FAILURE; } if (1 == g_lsockFlg) { dst_addr.sin_family = AF_INET; memcpy(&dst_addr.sin_addr.s_addr, &addr, sizeof(struct in_addr)); dst_addr.sin_port= htons(port); if ((1 == IpisInNet(utils_inet_ntoa(addr), g_acBrIpAddr, g_acBrMask)) || (1 == IpisInNet(utils_inet_ntoa(addr), g_acPPPoEIpAddr, g_acPPPoEMask))) { sts = sendto(sip_udp_socket, buffer, size, 0, (const struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)); } else /* wan 侧 */ { // TODO: 这里需要优化,目前PPPoE代理的时候没有默认路由 // 因此需要进行判断,如果没有默认路由那么就需要使用使用sip_udp_wan_socket // 发包,否则一直使用 sip_udp_socket 发包 // if (没有默认路由) if (0 != sip_udp_wan_socket) { sts = sendto(sip_udp_wan_socket, buffer, size, 0, (const struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)); } else if (0 == sip_udp_wan_socket) { sts = sendto(sip_udp_socket, buffer, size, 0, (const struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)); } else { ERROR("no proper socket fd to send out"); } } if (sts == -1) { if (errno != ECONNREFUSED) { ERROR("sendto() [%s:%i size=%i] call failed: %s", utils_inet_ntoa(addr), port, size, strerror(errno)); return STS_FAILURE; } DEBUGC(DBCLASS_BABBLE,"sendto() [%s:%i] call failed: %s", utils_inet_ntoa(addr), port, strerror(errno)); } } else { sock=socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) { printsip("Sip: socket() call failed: %s",strerror(errno)); return STS_FAILURE; } dst_addr.sin_family = AF_INET; memcpy(&dst_addr.sin_addr.s_addr, &addr, sizeof(struct in_addr)); dst_addr.sin_port= htons(port); DEBUGC(DBCLASS_NET,"send UDP packet to %s: %i", utils_inet_ntoa(addr),port); printsip("Sip:send UDP packet to %s: %i\r\n", utils_inet_ntoa(addr),port); DUMP_BUFFER(DBCLASS_NETTRAF, buffer, size); /* 本地发送源 */ bzero(&stLocalAddr, 0); /* 目的ip为LAN侧ip */ if ((1 == IpisInNet(utils_inet_ntoa(addr), g_acBrIpAddr, g_acBrMask)) || (1 == IpisInNet(utils_inet_ntoa(addr), g_acPPPoEIpAddr, g_acPPPoEMask))) { get_ip_by_ifname(configuration.inbound_if, &stLocalAddr.sin_addr); } else { get_ip_by_ifname(configuration.outbound_if, &stLocalAddr.sin_addr); } /* if (g_lPacketDir == 0) { get_ip_by_ifname(configuration.outbound_if,&stLocalAddr.sin_addr); // stLocalAddr.sin_port = htons(atoi(pszLocalPort)); } else { get_ip_by_ifname(configuration.inbound_if,&stLocalAddr.sin_addr); // stLocalAddr.sin_port = htons(atoi(pszLocalPort)); } */ stLocalAddr.sin_family = AF_INET; if (bind(sock, (struct sockaddr *)&stLocalAddr, sizeof(stLocalAddr)) < 0) { perror("bind"); } else { printsip("Sip: bind src ip:[%s]\r\n", inet_ntoa(stLocalAddr.sin_addr)); } // if (0 != sip_udp_socket) #if 0 if ((1 == IpisInNet(utils_inet_ntoa(addr), g_acBrIpAddr, g_acBrMask)) || (1 == IpisInNet(utils_inet_ntoa(addr), g_acPPPoEIpAddr, g_acPPPoEMask))) #else if (0) #endif { sts = sendto(sock, buffer, size, 0, (const struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)); } else if (0 != sip_udp_socket) { sts = sendto(sip_udp_socket, buffer, size, 0, (const struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)); } else { printf("no proper socket found \r\n"); } if (sts == -1) { if (errno != ECONNREFUSED) { ERROR("sendto() [%s:%i size=%i] call failed: %s", utils_inet_ntoa(addr), port, size, strerror(errno)); close(sock); return STS_FAILURE; } DEBUGC(DBCLASS_BABBLE,"sendto() [%s:%i] call failed: %s", utils_inet_ntoa(addr), port, strerror(errno)); } close(sock); } return STS_SUCCESS; }