📄 nathelper.c
字号:
fd = socket(AF_LOCAL, SOCK_STREAM, 0); if (fd < 0) { LOG(L_ERR, "ERROR: send_rtpp_command: can't create socket\n"); return NULL; } if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { close(fd); LOG(L_ERR, "ERROR: send_rtpp_command: can't connect to RTP proxy\n"); return NULL; } do { len = writev(fd, v + 1, vcnt - 1); } while (len == -1 && errno == EINTR); if (len <= 0) { close(fd); LOG(L_ERR, "ERROR: send_rtpp_command: can't send command to a RTP proxy\n"); return NULL; } do { len = read(fd, buf, sizeof(buf) - 1); } while (len == -1 && errno == EINTR); close(fd); if (len <= 0) { LOG(L_ERR, "ERROR: send_rtpp_command: can't read reply from a RTP proxy\n"); return NULL; } } else { fds[0].fd = controlfd; fds[0].events = POLLIN; fds[0].revents = 0; /* Drain input buffer */ while ((poll(fds, 1, 0) == 1) && ((fds[0].revents & POLLIN) != 0)) { recv(controlfd, buf, sizeof(buf) - 1, 0); fds[0].revents = 0; } v[0].iov_base = gencookie(); v[0].iov_len = strlen(v[0].iov_base); for (i = 0; i < rtpproxy_retr; i++) { do { len = writev(controlfd, v, vcnt); } while (len == -1 && (errno == EINTR || errno == ENOBUFS)); if (len <= 0) { LOG(L_ERR, "ERROR: send_rtpp_command: " "can't send command to a RTP proxy\n"); return NULL; } while ((poll(fds, 1, rtpproxy_tout * 1000) == 1) && (fds[0].revents & POLLIN) != 0) { do { len = recv(controlfd, buf, sizeof(buf) - 1, 0); } while (len == -1 && errno == EINTR); if (len <= 0) { LOG(L_ERR, "ERROR: send_rtpp_command: " "can't read reply from a RTP proxy\n"); return NULL; } if (len >= (v[0].iov_len - 1) && memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) { len -= (v[0].iov_len - 1); cp += (v[0].iov_len - 1); if (len != 0) { len--; cp++; } goto out; } fds[0].revents = 0; } } if (i == rtpproxy_retr) { LOG(L_ERR, "ERROR: send_rtpp_command: " "timeout waiting reply from a RTP proxy\n"); return NULL; } }out: cp[len] = '\0'; return cp;}static intunforce_rtp_proxy_f(struct sip_msg* msg, char* str1, char* str2){ str callid, from_tag, to_tag; struct iovec v[1 + 4 + 3] = {{NULL, 0}, {"D", 1}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}}; /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 1 */ rtpproxy_disable = rtpp_test(rtpproxy_disable, 0); if (rtpproxy_disable != 0) { LOG(L_ERR, "ERROR: unforce_rtp_proxy: support for RTP proxy " "is disabled\n"); return -1; } if (get_callid(msg, &callid) == -1 || callid.len == 0) { LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get Call-Id field\n"); return -1; } if (get_to_tag(msg, &to_tag) == -1) { LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get To tag\n"); return -1; } if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) { LOG(L_ERR, "ERROR: unforce_rtp_proxy: can't get From tag\n"); return -1; } STR2IOVEC(callid, v[3]); STR2IOVEC(from_tag, v[5]); STR2IOVEC(to_tag, v[7]); send_rtpp_command(v, (to_tag.len > 0) ? 8 : 6); return 1;}static intforce_rtp_proxy2_f(struct sip_msg* msg, char* str1, char* str2){ str body, body1, oldport, oldip, oldip1, newport, newip; str callid, from_tag, to_tag, tmp; int create, port, len, asymmetric, flookup, argc, proxied, real; int oidx, pf, pf1, force; char opts[16]; char *cp, *cp1; char *cpend, *next; char **ap, *argv[10]; struct lump* anchor; struct iovec v[1 + 6 + 5] = {{NULL, 0}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 7}, {" ", 1}, {NULL, 1}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}}; /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* 10 */ /* 11 */ v[1].iov_base=opts; asymmetric = flookup = force = real = 0; oidx = 1; for (cp = str1; *cp != '\0'; cp++) { switch (*cp) { case 'a': case 'A': opts[oidx++] = 'A'; asymmetric = 1; real = 1; break; case 'i': case 'I': opts[oidx++] = 'I'; break; case 'e': case 'E': opts[oidx++] = 'E'; break; case 'l': case 'L': flookup = 1; break; case 'f': case 'F': force = 1; break; case 'r': case 'R': real = 1; break; default: LOG(L_ERR, "ERROR: force_rtp_proxy2: unknown option `%c'\n", *cp); return -1; } } rtpproxy_disable = rtpp_test(rtpproxy_disable, 0); if (rtpproxy_disable != 0) { LOG(L_ERR, "ERROR: force_rtp_proxy2: support for RTP proxy " "is disabled\n"); return -1; } if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE) { create = 1; } else if (msg->first_line.type == SIP_REPLY) { create = 0; } else { return -1; } /* extract_body will also parse all the headers in the message as * a side effect => don't move get_callid/get_to_tag in front of it * -- andrei */ if (extract_body(msg, &body) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract body " "from the message\n"); return -1; } if (get_callid(msg, &callid) == -1 || callid.len == 0) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get Call-Id field\n"); return -1; } if (get_to_tag(msg, &to_tag) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get To tag\n"); return -1; } if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get From tag\n"); return -1; } if (flookup != 0) { if (create == 0 || to_tag.len == 0) return -1; create = 0; tmp = from_tag; from_tag = to_tag; to_tag = tmp; } proxied = 0; for (cp = body.s; (len = body.s + body.len - cp) >= ANORTPPROXY_LEN;) { cp1 = ser_memmem(cp, ANORTPPROXY, len, ANORTPPROXY_LEN); if (cp1 == NULL) break; if (cp1[-1] == '\n' || cp1[-1] == '\r') { proxied = 1; break; } cp = cp1 + ANORTPPROXY_LEN; } if (proxied != 0 && force == 0) return -1; if (extract_mediaip(&body, &oldip, &pf) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract media IP " "from the message\n"); return -1; } if (asymmetric != 0 || real != 0) { newip = oldip; } else { newip.s = ip_addr2a(&msg->rcv.src_ip); newip.len = strlen(newip.s); } 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: force_rtp_proxy2: mismatching address " "families in SDP\n"); return -1; } if (extract_mediaport(&body, &oldport) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract media port " "from the message\n"); return -1; } if (pf == AF_INET6) { opts[oidx] = '6'; oidx++; } opts[0] = (create == 0) ? 'L' : 'U'; v[1].iov_len = oidx; STR2IOVEC(callid, v[3]); STR2IOVEC(newip, v[5]); STR2IOVEC(oldport, v[7]); STR2IOVEC(from_tag, v[9]); STR2IOVEC(to_tag, v[11]); cp = send_rtpp_command(v, (to_tag.len > 0) ? 12 : 10); if (cp == NULL) return -1; argc = 0; memset(argv, 0, sizeof(argv)); cpend=cp+strlen(cp); next=eat_token_end(cp, cpend); for (ap = argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){ *next=0; if (*cp != '\0') { *ap=cp; argc++; if ((char*)++ap >= ((char*)argv+sizeof(argv))) break; } } if (argc < 1) return -1; port = atoi(argv[0]); if (port <= 0 || port > 65535) return -1; pf1 = (argc >= 3 && argv[2][0] == '6') ? AF_INET6 : AF_INET; if (isnulladdr(&oldip, pf)) { if (pf1 == AF_INET6) { newip.s = "::"; newip.len = 2; } else { newip.s = "0.0.0.0"; newip.len = 7; } } else { newip.s = (argc < 2) ? str2 : argv[1]; newip.len = strlen(newip.s); } newport.s = int2str(port, &newport.len); /* beware static buffer */ if (alter_mediaip(msg, &body, &oldip, pf, &newip, pf1, 0) == -1) return -1; if (oldip1.len > 0 && alter_mediaip(msg, &body1, &oldip1, pf, &newip, pf1, 0) == -1) return -1; if (alter_mediaport(msg, &body, &oldport, &newport, 0) == -1) return -1; if (proxied == 0) { cp = pkg_malloc(ANORTPPROXY_LEN * sizeof(char)); if (cp == NULL) { LOG(L_ERR, "ERROR: force_rtp_proxy2: out of memory\n"); return -1; } anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: force_rtp_proxy2: anchor_lump failed\n"); pkg_free(cp); return -1; } memcpy(cp, ANORTPPROXY, ANORTPPROXY_LEN); if (insert_new_lump_after(anchor, cp, ANORTPPROXY_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: force_rtp_proxy2: insert_new_lump_after failed\n"); pkg_free(cp); return -1; } } return 1;}static intforce_rtp_proxy1_f(struct sip_msg* msg, char* str1, char* str2){ char *cp; char newip[IP_ADDR_MAX_STR_SIZE]; cp = ip_addr2a(&msg->rcv.dst_ip); strcpy(newip, cp); return force_rtp_proxy2_f(msg, str1, newip);}static intforce_rtp_proxy0_f(struct sip_msg* msg, char* str1, char* str2){ char arg[1] = {'\0'}; return force_rtp_proxy1_f(msg, arg, NULL);}static voidtimer(unsigned int ticks, void *param){ int rval; void *buf, *cp; str c; struct sip_uri curi; union sockaddr_union to; struct hostent* he; struct socket_info* send_sock; buf = NULL; if (cblen > 0) { buf = pkg_malloc(cblen); if (buf == NULL) { LOG(L_ERR, "ERROR: nathelper::timer: out of memory\n"); return; } } rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? FL_NAT : 0)); if (rval > 0) { if (buf != NULL) pkg_free(buf); cblen = rval * 2; buf = pkg_malloc(cblen); if (buf == NULL) { LOG(L_ERR, "ERROR: nathelper::timer: out of memory\n"); return; } rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? FL_NAT : 0)); if (rval != 0) { pkg_free(buf); return; } } if (buf == NULL) return; cp = buf; while (1) { memcpy(&(c.len), cp, sizeof(c.len)); if (c.len == 0) break; c.s = (char*)cp + sizeof(c.len); cp = (char*)cp + sizeof(c.len) + c.len; if (parse_uri(c.s, c.len, &curi) < 0) { LOG(L_ERR, "ERROR: nathelper::timer: can't parse contact uri\n"); continue; } if (curi.proto != PROTO_UDP && curi.proto != PROTO_NONE) continue; if (curi.port_no == 0) curi.port_no = SIP_PORT; he = sip_resolvehost(&curi.host, &curi.port_no, PROTO_UDP); if (he == NULL){ LOG(L_ERR, "ERROR: nathelper::timer: can't resolve_hos\n"); continue; } hostent2su(&to, he, 0, curi.port_no); send_sock=force_socket ? force_socket : get_send_socket(0, &to, PROTO_UDP); if (send_sock == NULL) { LOG(L_ERR, "ERROR: nathelper::timer: can't get sending socket\n"); continue; } udp_send(send_sock, (char *)sbuf, sizeof(sbuf), &to); } pkg_free(buf);}/* * Create received SIP uri that will be either * passed to registrar in an AVP or apended * to Contact header field as a parameter */static intcreate_rcv_uri(str* uri, struct sip_msg* m){ static char buf[MAX_URI_SIZE]; char* p; str ip, port; int len; str proto; if (!uri || !m) { LOG(L_ERR, "create_rcv_uri: Invalid parameter value\n"); return -1; } ip.s = ip_addr2a(&m->rcv.src_ip); ip.len = strlen(ip.s); port.s = int2str(m->rcv.src_port, &port.len); switch(m->rcv.proto) { case PROTO_NONE: case PROTO_UDP: proto.s = 0; /* Do not add transport parameter, UDP is default */ proto.len = 0; break; case PROTO_TCP: proto.s = "TCP"; proto.len = 3; break; case PROTO_TLS: proto.s = "TLS"; proto.len = 3; break; case PROTO_SCTP: proto.s = "SCTP"; proto.len = 4; break; default: LOG(L_ERR, "BUG: create_rcv_uri: Unknown transport protocol\n"); return -1; } len = 4 + ip.len + 1 + port.len; if (proto.s) { len += TRANSPORT_PARAM_LEN; len += proto.len; } if (len > MAX_URI_SIZE) { LOG(L_ERR, "create_rcv_uri: Buffer too small\n"); return -1; } p = buf; memcpy(p, "sip:", 4); p += 4; memcpy(p, ip.s, ip.len); p += ip.len; *p++ = ':'; memcpy(p, port.s, port.len); p += port.len; if (proto.s) { memcpy(p, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN); p += TRANSPORT_PARAM_LEN; memcpy(p, proto.s, proto.len); p += proto.len; } uri->s = buf; uri->len = len; return 0;}/* * Add received parameter to Contacts for further * forwarding of the REGISTER requuest */static intadd_rcv_param_f(struct sip_msg* msg, char* str1, char* str2){ contact_t* c; struct lump* anchor; char* param; str uri; if (create_rcv_uri(&uri, msg) < 0) { return -1; } if (contact_iterator(&c, msg, 0) < 0) { return -1; } while(c) { param = (char*)pkg_malloc(RECEIVED_LEN + 2 + uri.len); if (!param) { LOG(L_ERR, "add_rcv_param: No memory left\n"); return -1; } memcpy(param, RECEIVED, RECEIVED_LEN); param[RECEIVED_LEN] = '\"'; memcpy(param + RECEIVED_LEN + 1, uri.s, uri.len); param[RECEIVED_LEN + 1 + uri.len] = '\"'; anchor = anchor_lump(msg, c->name.s + c->len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "add_rcv_param: anchor_lump failed\n"); return -1; } if (insert_new_lump_after(anchor, param, RECEIVED_LEN + 1 + uri.len + 1, 0) == 0) { LOG(L_ERR, "add_rcv_param: insert_new_lump_after failed\n"); pkg_free(param); return -1; } if (contact_iterator(&c, msg, c) < 0) { return -1; } } return 1;}/* * Create an AVP to be used by registrar with the source IP and port * of the REGISTER */static intfix_nated_register_f(struct sip_msg* msg, char* str1, char* str2){ str uri; int_str val; int_str rcv_avp; if (create_rcv_uri(&uri, msg) < 0) { return -1; } val.s = &uri; rcv_avp.n=rcv_avp_no; if (add_avp(AVP_VAL_STR, rcv_avp, val) < 0) { LOG(L_ERR, "fix_nated_register: Error while creating AVP\n"); return -1; } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -