예제 #1
0
파일: sdp_util.c 프로젝트: asyn/openvims
static int unforce_rtp_proxy_f(struct sip_msg* msg, int node_idx)
{
	str callid, from_tag, to_tag;
	struct rtpp_node *node;
	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 */
	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]);
	node = select_rtpp_node(callid, 1, node_idx);
	if (!node) {
		LOG(L_ERR, "ERROR: unforce_rtp_proxy: no available proxies\n");
		return -1;
	}
	send_rtpp_command(node, v, (to_tag.len > 0) ? 8 : 6);

	return 1;
}
static int
ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
{
	struct ip_vs_iphdr iph;
	unsigned int dataoff, datalen, matchoff, matchlen;
	const char *dptr;
	int retc;

	ip_vs_fill_iphdr(p->af, skb_network_header(skb), &iph);

	
	if (iph.protocol != IPPROTO_UDP)
		return -EINVAL;

	
	dataoff = iph.len + sizeof(struct udphdr);
	if (dataoff >= skb->len)
		return -EINVAL;

	if ((retc=skb_linearize(skb)) < 0)
		return retc;
	dptr = skb->data + dataoff;
	datalen = skb->len - dataoff;

	if (get_callid(dptr, dataoff, datalen, &matchoff, &matchlen))
		return -EINVAL;

	p->pe_data = kmemdup(dptr + matchoff, matchlen, GFP_ATOMIC);
	if (!p->pe_data)
		return -ENOMEM;

	p->pe_data_len = matchlen;

	return 0;
}
예제 #3
0
	static int
rtpproxy_stop_stream(struct sip_msg* msg, int stream2uac)
{
	int nitems;
	str callid, from_tag, to_tag;
	struct rtpp_node *node;
	struct iovec v[] = {
		{NULL,        0},
		{"S",         1}, /* 1 */
		{" ",         1},
		{NULL,        0}, /* 3 callid */
		{" ",         1},
		{NULL,        0}, /* 5 from tag */
		{";1 ",       3},
		{NULL,        0}, /* 7 to tag */
		{";1",        2}
	};

	if (get_callid(msg, &callid) == -1 || callid.len == 0) {
		LM_ERR("can't get Call-Id field\n");
		return -1;
	}
	if (get_to_tag(msg, &to_tag) == -1) {
		LM_ERR("can't get To tag\n");
		return -1;
	}
	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
		LM_ERR("can't get From tag\n");
		return -1;
	}
	STR2IOVEC(callid, v[3]);
	node = select_rtpp_node(callid, 1);
	if (!node) {
		LM_ERR("no available proxies\n");
		return -1;
	}
	if (node->rn_ptl_supported == 0) {
		LM_ERR("required functionality is not "
				"supported by the version of the RTPproxy running on the selected "
				"node.  Please upgrade the RTPproxy and try again.\n");
		return -1;
	}
	set_rtp_inst_pvar(msg, &node->rn_url);
	nitems = 9;
	if (stream2uac == 0) {
		if (to_tag.len == 0)
			return -1;
		STR2IOVEC(to_tag, v[5]);
		STR2IOVEC(from_tag, v[7]);
	} else {
		STR2IOVEC(from_tag, v[5]);
		STR2IOVEC(to_tag, v[7]);
		if (to_tag.len <= 0)
			nitems -= 2;
	}
	send_rtpp_command(node, v, nitems);

	return 1;
}
예제 #4
0
파일: dlg.c 프로젝트: AndreyRybkin/kamailio
/*
 * Extract all information from a request 
 * and update a dialog structure
 */
static inline int request2dlg(struct sip_msg* _m, dlg_t* _d)
{
	str contact, rtag, callid;

	if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
		LOG(L_ERR, "request2dlg(): Error while parsing headers");
		return -1;
	}

	if (get_contact_uri(_m, &contact) < 0) return -2;
	if (contact.len) {
		if (_d->rem_target.s) shm_free(_d->rem_target.s);
		if (_d->dst_uri.s) {
			shm_free(_d->dst_uri.s);
			_d->dst_uri.s = 0;
			_d->dst_uri.len = 0;
		}
		if (str_duplicate(&_d->rem_target, &contact) < 0) return -3;
	}
	
	if (get_from_tag(_m, &rtag) < 0) goto err1;
	if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1;

	if (get_callid(_m, &callid) < 0) goto err2;
	if (callid.len && str_duplicate(&_d->id.call_id, &callid) < 0) goto err2;

	if (get_cseq_value(_m, &_d->rem_seq.value) < 0) goto err3;
	_d->rem_seq.is_set = 1;

	if (get_dlg_uri(_m->from, &_d->rem_uri) < 0) goto err3;
	if (get_dlg_uri(_m->to, &_d->loc_uri) < 0) goto err4;

	if (get_route_set(_m, &_d->route_set, NORMAL_ORDER) < 0) goto err5;	

	return 0;
 err5:
	if (_d->loc_uri.s) shm_free(_d->loc_uri.s);
	_d->loc_uri.s = 0;
	_d->loc_uri.len = 0;
 err4:
	if (_d->rem_uri.s) shm_free(_d->rem_uri.s);
	_d->rem_uri.s = 0;
	_d->rem_uri.len = 0;
 err3:
	if (_d->id.call_id.s) shm_free(_d->id.call_id.s);
	_d->id.call_id.s = 0;
	_d->id.call_id.len = 0;
 err2:
	if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s);
	_d->id.rem_tag.s = 0;
	_d->id.rem_tag.len = 0;
 err1:
	if (_d->rem_target.s) shm_free(_d->rem_target.s);
	_d->rem_target.s = 0;
	_d->rem_target.len = 0;
	return -4;
}
예제 #5
0
static int
ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
{
	struct ip_vs_iphdr iph;
	unsigned int dataoff, datalen, matchoff, matchlen;
	const char *dptr;
	int retc;

	retc = ip_vs_fill_iph_skb(p->af, skb, false, &iph);

	/* Only useful with UDP */
	if (!retc || iph.protocol != IPPROTO_UDP)
		return -EINVAL;
	/* todo: IPv6 fragments:
	 *       I think this only should be done for the first fragment. /HS
	 */
	dataoff = iph.len + sizeof(struct udphdr);

	if (dataoff >= skb->len)
		return -EINVAL;
	retc = skb_linearize(skb);
	if (retc < 0)
		return retc;
	dptr = skb->data + dataoff;
	datalen = skb->len - dataoff;

	if (get_callid(dptr, 0, datalen, &matchoff, &matchlen))
		return -EINVAL;

	/* N.B: pe_data is only set on success,
	 * this allows fallback to the default persistence logic on failure
	 */
	p->pe_data = kmemdup(dptr + matchoff, matchlen, GFP_ATOMIC);
	if (!p->pe_data)
		return -ENOMEM;

	p->pe_data_len = matchlen;

	return 0;
}
예제 #6
0
static int
ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
{
	struct ip_vs_iphdr iph;
	unsigned int dataoff, datalen, matchoff, matchlen;
	const char *dptr;
	int retc;

	ip_vs_fill_iphdr(p->af, skb_network_header(skb), &iph);

	/* Only useful with UDP */
	if (iph.protocol != IPPROTO_UDP)
		return -EINVAL;

	/* No Data ? */
	dataoff = iph.len + sizeof(struct udphdr);
	if (dataoff >= skb->len)
		return -EINVAL;

	if ((retc=skb_linearize(skb)) < 0)
		return retc;
	dptr = skb->data + dataoff;
	datalen = skb->len - dataoff;

	if (get_callid(dptr, dataoff, datalen, &matchoff, &matchlen))
		return -EINVAL;

	/* N.B: pe_data is only set on success,
	 * this allows fallback to the default persistence logic on failure
	 */
	p->pe_data = kmemdup(dptr + matchoff, matchlen, GFP_ATOMIC);
	if (!p->pe_data)
		return -ENOMEM;

	p->pe_data_len = matchlen;

	return 0;
}
예제 #7
0
static int
rtpproxy_stream(struct sip_msg* msg, str *pname, int count, int stream2uac)
{
    int nitems;
    str callid, from_tag, to_tag;
    struct rtpp_node *node;
    char cbuf[16];
    struct iovec v[] = {
        {NULL,        0},
        {cbuf,        0}, /* 1 P<count> */
        {" ",         1},
        {NULL,        0}, /* 3 callid */
        {" ",         1},
        {NULL,        0}, /* 5 pname */
        {" session ", 9},
        {NULL,        0}, /* 7 from tag */
        {";1 ",       3},
        {NULL,        0}, /* 9 to tag */
        {";1",        2}
    };

    if (get_callid(msg, &callid) == -1 || callid.len == 0) {
        LM_ERR("can't get Call-Id field\n");
        return -1;
    }
    if (get_to_tag(msg, &to_tag) == -1) {
        LM_ERR("can't get To tag\n");
        return -1;
    }
    if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
        LM_ERR("can't get From tag\n");
        return -1;
    }
    v[1].iov_len = sprintf(cbuf, "P%d", count);
    STR2IOVEC(callid, v[3]);
    STR2IOVEC(*pname, v[5]);
    node = select_rtpp_node(callid, 1);
    if (!node) {
        LM_ERR("no available proxies\n");
        return -1;
    }
    if (node->rn_ptl_supported == 0) {
        LM_ERR("required functionality is not "
          "supported by the version of the RTPproxy running on the selected "
          "node.  Please upgrade the RTPproxy and try again.\n");
        return -1;
    }
    nitems = 11;
    if (stream2uac == 0) {
        if (to_tag.len == 0)
            return -1;
        STR2IOVEC(to_tag, v[7]);
        STR2IOVEC(from_tag, v[9]);
    } else {
        STR2IOVEC(from_tag, v[7]);
        STR2IOVEC(to_tag, v[9]);
        if (to_tag.len <= 0)
            nitems -= 2;
    }
    send_rtpp_command(node, v, nitems);

    return 1;
}
예제 #8
0
파일: sdp_util.c 프로젝트: asyn/openvims
static int
force_rtp_proxy2_f(struct sip_msg* msg, char* str1, char* str2)
{
	str body, body1, oldport, oldip, newport, newip;
	str callid, from_tag, to_tag, tmp;
	int create, port, len, asymmetric, flookup, argc, proxied, real;
	int oidx, pf=0, pf1, force, node_idx;
	char opts[16];
	char *cp, *cp1;
	char  *cpend, *next;
	char **ap, *argv[10];
	struct lump* anchor;
	struct rtpp_node *node;
	struct iovec v[14] = {
		{NULL, 0},	/* command */
		{NULL, 0},	/* options */
		{" ", 1},	/* separator */
		{NULL, 0},	/* callid */
		{" ", 1},	/* separator */
		{NULL, 7},	/* newip */
		{" ", 1},	/* separator */
		{NULL, 1},	/* oldport */
		{" ", 1},	/* separator */
		{NULL, 0},	/* from_tag */
		{";", 1},	/* separator */
		{NULL, 0},	/* medianum */
		{" ", 1},	/* separator */
		{NULL, 0}	/* to_tag */
	};
	char *v1p, *v2p, *c1p, *c2p, *m1p, *m2p, *bodylimit;
	char medianum_buf[20];
	int medianum, media_multi;
	str medianum_str, tmpstr1;
	int c1p_altered;

	v[1].iov_base=opts;
	asymmetric = flookup = force = real = 0;
	oidx = 1;
	node_idx = -1;
	for (cp = str1; *cp != '\0'; cp++) {
		switch (*cp) {
		case ' ':
		case '\t':
			break;

		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;

		case 'n':
		case 'N':
			cp++;
			for (len = 0; isdigit(cp[len]); len++)
				continue;
			if (len == 0) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: non-negative integer"
				    "should follow N option\n");
				return -1;
			}
			node_idx = strtoul(cp, NULL, 10);
			cp += len - 1;
			break;

		default:
			LOG(L_ERR, "ERROR: force_rtp_proxy2: unknown option `%c'\n", *cp);
			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;
	/*
	 * Parsing of SDP body.
	 * It can contain a few session descriptions (each starts with
	 * v-line), and each session may contain a few media descriptions
	 * (each starts with m-line).
	 * We have to change ports in m-lines, and also change IP addresses in
	 * c-lines which can be placed either in session header (fallback for
	 * all medias) or media description.
	 * Ports should be allocated for any media. IPs all should be changed
	 * to the same value (RTP proxy IP), so we can change all c-lines
	 * unconditionally.
	 */
	bodylimit = body.s + body.len;
	v1p = find_sdp_line(body.s, bodylimit, 'v');
	if (v1p == NULL) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: no sessions in SDP\n");
		return -1;
	}
	v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
	media_multi = (v2p != bodylimit);
	v2p = v1p;
	medianum = 0;
	for(;;) {
		/* Per-session iteration. */
		v1p = v2p;
		if (v1p == NULL || v1p >= bodylimit)
			break; /* No sessions left */
		v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
		/* v2p is text limit for session parsing. */
		m1p = find_sdp_line(v1p, v2p, 'm');
		/* Have this session media description? */
		if (m1p == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: no m= in session\n");
			return -1;
		}
		/*
		 * Find c1p only between session begin and first media.
		 * c1p will give common c= for all medias.
		 */
		c1p = find_sdp_line(v1p, m1p, 'c');
		c1p_altered = 0;
		/* Have session. Iterate media descriptions in session */
		m2p = m1p;
		for (;;) {
			m1p = m2p;
			if (m1p == NULL || m1p >= v2p)
				break;
			m2p = find_next_sdp_line(m1p, v2p, 'm', v2p);
			/* c2p will point to per-media "c=" */
			c2p = find_sdp_line(m1p, m2p, 'c');
			/* Extract address and port */
			tmpstr1.s = c2p ? c2p : c1p;
			if (tmpstr1.s == NULL) {
				/* No "c=" */
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " find media IP in the message\n");
				return -1;
			}
			tmpstr1.len = v2p - tmpstr1.s; /* limit is session limit text */
			if (extract_mediaip(&tmpstr1, &oldip, &pf) == -1) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " extract media IP from the message\n");
				return -1;
			}
			tmpstr1.s = m1p;
			tmpstr1.len = m2p - m1p;
			if (extract_mediaport(&tmpstr1, &oldport) == -1) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " extract media port from the message\n");
				return -1;
			}
			++medianum;
			if (asymmetric != 0 || real != 0) {
				newip = oldip;
			} else {
				newip.s = ip_addr2a(&msg->rcv.src_ip);
				newip.len = strlen(newip.s);
			}
			/* XXX must compare address families in all addresses */
			if (pf == AF_INET6) {
				opts[oidx] = '6';
				oidx++;
			}
			snprintf(medianum_buf, sizeof medianum_buf, "%d", medianum);
			medianum_str.s = medianum_buf;
			medianum_str.len = strlen(medianum_buf);
			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]);
			if (1 || media_multi) /* XXX netch: can't choose now*/
			{
				STR2IOVEC(medianum_str, v[11]);
			} else {
				v[10].iov_len = v[11].iov_len = 0;
			}
			STR2IOVEC(to_tag, v[13]);
			do {
				node = select_rtpp_node(callid, 1, node_idx);
				if (!node) {
					LOG(L_ERR, "ERROR: force_rtp_proxy2: no available proxies\n");
					return -1;
				}
				cp = send_rtpp_command(node, v, (to_tag.len > 0) ? 14 : 12);
			} while (cp == NULL);
			/* Parse proxy reply to <argc,argv> */
			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) {
				LOG(L_ERR, "force_rtp_proxy2: no reply from rtp proxy\n");
				return -1;
			}
			port = atoi(argv[0]);
			if (port <= 0 || port > 65535) {
				LOG(L_ERR, "force_rtp_proxy2: incorrect port in reply from rtp proxy\n");
				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 */
			/* Alter port. */
			body1.s = m1p;
			body1.len = bodylimit - body1.s;
			if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1)
				return -1;
			/*
			 * Alter IP. Don't alter IP common for the session
			 * more than once.
			 */
			if (c2p != NULL || !c1p_altered) {
				body1.s = c2p ? c2p : c1p;
				body1.len = bodylimit - body1.s;
				if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0) == -1)
					return -1;
				if (!c2p)
					c1p_altered = 1;
			}
		} /* Iterate medias in session */
	} /* Iterate sessions */

	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;
}