Пример #1
0
static int request_next(struct sip_request *req)
{
	struct dnsrr *rr;
	struct sa dst;
	int err;

 again:
	rr = list_ledata(req->addrl.head);
	if (!rr) {
		rr = list_ledata(req->srvl.head);
		if (!rr)
			return ENOENT;

		req->port = rr->rdata.srv.port;

		dns_rrlist_apply2(&req->cachel, rr->rdata.srv.target,
				  DNS_TYPE_A, DNS_TYPE_AAAA, DNS_CLASS_IN,
				  true, rr_append_handler, &req->addrl);

		list_unlink(&rr->le);

		if (req->addrl.head) {
			mem_deref(rr);
			goto again;
		}

		err = addr_lookup(req, rr->rdata.srv.target);
		mem_deref(rr);

		return err;
	}

	switch (rr->type) {

	case DNS_TYPE_A:
		sa_set_in(&dst, rr->rdata.a.addr, req->port);
		break;

	case DNS_TYPE_AAAA:
		sa_set_in6(&dst, rr->rdata.aaaa.addr, req->port);
		break;

	default:
		return EINVAL;
	}

	list_unlink(&rr->le);
	mem_deref(rr);

	err = request(req, req->tp, &dst);
	if (err) {
		if (req->addrl.head || req->srvl.head)
			goto again;
	}

	return err;
}
Пример #2
0
static struct sipsess *sipsess_find(struct sipsess_sock *sock,
				    const struct sip_msg *msg)
{
	return list_ledata(hash_lookup(sock->ht_sess,
				       hash_joaat_pl(&msg->callid),
				       cmp_handler, (void *)msg));
}
Пример #3
0
static int request_next(struct request *req, struct sa* dst)
{
	struct dnsrr *rr;
	int err = 0;

	rr = list_ledata(req->addrl.head);
	if(!rr)
            return -ENOENT;

	switch (rr->type) {

	case DNS_TYPE_A:
		sa_set_in(dst, rr->rdata.a.addr, req->port);
		break;

	case DNS_TYPE_AAAA:
		sa_set_in6(dst, rr->rdata.aaaa.addr, req->port);
		break;

	default:
		return EINVAL;
	}

	list_unlink(&rr->le);
	mem_deref(rr);

	return err;
}
Пример #4
0
/**
 * Poll all timers in the current thread
 *
 * @param tmrl Timer list
 */
void tmr_poll(struct list *tmrl)
{
	const uint64_t jfs = tmr_jiffies();

	for (;;) {
		struct tmr *tmr;
		tmr_h *th;
		void *th_arg;

		tmr = list_ledata(tmrl->head);

		if (!tmr || (tmr->jfs > jfs)) {
			break;
		}

		th = tmr->th;
		th_arg = tmr->arg;

		tmr->th = NULL;

		list_unlink(&tmr->le);

		if (!th)
			continue;

#if TMR_DEBUG
		call_handler(th, th_arg);
#else
		th(th_arg);
#endif
	}
}
Пример #5
0
struct tls_conn *tls_udp_conn(const struct tls_sock *ts, const struct sa *peer)
{
	if (!ts)
		return NULL;

	return list_ledata(hash_lookup(ts->ht_conn, sa_hash(peer, SA_ALL),
				       hash_cmp_handler, (void *)peer));
}
Пример #6
0
/**
 * Lookup a SIP uri in all registered contacts
 *
 * @param contacts Contacts container
 * @param uri      SIP uri to lookup
 *
 * @return Matching contact if found, otherwise NULL
 */
struct contact *contact_find(const struct contacts *contacts, const char *uri)
{
	if (!contacts)
		return NULL;

	return list_ledata(hash_lookup(contacts->cht, hash_joaat_str(uri),
				       find_handler, (void *)uri));
}
Пример #7
0
static struct allocation *allocation_find(int proto, const struct sa *src,
					  const struct sa *dst)
{
	struct tuple tup;

	tup.cli_addr = src;
	tup.srv_addr = dst;
	tup.proto = proto;

	return list_ledata(hash_lookup(turnd.ht_alloc, sa_hash(src, SA_ALL),
				       hash_cmp_handler, &tup));
}
Пример #8
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;
}
Пример #9
0
/**
 * Get number of milliseconds until the next timer expires
 *
 * @param tmrl Timer-list
 *
 * @return Number of [ms], or 0 if no active timers
 */
uint64_t tmr_next_timeout(struct list *tmrl)
{
	const uint64_t jif = tmr_jiffies();
	const struct tmr *tmr;

	tmr = list_ledata(tmrl->head);
	if (!tmr)
		return 0;

	if (tmr->jfs <= jif)
		return 1;
	else
		return tmr->jfs - jif;
}
TEST_F(cryptoboxtest, tmp)
{
#define NUM 3
	struct device *a;

	add_devices(NUM);

	connect_devices();

	//debug();

	/* number of peers is always N-1 */
	a = (struct device *)list_ledata(devicel.head);
	ASSERT_EQ(NUM-1, list_count(&a->peerl));
}
Пример #11
0
int sipsess_reply_ack(struct sipsess *sess, const struct sip_msg *msg,
		      bool *awaiting_answer)
{
	struct sipsess_reply *reply;

	reply = list_ledata(list_apply(&sess->replyl, false, cmp_handler,
				       (void *)msg));
	if (!reply)
		return ENOENT;

	*awaiting_answer = reply->awaiting_answer;

	mem_deref(reply);

	return 0;
}
Пример #12
0
static int send_tcp(struct dns_query *q)
{
	const struct sa *srv;
	struct tcpconn *tc;
	int err = 0;

	if (!q)
		return EINVAL;

	while (q->ntx < *q->srvc) {

		srv = &q->srvv[q->ntx++];

		DEBUG_NOTICE("trying tcp server#%u: %J\n", q->ntx-1, srv);

		tc = list_ledata(hash_lookup(q->dnsc->ht_tcpconn,
					     sa_hash(srv, SA_ALL),
					     tcpconn_cmp_handler,
					     (void *)srv));
		if (!tc) {
			err = tcpconn_alloc(&tc, q->dnsc, srv);
			if (err)
				continue;
		}

		if (tc->connected) {
			q->mb.pos = 0;
			err = tcp_send(tc->conn, &q->mb);
			if (err) {
				tcpconn_close(tc, err);
				continue;
			}

			tmr_start(&tc->tmr, tc->dnsc->conf.idle_timeout,
				  tcpconn_timeout_handler, tc);
			DEBUG_NOTICE("tcp send %J\n", srv);
		}

		list_append(&tc->ql, &q->le_tc, q);
		q->tc = mem_ref(tc);
		break;
	}

	return err;
}
	void send_all()
	{
		struct le *le;

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

			struct device *dev = (struct device *)le->data, *other;
			struct le *next;

			next = le->next ? le->next : devicel.head;
			other = (struct device *)list_ledata(next);

			err = device_new_session(dev, other);
			ASSERT_EQ(0, err);

			send_message(dev, other, hello_msg, sizeof(hello_msg));
		}
	}
Пример #14
0
static bool response_handler(const struct sip_msg *msg, void *arg)
{
	struct sip_ctrans *ct;
	struct sip *sip = arg;

	ct = list_ledata(hash_lookup(sip->ht_ctrans,
				     hash_joaat_pl(&msg->via.branch),
				     cmp_handler, (void *)msg));
	if (!ct)
		return false;

	if (ct->invite) {
		invite_response(ct, msg);
		return true;
	}

	switch (ct->state) {

	case TRYING:
	case PROCEEDING:
		if (msg->scode < 200) {
			ct->state = PROCEEDING;
			ct->resph(0, msg, ct->arg);
		}
		else {
			ct->state = COMPLETED;
			ct->resph(0, msg, ct->arg);

			if (sip_transp_reliable(ct->tp)) {
				mem_deref(ct);
				break;
			}

			tmr_start(&ct->tmr, SIP_T4, tmr_handler, ct);
			tmr_cancel(&ct->tmre);
		}
		break;

	default:
		break;
	}

	return true;
}
Пример #15
0
struct chan *chan_peer_find(const struct chanlist *cl, const struct sa *peer)
{
	struct chan *chan;

	if (!cl || !peer)
		return NULL;

	chan = list_ledata(hash_lookup(cl->ht_peer, sa_hash(peer, SA_ALL),
				       hash_peer_cmp_handler, (void *)peer));
	if (!chan)
		return NULL;

	if (chan->expires < time(NULL)) {
		restund_debug("turn: allocation %p channel 0x%x %J expired\n",
			      chan->al, chan->numb, &chan->peer);
		mem_deref(chan);
		return NULL;
	}

	return chan;
}
Пример #16
0
struct chan *chan_numb_find(const struct chanlist *cl, uint16_t numb)
{
	struct chan *chan;

	if (!cl)
		return NULL;

	chan = list_ledata(hash_lookup(cl->ht_numb, numb,
				       hash_numb_cmp_handler, &numb));
	if (!chan)
		return NULL;

	if (chan->expires < time(NULL)) {
		restund_debug("turn: allocation %p channel 0x%x %J expired\n",
			      chan->al, chan->numb, &chan->peer);
		mem_deref(chan);
		return NULL;
	}

	return chan;
}
/* Test sending messages between 3 devices */
TEST_F(cryptoboxtest, three_devices)
{
	struct le *le;

	add_devices(3);

	/* Connect the devices */
	connect_devices();

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

		struct device *dev = (struct device *)le->data, *other;
		struct le *next;

		next = le->next ? le->next : devicel.head;
		other = (struct device *)list_ledata(next);

		err = device_new_session(dev, other);
		ASSERT_EQ(0, err);

		send_message(dev, other, hello_msg, sizeof(hello_msg));
	}
}
Пример #18
0
static int dequeue(struct tcp_conn *tc)
{
	struct tcp_qent *qe = list_ledata(tc->sendq.head);
	ssize_t n;
#ifdef MSG_NOSIGNAL
	const int flags = MSG_NOSIGNAL; /* disable SIGPIPE signal */
#else
	const int flags = 0;
#endif
	if (!qe) {
		if (tc->sendh)
			tc->sendh(tc->arg);

		return 0;
	}

	n = send(tc->fdc, BUF_CAST mbuf_buf(&qe->mb),
		 qe->mb.end - qe->mb.pos, flags);
	if (n < 0) {
		if (EAGAIN == errno)
			return 0;
#ifdef WIN32
		if (WSAEWOULDBLOCK == WSAGetLastError())
			return 0;
#endif
		return errno;
	}

	tc->txqsz  -= n;
	qe->mb.pos += n;

	if (qe->mb.pos >= qe->mb.end)
		mem_deref(qe);

	return 0;
}
Пример #19
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;
}
Пример #20
0
static bool auth_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
			 void *arg)
{
	struct httpauth_digest_chall ch;
	struct sip_auth *auth = arg;
	struct realm *realm = NULL;
	int err;
	(void)msg;

	if (httpauth_digest_challenge_decode(&ch, &hdr->val)) {
		err = EBADMSG;
		goto out;
	}

	if (pl_isset(&ch.algorithm) && pl_strcasecmp(&ch.algorithm, "md5")) {
		err = ENOSYS;
		goto out;
	}

	realm = list_ledata(list_apply(&auth->realml, true, cmp_handler,
				       &ch.realm));
	if (!realm) {
		realm = mem_zalloc(sizeof(*realm), realm_destructor);
		if (!realm) {
			err = ENOMEM;
			goto out;
		}

		list_append(&auth->realml, &realm->le, realm);

		err = pl_strdup(&realm->realm, &ch.realm);
		if (err)
			goto out;

		err = auth->authh(&realm->user, &realm->pass,
				  realm->realm, auth->arg);
		if (err)
			goto out;
	}
	else {
		if (!pl_isset(&ch.stale) || pl_strcasecmp(&ch.stale, "true")) {
			err = EAUTH;
			goto out;
		}

		realm->nonce  = mem_deref(realm->nonce);
		realm->qop    = mem_deref(realm->qop);
		realm->opaque = mem_deref(realm->opaque);
	}

	realm->hdr = hdr->id;
	realm->nc  = 1;

	err = pl_strdup(&realm->nonce, &ch.nonce);

	if (pl_isset(&ch.qop))
		err |= pl_strdup(&realm->qop, &ch.qop);

	if (pl_isset(&ch.opaque))
		err |= pl_strdup(&realm->opaque, &ch.opaque);

 out:
	if (err) {
		mem_deref(realm);
		auth->err = err;
		return true;
	}

	return false;
}
Пример #21
0
static struct device *find_device(const char *device)
{
	return list_ledata(hash_lookup(ht_device, hash_joaat_str(device),
				       list_apply_handler, (void *)device));
}
Пример #22
0
static struct perm *perm_find(const struct turnc *turnc, const struct sa *peer)
{
	return list_ledata(hash_lookup(turnc->perms, sa_hash(peer, SA_ADDR),
				       hash_cmp_handler, (void *)peer));
}
Пример #23
0
struct vidisp_st *vidbridge_disp_find(const char *device)
{
    return list_ledata(hash_lookup(ht_disp, hash_joaat_str(device),
                                   list_apply_handler, (void *)device));
}
Пример #24
0
static int reply_recv(struct dnsc *dnsc, struct mbuf *mb)
{
	struct dns_query *q = NULL;
	uint32_t i, j, nv[3];
	struct dnsquery dq;
	int err = 0;

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

	dq.name = NULL;

	if (dns_hdr_decode(mb, &dq.hdr) || !dq.hdr.qr) {
		err = EBADMSG;
		goto out;
	}

	err = dns_dname_decode(mb, &dq.name, 0);
	if (err)
		goto out;

	if (mbuf_get_left(mb) < 4) {
		err = EBADMSG;
		goto out;
	}

	dq.type     = ntohs(mbuf_read_u16(mb));
	dq.dnsclass = ntohs(mbuf_read_u16(mb));

	q = list_ledata(hash_lookup(dnsc->ht_query, hash_joaat_str_ci(dq.name),
				    query_cmp_handler, &dq));
	if (!q) {
		err = ENOENT;
		goto out;
	}

	/* try next server */
	if (dq.hdr.rcode == DNS_RCODE_SRV_FAIL && q->ntx < *q->srvc) {

		if (!q->tc) /* try next UDP server immediately */
			tmr_start(&q->tmr, 0, udp_timeout_handler, q);

		err = EPROTO;
		goto out;
	}

	nv[0] = dq.hdr.nans;
	nv[1] = dq.hdr.nauth;
	nv[2] = dq.hdr.nadd;

	for (i=0; i<ARRAY_SIZE(nv); i++) {

		for (j=0; j<nv[i]; j++) {

			struct dnsrr *rr = NULL;

			err = dns_rr_decode(mb, &rr, 0);
			if (err) {
				query_handler(q, err, NULL, NULL, NULL, NULL);
				mem_deref(q);
				goto out;
			}

			list_append(&q->rrlv[i], &rr->le_priv, rr);
		}
	}

	if (q->type == DNS_QTYPE_AXFR) {

		struct dnsrr *rrh, *rrt;

		rrh = list_ledata(list_head(&q->rrlv[0]));
		rrt = list_ledata(list_tail(&q->rrlv[0]));

		/* Wait for last AXFR reply with terminating SOA record */
		if (dq.hdr.rcode == DNS_RCODE_OK && dq.hdr.nans > 0 &&
		    (!rrt || rrt->type != DNS_TYPE_SOA || rrh == rrt)) {
			DEBUG_INFO("waiting for last SOA record in reply\n");
			goto out;
		}
	}

	query_handler(q, 0, &dq.hdr, &q->rrlv[0], &q->rrlv[1], &q->rrlv[2]);
	mem_deref(q);

 out:
	mem_deref(dq.name);

	return err;
}
Пример #25
0
static inline struct dname *dname_lookup(struct hash *ht_dname,
					 const char *name)
{
	return list_ledata(hash_lookup(ht_dname, hash_joaat_str_ci(name),
				       lookup_handler, (void *)name));
}