nathelper.c
来自「性能优秀的SIP Proxy」· C语言 代码 · 共 2,354 行 · 第 1/5 页
C
2,354 行
} memset(pnode, 0, sizeof(*pnode)); pnode->rn_recheck_ticks = 0; pnode->rn_weight = weight; pnode->rn_umode = 0; pnode->rn_fd = -1; pnode->rn_disabled = 0; pnode->rn_url = pkg_malloc(p2 - p1 + 1); if (pnode->rn_url == NULL) { LOG(L_ERR, "nathelper: Can't allocate memory\n"); return -1; } memmove(pnode->rn_url, p1, p2 - p1); pnode->rn_url[p2 - p1] = 0; if (rtpp_list.rn_first == NULL) { rtpp_list.rn_first = pnode; } else { rtpp_list.rn_last->rn_next = pnode; } rtpp_list.rn_last = pnode; ++rtpp_node_count; /* Leave only address in rn_address */ pnode->rn_address = pnode->rn_url; if (strncmp(pnode->rn_address, "udp:", 4) == 0) { pnode->rn_umode = 1; pnode->rn_address += 4; } else if (strncmp(pnode->rn_address, "udp6:", 5) == 0) { pnode->rn_umode = 6; pnode->rn_address += 5; } else if (strncmp(pnode->rn_address, "unix:", 5) == 0) { pnode->rn_umode = 0; pnode->rn_address += 5; } } } return 0;}static intchild_init(int rank){ int n; char *cp; struct addrinfo hints, *res; struct rtpp_node *pnode; /* Iterate known RTP proxies - create sockets */ mypid = getpid(); for (pnode = rtpp_list.rn_first; pnode != NULL; pnode = pnode->rn_next) { char *old_colon; if (pnode->rn_umode == 0) goto rptest; /* * This is UDP or UDP6. Detect host and port; lookup host; * do connect() in order to specify peer address */ old_colon = cp = strrchr(pnode->rn_address, ':'); if (cp != NULL) { old_colon = cp; *cp = '\0'; cp++; } if (cp == NULL || *cp == '\0') cp = CPORT; memset(&hints, 0, sizeof(hints)); hints.ai_flags = 0; hints.ai_family = (pnode->rn_umode == 6) ? AF_INET6 : AF_INET; hints.ai_socktype = SOCK_DGRAM; if ((n = getaddrinfo(pnode->rn_address, cp, &hints, &res)) != 0) { LOG(L_ERR, "nathelper: getaddrinfo: %s\n", gai_strerror(n)); return -1; } if (old_colon) *old_colon = ':'; /* restore rn_address */ pnode->rn_fd = socket((pnode->rn_umode == 6) ? AF_INET6 : AF_INET, SOCK_DGRAM, 0); if (pnode->rn_fd == -1) { LOG(L_ERR, "nathelper: can't create socket\n"); freeaddrinfo(res); return -1; } if (connect(pnode->rn_fd, res->ai_addr, res->ai_addrlen) == -1) { LOG(L_ERR, "nathelper: can't connect to a RTP proxy\n"); close(pnode->rn_fd); pnode->rn_fd = -1; freeaddrinfo(res); return -1; } freeaddrinfo(res);rptest: pnode->rn_disabled = rtpp_test(pnode, 0, 1); } if (rtpproxy_disable) rtpproxy_disable_tout = -1; return 0;}static intisnulladdr(str *sx, int pf){ char *cp; if (pf == AF_INET6) { for(cp = sx->s; cp < sx->s + sx->len; cp++) if (*cp != '0' && *cp != ':') return 0; return 1; } return (sx->len == 7 && memcmp("0.0.0.0", sx->s, 7) == 0);}/* * ser_memmem() returns the location of the first occurrence of data * pattern b2 of size len2 in memory block b1 of size len1 or * NULL if none is found. Obtained from NetBSD. */static void *ser_memmem(const void *b1, const void *b2, size_t len1, size_t len2){ /* Initialize search pointer */ char *sp = (char *) b1; /* Initialize pattern pointer */ char *pp = (char *) b2; /* Initialize end of search address space pointer */ char *eos = sp + len1 - len2; /* Sanity check */ if(!(b1 && b2 && len1 && len2)) return NULL; while (sp <= eos) { if (*sp == *pp) if (memcmp(sp, pp, len2) == 0) return sp; sp++; } return NULL;}/* * Some helper functions taken verbatim from tm module. *//* * Extract tag from To header field of a response * assumes the to header is already parsed, so * make sure it really is before calling this function */static inline intget_to_tag(struct sip_msg* _m, str* _tag){ if (!_m->to) { LOG(L_ERR, "get_to_tag(): To header field missing\n"); return -1; } if (get_to(_m)->tag_value.len) { _tag->s = get_to(_m)->tag_value.s; _tag->len = get_to(_m)->tag_value.len; } else { _tag->len = 0; } return 0;}/* * Extract tag from From header field of a request */static inline intget_from_tag(struct sip_msg* _m, str* _tag){ if (parse_from_header(_m)<0) { LOG(L_ERR, "get_from_tag(): Error while parsing From header\n"); return -1; } if (get_from(_m)->tag_value.len) { _tag->s = get_from(_m)->tag_value.s; _tag->len = get_from(_m)->tag_value.len; } else { _tag->len = 0; } return 0;}/* * Extract Call-ID value * assumes the callid header is already parsed * (so make sure it is, before calling this function or * it might fail even if the message _has_ a callid) */static inline intget_callid(struct sip_msg* _m, str* _cid){ if ((parse_headers(_m, HDR_CALLID_F, 0) == -1)) { LOG(L_ERR, "get_callid(): parse_headers() failed\n"); return -1; } if (_m->callid == NULL) { LOG(L_ERR, "get_callid(): Call-ID not found\n"); return -1; } _cid->s = _m->callid->body.s; _cid->len = _m->callid->body.len; trim(_cid); return 0;}/* * Extract URI from the Contact header field */static inline intget_contact_uri(struct sip_msg* _m, struct sip_uri *uri, contact_t** _c){ if ((parse_headers(_m, HDR_CONTACT_F, 0) == -1) || !_m->contact) return -1; if (!_m->contact->parsed && parse_contact(_m->contact) < 0) { LOG(L_ERR, "get_contact_uri: Error while parsing Contact body\n"); return -1; } *_c = ((contact_body_t*)_m->contact->parsed)->contacts; if (*_c == NULL) /* no contacts found */ return -1; if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) { LOG(L_ERR, "get_contact_uri: Error while parsing Contact URI\n"); return -1; } return 0;}/* * Replaces ip:port pair in the Contact: field with the source address * of the packet. */static intfix_nated_contact_f(struct sip_msg* msg, char* str1, char* str2){ int offset, len, len1; char *cp, *buf, temp[2]; contact_t *c; struct lump *anchor; struct sip_uri uri; str hostport; if (get_contact_uri(msg, &uri, &c) == -1) return -1; if ((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) { LOG(L_ERR, "ERROR: you can't call fix_nated_contact twice, " "check your config!\n"); return -1; } offset = c->uri.s - msg->buf; anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT_T); if (anchor == 0) return -1; hostport = uri.host; if (uri.port.len > 0) hostport.len = uri.port.s + uri.port.len - uri.host.s; cp = ip_addr2a(&msg->rcv.src_ip); len = c->uri.len + strlen(cp) + 6 /* :port */ - hostport.len + 1; buf = pkg_malloc(len); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_contact: out of memory\n"); return -1; } temp[0] = hostport.s[0]; temp[1] = c->uri.s[c->uri.len]; c->uri.s[c->uri.len] = hostport.s[0] = '\0'; len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp, msg->rcv.src_port, hostport.s + hostport.len); if (len1 < len) len = len1; hostport.s[0] = temp[0]; c->uri.s[c->uri.len] = temp[1]; if (insert_new_lump_after(anchor, buf, len, HDR_CONTACT_T) == 0) { pkg_free(buf); return -1; } c->uri.s = buf; c->uri.len = len; return 1;}inline static intfixup_str2int( void** param, int param_no){ unsigned long go_to; int err; if (param_no == 1 || param_no == 2) { go_to = str2s(*param, strlen(*param), &err); if (err == 0) { pkg_free(*param); *param = (void *)go_to; return 0; } else { LOG(L_ERR, "ERROR: fixup_str2int: bad number <%s>\n", (char *)(*param)); return E_CFG; } } return 0;}/* * Test if IP address pointed to by saddr belongs to RFC1918 networks */static inline intis1918addr(str *saddr){ struct in_addr addr; uint32_t netaddr; int i, rval; char backup; rval = -1; backup = saddr->s[saddr->len]; saddr->s[saddr->len] = '\0'; if (inet_aton(saddr->s, &addr) != 1) goto theend; netaddr = ntohl(addr.s_addr); for (i = 0; nets_1918[i].cnetaddr != NULL; i++) { if ((netaddr & nets_1918[i].mask) == nets_1918[i].netaddr) { rval = 1; goto theend; } } rval = 0;theend: saddr->s[saddr->len] = backup; return rval;}/* * test for occurrence of RFC1918 IP address in Contact HF */static intcontact_1918(struct sip_msg* msg){ struct sip_uri uri; contact_t* c; if (get_contact_uri(msg, &uri, &c) == -1) return -1; return (is1918addr(&(uri.host)) == 1) ? 1 : 0;}/* * test for occurrence of RFC1918 IP address in SDP */static intsdp_1918(struct sip_msg* msg){ str body, ip; int pf; if (extract_body(msg, &body) == -1) { LOG(L_ERR,"ERROR: sdp_1918: cannot extract body from msg!\n"); return 0; } if (extract_mediaip(&body, &ip, &pf,"c=") == -1) { LOG(L_ERR, "ERROR: sdp_1918: can't extract media IP from the SDP\n"); return 0; } if (pf != AF_INET || isnulladdr(&ip, pf)) return 0; return (is1918addr(&ip) == 1) ? 1 : 0;}/* * test for occurrence of RFC1918 IP address in top Via */static intvia_1918(struct sip_msg* msg){ return (is1918addr(&(msg->via1->host)) == 1) ? 1 : 0;}static intnat_uac_test_f(struct sip_msg* msg, char* str1, char* str2){ int tests; tests = (int)(long)str1; /* return true if any of the NAT-UAC tests holds */ /* test if the source port is different from the port in Via */ if ((tests & NAT_UAC_TEST_RPORT) && (msg->rcv.src_port!=(msg->via1->port?msg->via1->port:SIP_PORT)) ){ return 1; } /* * test if source address of signaling is different from * address advertised in Via */ if ((tests & NAT_UAC_TEST_RCVD) && received_test(msg)) return 1; /* * test for occurrences of RFC1918 addresses in Contact * header field */ if ((tests & NAT_UAC_TEST_C_1918) && (contact_1918(msg)>0)) return 1; /* * test for occurrences of RFC1918 addresses in SDP body */ if ((tests & NAT_UAC_TEST_S_1918) && sdp_1918(msg)) return 1; /* * test for occurrences of RFC1918 addresses top Via */ if ((tests & NAT_UAC_TEST_V_1918) && via_1918(msg)) return 1; /* no test succeeded */ return -1;}#define ADD_ADIRECTION 0x01#define FIX_MEDIP 0x02#define ADD_ANORTPPROXY 0x04#define FIX_ORGIP 0x08#define ADIRECTION "a=direction:active\r\n"#define ADIRECTION_LEN (sizeof(ADIRECTION) - 1)#define AOLDMEDIP "a=oldmediaip:"#define AOLDMEDIP_LEN (sizeof(AOLDMEDIP) - 1)#define AOLDMEDIP6 "a=oldmediaip6:"#define AOLDMEDIP6_LEN (sizeof(AOLDMEDIP6) - 1)#define AOLDMEDPRT "a=oldmediaport:"#define AOLDMEDPRT_LEN (sizeof(AOLDMEDPRT) - 1)#define ANORTPPROXY "a=nortpproxy:yes\r\n"#define ANORTPPROXY_LEN (sizeof(ANORTPPROXY) - 1)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?