Ejemplo n.º 1
0
Archivo: msg.c Proyecto: Issic47/libre
int sipevent_substate_decode(struct sipevent_substate *ss, const struct pl *pl)
{
	struct pl state, param;
	int err;

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

	err = re_regex(pl->p, pl->l, "[a-z]+[ \t\r\n]*[^]*",
		       &state, NULL, &ss->params);
	if (err)
		return EBADMSG;

	if (!pl_strcasecmp(&state, "active"))
		ss->state = SIPEVENT_ACTIVE;
	else if (!pl_strcasecmp(&state, "pending"))
		ss->state = SIPEVENT_PENDING;
	else if (!pl_strcasecmp(&state, "terminated"))
		ss->state = SIPEVENT_TERMINATED;
	else
		ss->state = -1;

	if (!msg_param_decode(&ss->params, "reason", &param)) {

		if (!pl_strcasecmp(&param, "deactivated"))
			ss->reason = SIPEVENT_DEACTIVATED;
		else if (!pl_strcasecmp(&param, "probation"))
			ss->reason = SIPEVENT_PROBATION;
		else if (!pl_strcasecmp(&param, "rejected"))
			ss->reason = SIPEVENT_REJECTED;
		else if (!pl_strcasecmp(&param, "timeout"))
			ss->reason = SIPEVENT_TIMEOUT;
		else if (!pl_strcasecmp(&param, "giveup"))
			ss->reason = SIPEVENT_GIVEUP;
		else if (!pl_strcasecmp(&param, "noresource"))
			ss->reason = SIPEVENT_NORESOURCE;
		else
			ss->reason = -1;
	}
	else {
		ss->reason = -1;
	}

	if (!msg_param_decode(&ss->params, "expires", &param))
		ss->expires = param;
	else
		ss->expires = pl_null;

	if (!msg_param_decode(&ss->params, "retry-after", &param))
		ss->retry_after = param;
	else
		ss->retry_after = pl_null;

	return 0;
}
Ejemplo n.º 2
0
/**
 * Find a User-Agent (UA) which has certain address parameter and/or value
 *
 * @param name  SIP Address parameter name
 * @param value SIP Address parameter value (optional)
 *
 * @return User-Agent (UA) if found, otherwise NULL
 */
struct ua *uag_find_param(const char *name, const char *value)
{
	struct le *le;

	for (le = uag.ual.head; le; le = le->next) {
		struct ua *ua = le->data;
		struct sip_addr *laddr = account_laddr(ua->acc);
		struct pl val;

		if (value) {

			if (0 == msg_param_decode(&laddr->params, name, &val)
			    &&
			    0 == pl_strcasecmp(&val, value)) {
				return ua;
			}
		}
		else {
			if (0 == msg_param_exists(&laddr->params, name, &val))
				return ua;
		}
	}

	return NULL;
}
Ejemplo n.º 3
0
/**
 * Add a contact
 *
 * @param contacts Contacts container
 * @param contactp Pointer to allocated contact (optional)
 * @param addr     Contact in SIP address format
 *
 * @return 0 if success, otherwise errorcode
 */
int contact_add(struct contacts *contacts,
		struct contact **contactp, const struct pl *addr)
{
	struct contact *c;
	struct pl pl;
	int err;

	if (!contacts)
		return EINVAL;

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

	err = pl_strdup(&c->buf, addr);
	if (err)
		goto out;

	pl_set_str(&pl, c->buf);

	err = sip_addr_decode(&c->addr, &pl);
	if (err) {
		warning("contact: decode error '%r'\n", addr);
		goto out;
	}

	if (0 == msg_param_decode(&c->addr.params, "access", &pl)) {

		if (0 == pl_strcasecmp(&pl, "block")) {
			c->access = ACCESS_BLOCK;
		}
		else if (0 == pl_strcasecmp(&pl, "allow")) {
			c->access = ACCESS_ALLOW;
		}
		else {
			warning("contact: unknown 'access=%r' for '%r'\n",
				&pl, addr);
			err = EINVAL;
			goto out;
		}
	}
	else
		c->access = ACCESS_UNKNOWN;

	c->status = PRESENCE_UNKNOWN;

	list_append(&contacts->cl, &c->le, c);
	hash_append(contacts->cht, hash_joaat_pl(&c->addr.auri), &c->he, c);

 out:
	if (err)
		mem_deref(c);
	else if (contactp)
		*contactp = c;

	return err;
}
Ejemplo n.º 4
0
Archivo: msg.c Proyecto: Issic47/libre
int sipevent_event_decode(struct sipevent_event *se, const struct pl *pl)
{
	struct pl param;
	int err;

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

	err = re_regex(pl->p, pl->l, "[^; \t\r\n]+[ \t\r\n]*[^]*",
		       &se->event, NULL, &se->params);
	if (err)
		return EBADMSG;

	if (!msg_param_decode(&se->params, "id", &param))
		se->id = param;
	else
		se->id = pl_null;

	return 0;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
int subscriber_init(void)
{
	struct le *le;
	int err = 0;

	for (le = list_head(contact_list()); le; le = le->next) {

		struct contact *c = le->data;
		struct sip_addr *addr = contact_addr(c);
		struct pl val;

		if (0 == msg_param_decode(&addr->params, "presence", &val) &&
		    0 == pl_strcasecmp(&val, "p2p")) {

			err |= presence_alloc(le->data);
		}
	}

	info("Subscribing to %u contacts\n", list_count(&presencel));

	return err;
}
Ejemplo n.º 7
0
/**
 * Send a SIP request
 *
 * @param reqp     Pointer to allocated SIP request object
 * @param sip      SIP Stack
 * @param stateful Stateful client transaction
 * @param met      SIP Method string
 * @param metl     Length of SIP Method string
 * @param uri      Request URI
 * @param uril     Length of Request URI string
 * @param route    Next hop route URI
 * @param mb       Buffer containing SIP request
 * @param sendh    Send handler
 * @param resph    Response handler
 * @param arg      Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_request(struct sip_request **reqp, struct sip *sip, bool stateful,
		const char *met, int metl, const char *uri, int uril,
		const struct uri *route, struct mbuf *mb,
		sip_send_h *sendh, sip_resp_h *resph, void *arg)
{
	struct sip_request *req;
	struct sa dst;
	struct pl pl;
	int err;

	if (!sip || !met || !uri || !route || !mb)
		return EINVAL;

	if (pl_strcasecmp(&route->scheme, "sip"))
		return ENOSYS;

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

	list_append(&sip->reql, &req->le, req);

	err = str_ldup(&req->met, met, metl);
	if (err)
		goto out;

	err = str_ldup(&req->uri, uri, uril);
	if (err)
		goto out;

	if (msg_param_decode(&route->params, "maddr", &pl))
		pl = route->host;

	err = pl_strdup(&req->host, &pl);
	if (err)
		goto out;

	req->stateful = stateful;
	req->mb    = mem_ref(mb);
	req->sip   = sip;
	req->sendh = sendh;
	req->resph = resph;
	req->arg   = arg;

	if (!msg_param_decode(&route->params, "transport", &pl)) {

		if (!pl_strcasecmp(&pl, "udp"))
			req->tp = SIP_TRANSP_UDP;
		else if (!pl_strcasecmp(&pl, "tcp"))
			req->tp = SIP_TRANSP_TCP;
		else if (!pl_strcasecmp(&pl, "tls"))
			req->tp = SIP_TRANSP_TLS;
		else {
			err = EPROTONOSUPPORT;
			goto out;
		}

		if (!sip_transp_supported(sip, req->tp, AF_UNSPEC)) {
			err = EPROTONOSUPPORT;
			goto out;
		}

		req->tp_selected = true;
	}
	else {
		req->tp = SIP_TRANSP_NONE;
		if (!transp_next(sip, &req->tp)) {
			err = EPROTONOSUPPORT;
			goto out;
		}

		req->tp_selected = false;
	}

	if (!sa_set_str(&dst, req->host,
			sip_transp_port(req->tp, route->port))) {

		err = request(req, req->tp, &dst);
		if (!req->stateful) {
			mem_deref(req);
			return err;
		}
	}
	else if (route->port) {

		req->port = sip_transp_port(req->tp, route->port);
		err = addr_lookup(req, req->host);
	}
	else if (req->tp_selected) {

		err = srv_lookup(req, req->host);
	}
	else {
	        err = dnsc_query(&req->dnsq, sip->dnsc, req->host,
				 DNS_TYPE_NAPTR, DNS_CLASS_IN, true,
				 naptr_handler, req);
	}

 out:
	if (err)
		mem_deref(req);
	else if (reqp) {
		req->reqp = reqp;
		*reqp = req;
	}

	return err;
}
Ejemplo n.º 8
0
Archivo: msg.c Proyecto: Issic47/libre
static inline int hdr_add(struct sip_msg *msg, const struct pl *name,
			  enum sip_hdrid id, const char *p, ssize_t l,
			  bool atomic, bool line)
{
	struct sip_hdr *hdr;
	int err = 0;

	hdr = mem_zalloc(sizeof(*hdr), hdr_destructor);
	if (!hdr)
		return ENOMEM;

	hdr->name  = *name;
	hdr->val.p = p;
	hdr->val.l = MAX(l, 0);
	hdr->id    = id;

	switch (id) {

	case SIP_HDR_VIA:
	case SIP_HDR_ROUTE:
		if (!atomic)
			break;

		hash_append(msg->hdrht, id, &hdr->he, mem_ref(hdr));
		list_append(&msg->hdrl, &hdr->le, mem_ref(hdr));
		break;

	default:
		if (atomic)
			hash_append(msg->hdrht, id, &hdr->he, mem_ref(hdr));
		if (line)
			list_append(&msg->hdrl, &hdr->le, mem_ref(hdr));
		break;
	}

	/* parse common headers */
	switch (id) {

	case SIP_HDR_VIA:
		if (!atomic || pl_isset(&msg->via.sentby))
			break;

		err = sip_via_decode(&msg->via, &hdr->val);
		break;

	case SIP_HDR_TO:
		err = sip_addr_decode((struct sip_addr *)&msg->to, &hdr->val);
		if (err)
			break;

		(void)msg_param_decode(&msg->to.params, "tag", &msg->to.tag);
		msg->to.val = hdr->val;
		break;

	case SIP_HDR_FROM:
		err = sip_addr_decode((struct sip_addr *)&msg->from,
				      &hdr->val);
		if (err)
			break;

		(void)msg_param_decode(&msg->from.params, "tag",
				       &msg->from.tag);
		msg->from.val = hdr->val;
		break;

	case SIP_HDR_CALL_ID:
		msg->callid = hdr->val;
		break;

	case SIP_HDR_CSEQ:
		err = sip_cseq_decode(&msg->cseq, &hdr->val);
		break;

	case SIP_HDR_MAX_FORWARDS:
		msg->maxfwd = hdr->val;
		break;

	case SIP_HDR_CONTENT_TYPE:
		err = msg_ctype_decode(&msg->ctyp, &hdr->val);
		break;

	case SIP_HDR_CONTENT_LENGTH:
		msg->clen = hdr->val;
		break;

	case SIP_HDR_EXPIRES:
		msg->expires = hdr->val;
		break;

	default:
		/* re_printf("%r = %u\n", &hdr->name, id); */
		break;
	}

	mem_deref(hdr);

	return err;
}
Ejemplo n.º 9
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;
}