Example #1
0
/**
 * Compare media line protocols
 *
 * @param m      SDP Media line
 * @param proto  Transport protocol
 * @param update Update media protocol if match is found in alternate set
 *
 * @return True if matching, False if not
 */
bool sdp_media_proto_cmp(struct sdp_media *m, const struct pl *proto,
			 bool update)
{
	unsigned i;

	if (!m || !proto)
		return false;

	if (!pl_strcmp(proto, m->proto))
		return true;

	for (i=0; i<ARRAY_SIZE(m->protov); i++) {

		if (!m->protov[i] || pl_strcmp(proto, m->protov[i]))
			continue;

		if (update) {
			mem_deref(m->proto);
			m->proto = mem_ref(m->protov[i]);
		}

		return true;
	}

	return false;
}
Example #2
0
static int media_decode(struct sdp_media **mp, struct sdp_session *sess,
			bool offer, const struct pl *pl)
{
	struct pl name, port, proto, fmtv, fmt;
	struct sdp_media *m;
	int err;

	if (re_regex(pl->p, pl->l, "[a-z]+ [^ ]+ [^ ]+[^]*",
		     &name, &port, &proto, &fmtv))
		return EBADMSG;

	m = list_ledata(*mp ? (*mp)->le.next : sess->medial.head);
	if (!m) {
		if (!offer)
			return EPROTO;

		m = sdp_media_find(sess, &name, &proto);
		if (!m) {
			err = sdp_media_radd(&m, sess, &name, &proto);
			if (err)
				return err;
		}
		else {
			list_unlink(&m->le);
			list_append(&sess->medial, &m->le, m);
		}
	}
	else {
		if (pl_strcmp(&name, m->name))
			return offer ? ENOTSUP : EPROTO;

		if (pl_strcmp(&proto, m->proto))
			return ENOTSUP;
	}

	while (!re_regex(fmtv.p, fmtv.l, " [^ ]+", &fmt)) {

		pl_advance(&fmtv, fmt.p + fmt.l - fmtv.p);

		err = sdp_format_radd(m, &fmt);
		if (err)
			return err;
	}

	m->raddr = sess->raddr;
	sa_set_port(&m->raddr, pl_u32(&port));

	m->rdir = sess->rdir;

	*mp = m;

	return 0;
}
Example #3
0
static bool cmp_handler(struct le *le, void *arg)
{
	struct sip_ctrans *ct = le->data;
	const struct sip_msg *msg = arg;

	if (pl_strcmp(&msg->via.branch, ct->branch))
		return false;

	if (pl_strcmp(&msg->cseq.met, ct->met))
		return false;

	return true;
}
Example #4
0
/**
 * Compare a half SIP Dialog against a SIP Message
 *
 * @param dlg SIP Dialog
 * @param msg SIP Message
 *
 * @return True if match, False if no match
 */
bool sip_dialog_cmp_half(const struct sip_dialog *dlg,
			 const struct sip_msg *msg)
{
	if (!dlg || !msg)
		return false;

	if (pl_strcmp(&msg->callid, dlg->callid))
		return false;

	if (pl_strcmp(msg->req ? &msg->to.tag : &msg->from.tag, dlg->ltag))
		return false;

	return true;
}
Example #5
0
static bool sdp_attr_handler(const char *name, const char *value, void *arg)
{
	struct menc_st *st = arg;
	struct crypto c;
	(void)name;

	if (sdes_decode_crypto(&c, value))
		return false;

	if (0 != pl_strcmp(&c.key_method, "inline"))
		return false;

	if (!cryptosuite_issupported(&c.suite))
		return false;

	st->crypto_suite = mem_deref(st->crypto_suite);
	pl_strdup(&st->crypto_suite, &c.suite);

	if (start_crypto(st, &c.key_info))
		return false;

	sdp_enc(st, st->sdpm, c.tag, st->crypto_suite);

	return true;
}
Example #6
0
static bool contact_handler(const struct sip_hdr *hdr,
			    const struct sip_msg *msg, void *arg)
{
	struct sipreg *reg = arg;
	struct sip_addr c;
	struct pl pval;
	char uri[256];

	if (sip_addr_decode(&c, &hdr->val))
		return false;

	if (re_snprintf(uri, sizeof(uri), "sip:%s@%J%s", reg->cuser,
			&reg->laddr, sip_transp_param(reg->tp)) < 0)
		return false;

	if (pl_strcmp(&c.auri, uri))
		return false;

	if (!sip_param_decode(&c.params, "expires", &pval)) {
	        reg->wait = pl_u32(&pval);
	}
	else if (pl_isset(&msg->expires))
	        reg->wait = pl_u32(&msg->expires);
	else
	        reg->wait = DEFAULT_EXPIRES;

	return true;
}
Example #7
0
static void sip_recv(struct sip *sip, const struct sip_msg *msg)
{
	struct le *le = sip->lsnrl.head;

	while (le) {
		struct sip_lsnr *lsnr = le->data;

		le = le->next;

		if (msg->req != lsnr->req)
			continue;

		if (lsnr->msgh(msg, lsnr->arg))
			return;
	}

	if (msg->req) {
		(void)re_fprintf(stderr, "unhandeled request from %J: %r %r\n",
				 &msg->src, &msg->met, &msg->ruri);

		if (!pl_strcmp(&msg->met, "CANCEL"))
			(void)sip_reply(sip, msg,
					481, "Transaction Does Not Exist");
		else
			(void)sip_reply(sip, msg,
					501, "Not Implemented");
	}
	else {
		(void)re_fprintf(stderr, "unhandeled response from %J:"
				 " %u %r (%r)\n", &msg->src,
				 msg->scode, &msg->reason, &msg->cseq.met);
	}
}
Example #8
0
static bool request_handler(const struct sip_msg *msg, void *arg)
{
	struct message *message = arg;
	struct ua *ua;
	struct le *le = message->lsnrl.head;
	bool hdld = false;

	if (pl_strcmp(&msg->met, "MESSAGE"))
		return false;

	ua = uag_find(&msg->uri.user);
	if (!ua) {
		(void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found");
		return true;
	}

	while (le) {
		struct message_lsnr *lsnr = le->data;

		le = le->next;

		handle_message(lsnr, ua, msg);

		hdld = true;
	}

	return hdld;
}
Example #9
0
/**
 * Find an SDP Media line from name and transport protocol
 *
 * @param sess  SDP Session
 * @param name  Media name
 * @param proto Transport protocol
 * @param update_proto Update media transport protocol
 *
 * @return Matching media line if found, NULL if not found
 */
struct sdp_media *sdp_media_find(const struct sdp_session *sess,
				 const struct pl *name,
				 const struct pl *proto,
				 bool update_proto)
{
	struct le *le;

	if (!sess || !name || !proto)
		return NULL;

	for (le=sess->lmedial.head; le; le=le->next) {

		struct sdp_media *m = le->data;

		if (pl_strcmp(name, m->name))
			continue;

		if (!sdp_media_proto_cmp(m, proto, update_proto))
			continue;

		return m;
	}

	return NULL;
}
Example #10
0
void http_init(struct httpc *app, struct request **rpp, char *str_uri)
{
    int ok;
    struct request *request;
    struct pl pl_uri;
    struct url url;

    *rpp = NULL;

    pl_uri.p = NULL;
    str_dup((char**)&pl_uri.p, str_uri);
    pl_uri.l = strlen(str_uri);

    ok = url_decode(&url, &pl_uri);

    if(ok!=0)
        goto err_uri;

    request = mem_zalloc(sizeof(*request), destructor);
    ok = hash_alloc(&request->hdrht, HDR_HASH_SIZE);
    request->err_h = dummy_err;
    request->done_h = http_done;
    request->post = NULL;
    request->form = 0;
    request->www_auth.p = NULL;
    request->www_auth.l = 0;
    request->auth = NULL;

    request->retry = 0;

    pl_strdup(&request->host, &url.host);
    pl_strdup(&request->path, &url.path);
    request->secure = !pl_strcmp(&url.scheme, "https");
    memcpy(&request->meth, "GET", 4);
    request->meth[4] = 0;

    if(url.port)
	request->port = url.port;
    else
        request->port = request->secure ? 443 : 80;

    DEBUG_INFO("secure: %d port %d\n", request->secure, request->port);
    sa_init(&request->dest, AF_INET);
    ok = sa_set_str(&request->dest, request->host, request->port);

    request->state = ok ? START : RESOLVED;

    request->app = app;
    *rpp = request;

err_uri:
    if(pl_uri.p)
        mem_deref((void*)pl_uri.p);

    return;
}
Example #11
0
/**
 * Decode a pointer-length string into a SIP Via header
 *
 * @param via SIP Via header
 * @param pl  Pointer-length string
 *
 * @return 0 for success, otherwise errorcode
 */
int sip_via_decode(struct sip_via *via, const struct pl *pl)
{
    struct pl transp, host, port;
    int err;

    if (!via || !pl)
        return EINVAL;

    err = re_regex(pl->p, pl->l,
                   "SIP[  \t\r\n]*/[ \t\r\n]*2.0[ \t\r\n]*/[ \t\r\n]*"
                   "[A-Z]+[ \t\r\n]*[^; \t\r\n]+[ \t\r\n]*[^]*",
                   NULL, NULL, NULL, NULL, &transp,
                   NULL, &via->sentby, NULL, &via->params);
    if (err)
        return err;

    if (!pl_strcmp(&transp, "TCP"))
        via->tp = SIP_TRANSP_TCP;
    else if (!pl_strcmp(&transp, "TLS"))
        via->tp = SIP_TRANSP_TLS;
    else if (!pl_strcmp(&transp, "UDP"))
        via->tp = SIP_TRANSP_UDP;
    else
        via->tp = SIP_TRANSP_NONE;

    err = decode_hostport(&via->sentby, &host, &port);
    if (err)
        return err;

    sa_init(&via->addr, AF_INET);

    (void)sa_set(&via->addr, &host, 0);

    if (pl_isset(&port))
        sa_set_port(&via->addr, pl_u32(&port));

    via->val = *pl;

    return msg_param_decode(&via->params, "branch", &via->branch);
}
Example #12
0
static bool response_handler(const struct sip_msg *msg, void *arg)
{
	struct sipsess_sock *sock = arg;

	if (pl_strcmp(&msg->cseq.met, "INVITE"))
		return false;

	if (msg->scode < 200 || msg->scode > 299)
		return false;

	(void)sipsess_ack_again(sock, msg);

	return true;
}
Example #13
0
static bool amr_octet_align(const char *fmtp)
{
	struct pl pl, oa;

	if (!fmtp)
		return false;

	pl_set_str(&pl, fmtp);

	if (fmt_param_get(&pl, "octet-align", &oa))
		return 0 == pl_strcmp(&oa, "1");

	return false;
}
Example #14
0
static bool request_handler(const struct sip_msg *msg, void *arg)
{
	struct sipsess_sock *sock = arg;

	if (!pl_strcmp(&msg->met, "INVITE")) {

		if (pl_isset(&msg->to.tag))
			reinvite_handler(sock, msg);
		else
			invite_handler(sock, msg);

		return true;
	}
	else if (!pl_strcmp(&msg->met, "ACK")) {
		ack_handler(sock, msg);
		return true;
	}
	else if (!pl_strcmp(&msg->met, "BYE")) {
		bye_handler(sock, msg);
		return true;
	}
	else if (!pl_strcmp(&msg->met, "INFO")) {
		info_handler(sock, msg);
		return true;
	}
	else if (!pl_strcmp(&msg->met, "REFER")) {

		if (!pl_isset(&msg->to.tag))
			return false;

		refer_handler(sock, msg);
		return true;
	}

	return false;
}
Example #15
0
static int bandwidth_decode(int32_t *bwv, const struct pl *pl)
{
	struct pl type, bw;

	if (re_regex(pl->p, pl->l, "[^:]+:[0-9]+", &type, &bw))
		return EBADMSG;

	if (!pl_strcmp(&type, "CT"))
		bwv[SDP_BANDWIDTH_CT] = pl_u32(&bw);

	else if (!pl_strcmp(&type, "AS"))
		bwv[SDP_BANDWIDTH_AS] = pl_u32(&bw);

	else if (!pl_strcmp(&type, "RS"))
		bwv[SDP_BANDWIDTH_RS] = pl_u32(&bw);

	else if (!pl_strcmp(&type, "RR"))
		bwv[SDP_BANDWIDTH_RR] = pl_u32(&bw);

	else if (!pl_strcmp(&type, "TIAS"))
		bwv[SDP_BANDWIDTH_TIAS] = pl_u32(&bw);

	return 0;
}
Example #16
0
static bool request_handler(const struct sip_msg *msg, void *arg)
{
	struct ua *ua;

	(void)arg;

	if (pl_strcmp(&msg->met, "MESSAGE"))
		return false;

	ua = uag_find(&msg->uri.user);
	if (!ua) {
		(void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found");
		return true;
	}

	handle_message(ua, msg);

	return true;
}
Example #17
0
struct sdp_format *sdp_format_find(const struct list *lst, const struct pl *id)
{
	struct le *le;

	if (!lst || !id)
		return NULL;

	for (le=lst->head; le; le=le->next) {

		struct sdp_format *fmt = le->data;

		if (pl_strcmp(id, fmt->id))
			continue;

		return fmt;
	}

	return NULL;
}
Example #18
0
void http_request_h(struct http_conn *conn, const struct http_msg *msg, void *arg)
{
    int err;
    enum app_cmd cmd;
    const struct http_hdr * expect_hdr;
    struct mbuf *mb = msg->mb;
    uint8_t *ret_buf;
    size_t ret_len;

    if(pl_strcmp(&msg->met, "POST")) {
        http_creply(conn, 405, "Method not allowed", "text/plain", "EMET");
        return;
    }

    expect_hdr = http_msg_hdr(msg, HTTP_HDR_EXPECT);
    if(expect_hdr != NULL && version_cmp(version, &expect_hdr->val) < 0) {
        http_creply(conn, 417, "Expectation Failed", "text/plain", "%s", version);
        return;
    }

    cmd = (enum app_cmd)(hash_joaat_ci(msg->path.p, msg->path.l) & 0xfff);
    err = app_handle(cmd, mbuf_buf(mb), mbuf_get_left(mb), &ret_buf, &ret_len);
    if(err < 0) {
        http_creply(conn, 500, "Internal Server Error", "text/plain", "EINT");
        return;
    }

    if(err > 200) {
        http_creply(conn, err, "Error", "text/plain", "NO", 2);
        return;
    }

    if(err == 0) {
        http_creply(conn, 200, "OK", "text/plain; charset=utf-8", "%b", ret_buf, ret_len);
    } else {
        http_creply(conn, 403, "Forbidden", "text/plain", "%b", ret_buf, ret_len);
    }

    free(ret_buf);
}
Example #19
0
static void udp_recv(const struct sa *src, struct mbuf *mb, void *arg)
{
	struct sip_server *srv = arg;
	struct sip_msg *msg;
	int err;

#if 0
	re_printf("sip: %zu bytes from %J\n", mbuf_get_left(mb), src);
	re_printf("%b\n", mb->buf, mb->end);
#endif

	err = sip_msg_decode(&msg, mb);
	if (err) {
		warning("selftest: sip_msg_decode: %m\n", err);
		return;
	}

	if (0 == pl_strcmp(&msg->met, "REGISTER"))
		srv->got_register_req = true;

	msg->sock = mem_ref(srv->us);
	msg->src  = *src;
	msg->dst  = srv->laddr;
	msg->tp   = SIP_TRANSP_UDP;

	if (srv->terminate)
		err = sip_reply(srv->sip, msg, 503, "Server Error");
	else
		err = sip_reply(srv->sip, msg, 200, "OK");
	if (err) {
		warning("selftest: could not reply: %m\n", err);
	}

	mem_deref(msg);

	if (srv->terminate)
		re_cancel();
}
Example #20
0
static int attr_decode(struct sdp_session *sess, struct sdp_media *m,
		       enum sdp_dir *dir, const struct pl *pl)
{
	struct pl name, val;
	int err = 0;

	if (re_regex(pl->p, pl->l, "[^:]+:[^]+", &name, &val)) {
		name = *pl;
		val  = pl_null;
	}

	if (!pl_strcmp(&name, "fmtp"))
		err = attr_decode_fmtp(m, &val);

	else if (!pl_strcmp(&name, "inactive"))
		*dir = SDP_INACTIVE;

	else if (!pl_strcmp(&name, "recvonly"))
		*dir = SDP_SENDONLY;

	else if (!pl_strcmp(&name, "rtcp"))
		err = attr_decode_rtcp(m, &val);

	else if (!pl_strcmp(&name, "rtpmap"))
		err = attr_decode_rtpmap(m, &val);

	else if (!pl_strcmp(&name, "sendonly"))
		*dir = SDP_RECVONLY;

	else if (!pl_strcmp(&name, "sendrecv"))
		*dir = SDP_SENDRECV;

	else
		err = sdp_attr_add(m ? &m->rattrl : &sess->rattrl,
				   &name, &val);

	return err;
}
Example #21
0
static bool find_handler(struct le *le, void *arg)
{
	struct contact *c = le->data;

	return 0 == pl_strcmp(&c->addr.auri, arg);
}
Example #22
0
static void notify_handler(struct sip *sip, const struct sip_msg *msg,
			   void *arg)
{
	enum presence_status status = PRESENCE_CLOSED;
	struct presence *pres = arg;
	const struct sip_hdr *type_hdr, *length_hdr;
	struct pl pl;

	pres->failc = 0;

	type_hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_TYPE);

	if (!type_hdr) {

		length_hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_LENGTH);
		if (0 == pl_strcmp(&length_hdr->val, "0")) {

			status = PRESENCE_UNKNOWN;
			goto done;
		}
	}

	if (!type_hdr ||
	    0 != pl_strcasecmp(&type_hdr->val, "application/pidf+xml")) {

		if (type_hdr)
			warning("presence: unsupported content-type: '%r'\n",
				&type_hdr->val);

		sip_treplyf(NULL, NULL, sip, msg, false,
			    415, "Unsupported Media Type",
			    "Accept: application/pidf+xml\r\n"
			    "Content-Length: 0\r\n"
			    "\r\n");
		return;
	}

	if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb),
		      "<basic>[^<]+</basic>", &pl)) {
		if (!pl_strcasecmp(&pl, "open"))
			status = PRESENCE_OPEN;
	}

	if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb),
		      "<rpid:away/>")) {

		status = PRESENCE_CLOSED;
	}
	else if (!re_regex((const char *)mbuf_buf(msg->mb),
			   mbuf_get_left(msg->mb),
			   "<rpid:busy/>")) {

		status = PRESENCE_BUSY;
	}
	else if (!re_regex((const char *)mbuf_buf(msg->mb),
			   mbuf_get_left(msg->mb),
			   "<rpid:on-the-phone/>")) {

		status = PRESENCE_BUSY;
	}

done:
	(void)sip_treply(NULL, sip, msg, 200, "OK");

	contact_set_presence(pres->contact, status);
}
Example #23
0
int sipevent_accept(struct sipnot **notp, struct sipevent_sock *sock,
		    const struct sip_msg *msg, struct sip_dialog *dlg,
		    const struct sipevent_event *event,
		    uint16_t scode, const char *reason, uint32_t expires_min,
		    uint32_t expires_dfl, uint32_t expires_max,
		    const char *cuser, const char *ctype,
		    sip_auth_h *authh, void *aarg, bool aref,
		    sipnot_close_h *closeh, void *arg, const char *fmt, ...)
{
	struct sipnot *not;
	uint32_t expires;
	int err;

	if (!notp || !sock || !msg || !scode || !reason || !expires_dfl ||
	    !expires_max || !cuser || !ctype || expires_dfl < expires_min)
		return EINVAL;

	not = mem_zalloc(sizeof(*not), destructor);
	if (!not)
		return ENOMEM;

	if (!pl_strcmp(&msg->met, "REFER")) {

		err = str_dup(&not->event, "refer");
		if (err)
			goto out;

		err = re_sdprintf(&not->id, "%u", msg->cseq.num);
		if (err)
			goto out;
	}
	else {
		if (!event) {
			err = EINVAL;
			goto out;
		}

		err = pl_strdup(&not->event, &event->event);
		if (err)
			goto out;

		if (pl_isset(&event->id)) {

			err = pl_strdup(&not->id, &event->id);
			if (err)
				goto out;
		}
	}

	if (dlg) {
		not->dlg = mem_ref(dlg);
	}
	else {
		err = sip_dialog_accept(&not->dlg, msg);
		if (err)
			goto out;
	}

	hash_append(sock->ht_not,
		    hash_joaat_str(sip_dialog_callid(not->dlg)),
		    &not->he, not);

	err = sip_auth_alloc(&not->auth, authh, aarg, aref);
	if (err)
		goto out;

	err = str_dup(&not->cuser, cuser);
	if (err)
		goto out;

	err = str_dup(&not->ctype, ctype);
	if (err)
		goto out;

	if (fmt) {
		va_list ap;

		va_start(ap, fmt);
		err = re_vsdprintf(&not->hdrs, fmt, ap);
		va_end(ap);
		if (err)
			goto out;
	}

	not->expires_min = expires_min;
	not->expires_dfl = expires_dfl;
	not->expires_max = expires_max;
	not->substate = SIPEVENT_PENDING;
	not->sock   = mem_ref(sock);
	not->sip    = mem_ref(sock->sip);
	not->closeh = closeh ? closeh : internal_close_handler;
	not->arg    = arg;

	if (pl_isset(&msg->expires))
		expires = pl_u32(&msg->expires);
	else
		expires = not->expires_dfl;

	sipnot_refresh(not, expires);

	err = sipnot_reply(not, msg, scode, reason);
	if (err)
		goto out;

	not->subscribed = true;

 out:
	if (err)
		mem_deref(not);
	else
		*notp = not;

	return err;
}
int trice_stund_recv(struct trice *icem, struct ice_lcand *lcand,
		    void *sock, const struct sa *src,
		    struct stun_msg *req, size_t presz)
{
	struct stun_attr *attr;
	struct pl lu, ru;
	bool remote_controlling;
	uint64_t tiebrk = 0;
	uint32_t prio_prflx;
	bool use_cand = false;
	int err;

	/* RFC 5389: Fingerprint errors are silently discarded */
	err = stun_msg_chk_fingerprint(req);
	if (err)
		return err;

	err = stun_msg_chk_mi(req, (uint8_t *)icem->lpwd, strlen(icem->lpwd));
	if (err) {
		DEBUG_WARNING("message-integrity failed (src=%J)\n", src);
		if (err == EBADMSG)
			goto unauth;
		else
			goto badmsg;
	}

	attr = stun_msg_attr(req, STUN_ATTR_USERNAME);
	if (!attr)
		goto badmsg;

	err = re_regex(attr->v.username, strlen(attr->v.username),
		       "[^:]+:[^]+", &lu, &ru);
	if (err) {
		DEBUG_WARNING("could not parse USERNAME attribute (%s)\n",
			      attr->v.username);
		goto unauth;
	}
	if (pl_strcmp(&lu, icem->lufrag)) {
		DEBUG_WARNING("local ufrag err (expected %s, actual %r)\n",
			      icem->lufrag, &lu);
		goto unauth;
	}
	if (str_isset(icem->rufrag) && pl_strcmp(&ru, icem->rufrag)) {
		DEBUG_WARNING("remote ufrag err (expected %s, actual %r)\n",
			      icem->rufrag, &ru);
		goto unauth;
	}

	attr = stun_msg_attr(req, STUN_ATTR_CONTROLLED);
	if (attr) {
		remote_controlling = false;
		tiebrk = attr->v.uint64;
	}

	attr = stun_msg_attr(req, STUN_ATTR_CONTROLLING);
	if (attr) {
		remote_controlling = true;
		tiebrk = attr->v.uint64;
	}

	if (remote_controlling == icem->controlling) {
		if (icem->tiebrk >= tiebrk)
			trice_switch_local_role(icem);
		else
			goto conflict;
	}

	attr = stun_msg_attr(req, STUN_ATTR_PRIORITY);
	if (attr)
		prio_prflx = attr->v.uint32;
	else
		goto badmsg;

	attr = stun_msg_attr(req, STUN_ATTR_USE_CAND);
	if (attr)
		use_cand = true;

	err = handle_stun_full(icem, lcand, sock, src, prio_prflx, use_cand);

	if (err)
		goto badmsg;

	trice_tracef(icem, 32,
		     "[%u] STUNSRV: Tx success respons [%H ---> %J]\n",
		     lcand->attr.compid,
		     trice_cand_print, lcand, src);

	return stun_reply(lcand->attr.proto, sock, src, presz, req,
			  (uint8_t *)icem->lpwd, strlen(icem->lpwd), true, 2,
			  STUN_ATTR_XOR_MAPPED_ADDR, src,
			  STUN_ATTR_SOFTWARE, icem->sw ? icem->sw : sw);


 badmsg:
	return stunsrv_ereply(icem, lcand, sock, src, presz, req,
			      400, "Bad Request");

 unauth:
	return stunsrv_ereply(icem, lcand, sock, src, presz, req,
			      401, "Unauthorized");

 conflict:
	return stunsrv_ereply(icem, lcand, sock, src, presz, req,
			      487, "Role Conflict");
}
Example #25
0
int location_update(struct list *locl, const struct sip_msg *msg,
                    const struct sip_addr *contact, uint32_t expires)
{
    struct location *loc, *loc_new = NULL;
    struct loctmp *tmp;
    struct pl pl;
    int err;

    if (!locl || !msg || !contact)
        return EINVAL;

    loc = list_ledata(list_apply(locl, true, cmp_handler,
                                 (void *)&contact->uri));
    if (!loc) {
        if (expires == 0)
            return 0;

        loc = loc_new = mem_zalloc(sizeof(*loc), destructor_location);
        if (!loc)
            return ENOMEM;

        list_append(locl, &loc->le, loc);
    }
    else {
        if (!pl_strcmp(&msg->callid, loc->callid) &&
                msg->cseq.num <= loc->cseq)
            return EPROTO;

        if (expires == 0) {
            loc->rm = true;
            return 0;
        }
    }

    tmp = mem_zalloc(sizeof(*tmp), destructor_loctmp);
    if (!tmp) {
        err = ENOMEM;
        goto out;
    }

    err = pl_strdup(&tmp->uri, &contact->auri);
    if (err)
        goto out;

    pl_set_str(&pl, tmp->uri);

    if (uri_decode(&tmp->duri, &pl)) {
        err = EBADMSG;
        goto out;
    }

    err = pl_strdup(&tmp->callid, &msg->callid);
    if (err)
        goto out;


    if (!msg_param_decode(&contact->params, "q", &pl))
        tmp->q = pl_float(&pl);
    else
        tmp->q = 1;

    tmp->cseq    = msg->cseq.num;
    tmp->expires = expires;
    tmp->src     = msg->src;

out:
    if (err) {
        mem_deref(loc_new);
        mem_deref(tmp);
    }
    else {
        mem_deref(loc->tmp);
        loc->tmp = tmp;
    }

    return err;
}
Example #26
0
static int version_decode(const struct pl *pl)
{
	return pl_strcmp(pl, "0") ? ENOSYS : 0;
}
Example #27
0
int icem_stund_recv(struct icem_comp *comp, const struct sa *src,
		    struct stun_msg *req, size_t presz)
{
	struct icem *icem = comp->icem;
	struct ice *ice = icem->ice;
	struct stun_attr *attr;
	struct pl lu, ru;
	enum role rrole = ROLE_UNKNOWN;
	uint64_t tiebrk = 0;
	uint32_t prio_prflx;
	bool use_cand = false;
	int err;

	/* RFC 5389: Fingerprint errors are silently discarded */
	err = stun_msg_chk_fingerprint(req);
	if (err)
		return err;

	err = stun_msg_chk_mi(req, (uint8_t *)ice->lpwd, strlen(ice->lpwd));
	if (err) {
		if (err == EBADMSG)
			goto unauth;
		else
			goto badmsg;
	}

	attr = stun_msg_attr(req, STUN_ATTR_USERNAME);
	if (!attr)
		goto badmsg;

	err = re_regex(attr->v.username, strlen(attr->v.username),
		       "[^:]+:[^]+", &lu, &ru);
	if (err) {
		DEBUG_WARNING("could not parse USERNAME attribute (%s)\n",
			      attr->v.username);
		goto unauth;
	}
	if (pl_strcmp(&lu, ice->lufrag))
		goto unauth;
	if (str_isset(icem->rufrag) && pl_strcmp(&ru, icem->rufrag))
		goto unauth;

	attr = stun_msg_attr(req, STUN_ATTR_CONTROLLED);
	if (attr) {
		rrole = ROLE_CONTROLLED;
		tiebrk = attr->v.uint64;
	}

	attr = stun_msg_attr(req, STUN_ATTR_CONTROLLING);
	if (attr) {
		rrole = ROLE_CONTROLLING;
		tiebrk = attr->v.uint64;
	}

	if (rrole == ice->lrole) {
		if (ice->tiebrk >= tiebrk)
			ice_switch_local_role(ice);
		else
			goto conflict;
	}

	attr = stun_msg_attr(req, STUN_ATTR_PRIORITY);
	if (attr)
		prio_prflx = attr->v.uint32;
	else
		goto badmsg;

	attr = stun_msg_attr(req, STUN_ATTR_USE_CAND);
	if (attr)
		use_cand = true;

	err = handle_stun(ice, icem, comp, src, prio_prflx,
			  use_cand, presz > 0);
	if (err)
		goto badmsg;

	return stun_reply(icem->proto, comp->sock, src, presz, req,
			  (uint8_t *)ice->lpwd, strlen(ice->lpwd), true, 2,
			  STUN_ATTR_XOR_MAPPED_ADDR, src,
			  STUN_ATTR_SOFTWARE, sw);

 badmsg:
	return stunsrv_ereply(comp, src, presz, req, 400, "Bad Request");

 unauth:
	return stunsrv_ereply(comp, src, presz, req, 401, "Unauthorized");

 conflict:
	return stunsrv_ereply(comp, src, presz, req, 487, "Role Conflict");
}
Example #28
0
File: msg.c Project: Issic47/libre
/**
 * Decode a SIP message
 *
 * @param msgp Pointer to allocated SIP Message
 * @param mb   Buffer containing SIP Message
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_msg_decode(struct sip_msg **msgp, struct mbuf *mb)
{
	struct pl x, y, z, e, name;
	const char *p, *v, *cv;
	struct sip_msg *msg;
	bool comsep, quote;
	enum sip_hdrid id = SIP_HDR_NONE;
	uint32_t ws, lf;
	size_t l;
	int err;

	if (!msgp || !mb)
		return EINVAL;

	p = (const char *)mbuf_buf(mb);
	l = mbuf_get_left(mb);

	if (re_regex(p, l, "[^ \t\r\n]+ [^ \t\r\n]+ [^\r\n]*[\r]*[\n]1",
		     &x, &y, &z, NULL, &e) || x.p != (char *)mbuf_buf(mb))
		return (l > STARTLINE_MAX) ? EBADMSG : ENODATA;

	msg = mem_zalloc(sizeof(*msg), destructor);
	if (!msg)
		return ENOMEM;

	err = hash_alloc(&msg->hdrht, HDR_HASH_SIZE);
	if (err)
		goto out;

	msg->tag = rand_u64();
	msg->mb  = mem_ref(mb);
	msg->req = (0 == pl_strcmp(&z, "SIP/2.0"));

	if (msg->req) {

		msg->met = x;
		msg->ruri = y;
		msg->ver = z;

		if (uri_decode(&msg->uri, &y)) {
			err = EBADMSG;
			goto out;
		}
	}
	else {
		msg->ver    = x;
		msg->scode  = pl_u32(&y);
		msg->reason = z;

		if (!msg->scode) {
			err = EBADMSG;
			goto out;
		}
	}

	l -= e.p + e.l - p;
	p = e.p + e.l;

	name.p = v = cv = NULL;
	name.l = ws = lf = 0;
	comsep = false;
	quote = false;

	for (; l > 0; p++, l--) {

		switch (*p) {

		case ' ':
		case '\t':
			lf = 0; /* folding */
			++ws;
			break;

		case '\r':
			++ws;
			break;

		case '\n':
			++ws;

			if (!lf++)
				break;

			++p; --l; /* eoh */

			/*@fallthrough@*/

		default:
			if (lf || (*p == ',' && comsep && !quote)) {

				if (!name.l) {
					err = EBADMSG;
					goto out;
				}

				err = hdr_add(msg, &name, id, cv ? cv : p,
					      cv ? p - cv - ws : 0,
					      true, cv == v && lf);
				if (err)
					goto out;

				if (!lf) { /* comma separated */
					cv = NULL;
					break;
				}

				if (cv != v) {
					err = hdr_add(msg, &name, id,
						      v ? v : p,
						      v ? p - v - ws : 0,
						      false, true);
					if (err)
						goto out;
				}

				if (lf > 1) { /* eoh */
					err = 0;
					goto out;
				}

				comsep = false;
				name.p = NULL;
				cv = v = NULL;
				lf = 0;
			}

			if (!name.p) {
				name.p = p;
				name.l = 0;
				ws = 0;
			}

			if (!name.l) {
				if (*p != ':') {
					ws = 0;
					break;
				}

				name.l = MAX((int)(p - name.p - ws), 0);
				if (!name.l) {
					err = EBADMSG;
					goto out;
				}

				id = hdr_hash(&name);
				comsep = hdr_comma_separated(id);
				break;
			}

			if (!cv) {
				quote = false;
				cv = p;
			}

			if (!v) {
				v = p;
			}

			if (*p == '"')
				quote = !quote;

			ws = 0;
			break;
		}
	}

	err = ENODATA;

 out:
	if (err)
		mem_deref(msg);
	else {
		*msgp = msg;
		mb->pos = mb->end - l;
	}

	return err;
}