📄 nathelper.c
字号:
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) == -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 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)static intfix_nated_sdp_f(struct sip_msg* msg, char* str1, char* str2){ str body, body1, oldip, oldip1, newip; int level, pf, pf1; char *buf; struct lump* anchor; level = (int)(long)str1; if (extract_body(msg, &body) == -1) { LOG(L_ERR,"ERROR: fix_nated_sdp: cannot extract body from msg!\n"); return -1; } if (level & (ADD_ADIRECTION | ADD_ANORTPPROXY)) { msg->msg_flags |= FL_FORCE_ACTIVE; anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: anchor_lump failed\n"); return -1; } if (level & ADD_ADIRECTION) { buf = pkg_malloc(ADIRECTION_LEN * sizeof(char)); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n"); return -1; } memcpy(buf, ADIRECTION, ADIRECTION_LEN); if (insert_new_lump_after(anchor, buf, ADIRECTION_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } } if (level & ADD_ANORTPPROXY) { buf = pkg_malloc(ANORTPPROXY_LEN * sizeof(char)); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n"); return -1; } memcpy(buf, ANORTPPROXY, ANORTPPROXY_LEN); if (insert_new_lump_after(anchor, buf, ANORTPPROXY_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } } } if (level & FIX_MEDIP) { if (extract_mediaip(&body, &oldip, &pf) == -1) { LOG(L_ERR, "ERROR: fix_nated_sdp: can't extract media IP from the SDP\n"); goto finalize; } if (pf != AF_INET) { LOG(L_ERR, "ERROR: fix_nated_sdp: " "not an IPv4 address in SDP\n"); goto finalize; } body1.s = oldip.s + oldip.len; body1.len = body.s + body.len - body1.s; if (extract_mediaip(&body1, &oldip1, &pf1) == -1) { oldip1.len = 0; } if (oldip1.len > 0 && pf != pf1) { LOG(L_ERR, "ERROR: fix_nated_sdp: mismatching " "address families in SDP\n"); return -1; } newip.s = ip_addr2a(&msg->rcv.src_ip); newip.len = strlen(newip.s); if (alter_mediaip(msg, &body, &oldip, pf, &newip, pf, 1) == -1) { LOG(L_ERR, "ERROR: fix_nated_sdp: can't alter media IP"); return -1; } if (oldip1.len > 0 && alter_mediaip(msg, &body, &oldip1, pf1, &newip, pf, 0) == -1) { LOG(L_ERR, "ERROR: fix_nated_sdp: can't alter media IP"); return -1; } }finalize: return 1;}static intextract_mediaip(str *body, str *mediaip, int *pf){ char *cp, *cp1; int len, nextisip; cp1 = NULL; for (cp = body->s; (len = body->s + body->len - cp) > 0;) { cp1 = ser_memmem(cp, "c=", len, 2); if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r') break; cp = cp1 + 2; } if (cp1 == NULL) { LOG(L_DBG, "ERROR: extract_mediaip: no `c=' in SDP\n"); return -1; } mediaip->s = cp1 + 2; mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s; trim_len(mediaip->len, mediaip->s, *mediaip); nextisip = 0; for (cp = mediaip->s; cp < mediaip->s + mediaip->len;) { len = eat_token_end(cp, mediaip->s + mediaip->len) - cp; if (nextisip == 1) { mediaip->s = cp; mediaip->len = len; nextisip++; break; } if (len == 3 && memcmp(cp, "IP", 2) == 0) { switch (cp[2]) { case '4': nextisip = 1; *pf = AF_INET; break; case '6': nextisip = 1; *pf = AF_INET6; break; default: break; } } cp = eat_space_end(cp + len, mediaip->s + mediaip->len); } if (nextisip != 2 || mediaip->len == 0) { LOG(L_ERR, "ERROR: extract_mediaip: " "no `IP[4|6]' in `c=' field\n"); return -1; } return 1;}static intextract_mediaport(str *body, str *mediaport){ char *cp, *cp1; int len; cp1 = NULL; for (cp = body->s; (len = body->s + body->len - cp) > 0;) { cp1 = ser_memmem(cp, "m=", len, 2); if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r') break; cp = cp1 + 2; } if (cp1 == NULL) { LOG(L_ERR, "ERROR: extract_mediaport: no `m=' in SDP\n"); return -1; } mediaport->s = cp1 + 2; mediaport->len = eat_line(mediaport->s, body->s + body->len - mediaport->s) - mediaport->s; trim_len(mediaport->len, mediaport->s, *mediaport); if (mediaport->len > 6 && memcmp(mediaport->s, "audio", 5) == 0 && isspace((int)mediaport->s[5])) { mediaport->s += 5; mediaport->len -= 5; } else if (mediaport->len > 12 && memcmp(mediaport->s, "application", 11) == 0 && isspace((int)mediaport->s[11])) { mediaport->s += 11; mediaport->len -= 11; } else { LOG(L_ERR, "ERROR: extract_mediaport: can't parse `m=' in SDP\n"); return -1; } cp = eat_space_end(mediaport->s, mediaport->s + mediaport->len); mediaport->len = eat_token_end(cp, mediaport->s + mediaport->len) - cp; mediaport->s = cp; return 1;}static intalter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf, str *newip, int newpf, int preserve){ char *buf; int offset; struct lump* anchor; str omip, nip, oip; /* check that updating mediaip is really necessary */ if (oldpf == newpf && isnulladdr(oldip, oldpf)) return 0; if (newip->len == oldip->len && memcmp(newip->s, oldip->s, newip->len) == 0) return 0; /* * Since rewriting the same info twice will mess SDP up, * apply simple anti foot shooting measure - put flag on * messages that have been altered and check it when * another request comes. */#if 0 /* disabled: * - alter_mediaip is called twice if 2 c= lines are present * in the sdp (and we want to allow it) * - the message flags are propagated in the on_reply_route * => if we set the flags for the request they will be seen for the * reply too, but we don't want that * --andrei */ if (msg->msg_flags & FL_SDP_IP_AFS) { LOG(L_ERR, "ERROR: alter_mediaip: you can't rewrite the same " "SDP twice, check your config!\n"); return -1; }#endif if (preserve != 0) { anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: anchor_lump failed\n"); return -1; } if (oldpf == AF_INET6) { omip.s = AOLDMEDIP6; omip.len = AOLDMEDIP6_LEN; } else { omip.s = AOLDMEDIP; omip.len = AOLDMEDIP_LEN; } buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN); if (buf == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n"); return -1; } memcpy(buf, omip.s, omip.len); memcpy(buf + omip.len, oldip->s, oldip->len); memcpy(buf + omip.len + oldip->len, CRLF, CRLF_LEN); if (insert_new_lump_after(anchor, buf, omip.len + oldip->len + CRLF_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } } if (oldpf == newpf) { nip.len = newip->len; nip.s = pkg_malloc(nip.len); if (nip.s == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n"); return -1; } memcpy(nip.s, newip->s, newip->len); } else { nip.len = newip->len + 2; nip.s = pkg_malloc(nip.len); if (nip.s == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n"); return -1; } memcpy(nip.s + 2, newip->s, newip->len); nip.s[0] = (newpf == AF_INET6) ? '6' : '4'; nip.s[1] = ' '; } oip = *oldip; if (oldpf != newpf) { do { oip.s--; oip.len++; } while (*oip.s != '6' && *oip.s != '4'); } offset = oip.s - msg->buf; anchor = del_lump(msg, offset, oip.len, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: alter_mediaip: del_lump failed\n"); pkg_free(nip.s); return -1; }#if 0 msg->msg_flags |= FL_SDP_IP_AFS;#endif if (insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) { LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n"); pkg_free(nip.s); return -1; } return 0;}static intalter_mediaport(struct sip_msg *msg, str *body, str *oldport, str *newport, int preserve){ char *buf; int offset; struct lump* anchor; /* check that updating mediaport is really necessary */ if (newport->len == oldport->len && memcmp(newport->s, oldport->s, newport->len) == 0) return 0; /* * Since rewriting the same info twice will mess SDP up, * apply simple anti foot shooting measure - put flag on * messages that have been altered and check it when * another request comes. */#if 0 /* disabled: - it propagates to the reply and we don't want this * -- andrei */ if (msg->msg_flags & FL_SDP_PORT_AFS) { LOG(L_ERR, "ERROR: alter_mediaip: you can't rewrite the same " "SDP twice, check your config!\n"); return -1; }#endif if (preserve != 0) { anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: alter_mediaport: anchor_lump failed\n"); return -1; } buf = pkg_malloc(AOLDMEDPRT_LEN + oldport->len + CRLF_LEN); if (buf == NULL) { LOG(L_ERR, "ERROR: alter_mediaport: out of memory\n"); return -1; } memcpy(buf, AOLDMEDPRT, AOLDMEDPRT_LEN); memcpy(buf + AOLDMEDPRT_LEN, oldport->s, oldport->len); memcpy(buf + AOLDMEDPRT_LEN + oldport->len, CRLF, CRLF_LEN); if (insert_new_lump_after(anchor, buf, AOLDMEDPRT_LEN + oldport->len + CRLF_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: alter_mediaport: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } } buf = pkg_malloc(newport->len); if (buf == NULL) { LOG(L_ERR, "ERROR: alter_mediaport: out of memory\n"); return -1; } offset = oldport->s - msg->buf; anchor = del_lump(msg, offset, oldport->len, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: alter_mediaport: del_lump failed\n"); pkg_free(buf); return -1; } memcpy(buf, newport->s, newport->len); if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) { LOG(L_ERR, "ERROR: alter_mediaport: insert_new_lump_after failed\n"); pkg_free(buf); return -1; }#if 0 msg->msg_flags |= FL_SDP_PORT_AFS;#endif return 0;}static char *gencookie(){ static char cook[34]; sprintf(cook, "%d_%u ", (int)mypid, myseqn); myseqn++; return cook;}static intrtpp_test(int isdisabled, int force){ int rtpp_ver; static int recheck_ticks = 0; char *cp; struct iovec v[2] = {{NULL, 0}, {"V", 1}}; if (force == 0) { if (isdisabled == 0) return 0; if (recheck_ticks > get_ticks()) return 1; } cp = send_rtpp_command(v, 2); if (cp == NULL) { LOG(L_WARN,"WARNING: rtpp_test: can't get version of " "the RTP proxy\n"); } else { rtpp_ver = atoi(cp); if (rtpp_ver == SUP_CPROTOVER) { LOG(L_INFO, "rtpp_test: RTP proxy found, support for " "it %senabled\n", force == 0 ? "re-" : ""); return 0; } LOG(L_WARN, "WARNING: rtpp_test: unsupported " "version of RTP proxy found: %d supported, " "%d present\n", SUP_CPROTOVER, rtpp_ver); } LOG(L_WARN, "WARNING: rtpp_test: support for RTP proxy " "has been disabled%s\n", rtpproxy_disable_tout < 0 ? "" : " temporarily"); if (rtpproxy_disable_tout >= 0) recheck_ticks = get_ticks() + rtpproxy_disable_tout; return 1;}static char *send_rtpp_command(struct iovec *v, int vcnt){ struct sockaddr_un addr; int fd, len, i; char *cp; static char buf[256]; struct pollfd fds[1]; len = 0; cp = buf; if (umode == 0) { memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_LOCAL; strncpy(addr.sun_path, rtpproxy_sock, sizeof(addr.sun_path) - 1);#ifdef HAVE_SOCKADDR_SA_LEN addr.sun_len = strlen(addr.sun_path);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -