Exemple #1
0
int icem_rcand_add(struct icem *icem, enum cand_type type, uint8_t compid,
		   uint32_t prio, const struct sa *addr,
		   const struct sa *rel_addr, const struct pl *foundation)
{
	struct cand *rcand;
	int err;

	if (!icem || !foundation)
		return EINVAL;

	rcand = mem_zalloc(sizeof(*rcand), cand_destructor);
	if (!rcand)
		return ENOMEM;

	list_append(&icem->rcandl, &rcand->le, rcand);

	rcand->type   = type;
	rcand->compid = compid;
	rcand->prio   = prio;

	sa_cpy(&rcand->addr, addr);
	sa_cpy(&rcand->rel, rel_addr);

	err = pl_strdup(&rcand->foundation, foundation);

	if (err)
		mem_deref(rcand);

	return err;
}
/**
 * Get the local IP address of the device
 *
 * @note Requires at least one IP packet sent in advance!
 */
int net_if_getaddr4(const char *ifname, int af, struct sa *ip)
{
	(void)ifname;

	if (AF_INET != af)
		return EAFNOSUPPORT;

	/* Already cached? */
	if (sa_isset(&local_ip, SA_ADDR)) {
		sa_cpy(ip, &local_ip);
		return 0;
	}

	RSocketServ ss;
	RSocket s;
	TInt ret;

	ret = ss.Connect();
	if (KErrNone != ret) {
		DEBUG_WARNING("connecting to socket server fail (ret=%d)\n",
			      ret);
		return ECONNREFUSED;
	}

	ret = s.Open(ss, KAfInet, KSockDatagram, KProtocolInetUdp);
	if (KErrNone != ret) {
		DEBUG_WARNING("open socket failed (ret=%d)\n", ret);
		return ECONNREFUSED;
	}

	TInetAddr bind;
	bind.SetPort(0);
	bind.SetAddress(KInetAddrAny);

	ret = s.Bind(bind);
	if (KErrNone != ret) {
		DEBUG_WARNING("bind socket failed (ret=%d)\n", ret);
		return ECONNREFUSED;
	}

	TInetAddr local;
	s.LocalName(local);

	s.Close();
	ss.Close();

	sa_set_in(&local_ip, local.Address(), local.Port());

	DEBUG_NOTICE("local IP addr: %j\n", &local_ip);

	if (!sa_isset(&local_ip, SA_ADDR))
		return EINVAL;

	sa_cpy(ip, &local_ip);

	return 0;
}
static int start_gathering(struct icem *icem, const struct sa *stun_srv,
			   const char *username, const char *password)
{
	struct le *le;
	int err = 0;

	if (icem->ice->lmode != ICE_MODE_FULL)
		return EINVAL;

	sa_cpy(&icem->stun_srv, stun_srv);

	/* for each component */
	for (le = icem->compl.head; le; le = le->next) {

		struct icem_comp *comp = le->data;

		if (username && password) {
			err |= cand_gather_relayed(icem, comp,
						   username, password);
		}
		else
			err |= send_binding_request(icem, comp);
	}

	return err;
}
Exemple #4
0
static bool if_getaddr_handler(const char *ifname,
			       const struct sa *sa, void *arg)
{
	struct ifentry *ife = arg;

	/* Match name of interface? */
	if (str_isset(ife->ifname) && 0 != str_casecmp(ife->ifname, ifname))
		return false;

	if (!sa_isset(sa, SA_ADDR))
		return false;

#if 1
	/* skip loopback and link-local IP */
	if (sa_is_loopback(sa) || sa_is_linklocal(sa))
		return false;
#endif

	/* Match address family */
	if (ife->af != sa_af(sa))
		return false;

	/* Match - copy address */
	sa_cpy(ife->ip, sa);
	ife->found = true;

	return ife->found;
}
Exemple #5
0
static int udp_send_internal(struct udp_sock *us, const struct sa *dst,
			     struct mbuf *mb, struct le *le)
{
	struct sa hdst;
	int err = 0, fd;

	/* check for error in e.g. connected state */
	if (us->err) {
		err = us->err;
		us->err = 0; /* clear error */
		return err;
	}

	/* choose a socket */
	if (AF_INET6 == sa_af(dst) && -1 != us->fd6)
		fd = us->fd6;
	else
		fd = us->fd;

	/* call helpers in reverse order */
	while (le) {
		struct udp_helper *uh = le->data;

		le = le->prev;

		if (dst != &hdst) {
			sa_cpy(&hdst, dst);
			dst = &hdst;
		}

		if (uh->sendh(&err, &hdst, mb, uh->arg) || err)
			return err;
	}

	/* Connected socket? */
	if (us->conn) {
		if (0 != connect(fd, &dst->u.sa, dst->len)) {
			DEBUG_WARNING("send: connect: %s\n", strerror(errno));
			us->conn = false;
		}

		if (send(fd, BUF_CAST mb->buf + mb->pos, mb->end - mb->pos,
			 0) < 0)
			return errno;
	}
	else {
		if (sendto(fd, BUF_CAST mb->buf + mb->pos, mb->end - mb->pos,
			   0, &dst->u.sa, dst->len) < 0)
			return errno;
	}

	return 0;
}
Exemple #6
0
void rtcp_sess_rx_rtp(struct rtcp_sess *sess, uint16_t seq, uint32_t ts,
		      uint32_t ssrc, size_t payload_size,
		      const struct sa *peer)
{
	struct rtp_member *mbr;

	if (!sess)
		return;

	mbr = get_member(sess, ssrc);
	if (!mbr) {
		DEBUG_NOTICE("could not add member: 0x%08x\n", ssrc);
		return;
	}

	if (!mbr->s) {
		mbr->s = mem_zalloc(sizeof(*mbr->s), NULL);
		if (!mbr->s) {
			DEBUG_NOTICE("could not add sender: 0x%08x\n", ssrc);
			return;
		}

		/* first packet - init sequence number */
		source_init_seq(mbr->s, seq);
		mbr->s->max_seq = seq - 1;
		/* probation not used */
		sa_cpy(&mbr->s->rtp_peer, peer);
		++sess->senderc;
	}

	if (!source_update_seq(mbr->s, seq)) {
		DEBUG_WARNING("rtp_update_seq() returned 0\n");
	}

	if (sess->srate_rx) {

		uint32_t ts_arrive;

		/* Convert from wall-clock time to timestamp units */
		ts_arrive = (uint32_t)(tmr_jiffies()) * sess->srate_rx / 1000;

		source_calc_jitter(mbr->s, ts, ts_arrive);
	}

	mbr->s->rtp_rx_bytes += payload_size;
}
Exemple #7
0
int http_clone(struct request **rp, struct request *req)
{
    struct request *request;
    int ok;

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

    ok = hash_alloc(&request->hdrht, HDR_HASH_SIZE);
    if(ok!=0)
        goto fail;

    request->err_h = req->err_h;
    request->done_h = req->done_h;
    request->arg = req->arg;

    if(req->post)
        request->post = mem_ref(req->post);
    else
	request->post = NULL;

    request->form = req->form;
    request->host = mem_ref(req->host);
    request->path = mem_ref(req->path);
    request->secure = req->secure;
    request->port = req->port;
    memcpy(&request->meth, &req->meth, 5);
    sa_cpy(&request->dest, &req->dest);
    request->www_auth.p = NULL;
    request->www_auth.l = 0;
    request->auth = NULL;

    // skip network resolution
    request->state = RESOLVED;
    request->app = req->app;

    *rp = request;
    return 0;
fail:
    return ok;

}
Exemple #8
0
// connect callback
void p2p_request_handler(struct p2phandle *p2p, const char* peername, struct p2pconnection **p2pcon)
{
	re_fprintf(stderr, "p2p accept from:%s\n", peername);
	int err = p2p_accept(p2p, p2pcon, peername, p2p_receive_handler, *p2pcon);
	int fdaccept = udp_sock_fd((*p2pcon)->ulsock, AF_INET);
	struct sa* lsa = NULL;
	lsa = (struct sa*)mem_zalloc(sizeof(struct sa),NULL);
	udp_local_get((*p2pcon)->ulsock, lsa);
	sa_cpy(lsa, p2p->sactl);
	int fdlisten = tcp_conn_fd(p2p->ltcp);
	UDPSOCKET udpsock = (UDPSOCKET)fdlisten;
	(*p2pcon)->udtsock = CUDT::socket(AF_INET, SOCK_STREAM, 0);
	CUDT::bind((*p2pcon)->udtsock, &udpsock, &(p2p->sactl->u.sa), p2p->sactl->len);
	CUDT::listen((*p2pcon)->udtsock, &(lsa->u.sa), 10);
	if (err)
	{
		re_fprintf(stderr, "p2p accept error:%s\n", strerror(err));
		return ;
	}
}
Exemple #9
0
int icem_lcand_add(struct icem *icem, struct cand *base, enum cand_type type,
		   const struct sa *addr)
{
	struct cand *cand;
	int err;

	if (!base)
		return EINVAL;

	err = cand_alloc(&cand, icem, type, base->compid,
			 ice_calc_prio(type, 0, base->compid),
			 base->ifname, base->transp, addr);
	if (err)
		return err;

	cand->base = mem_ref(base);
	sa_cpy(&cand->rel, &base->addr);

	return 0;
}
Exemple #10
0
struct udp_sock *restund_udp_socket(struct sa *sa, const struct sa *orig,
                                    bool ch_ip, bool ch_port)
{
    struct le *le = list_head(&lstnrl);

    while (le) {
        struct udp_lstnr *ul = le->data;
        le = le->next;

        if (ch_ip && sa_cmp(orig, &ul->bnd_addr, SA_PORT))
            continue;

        if (ch_port && (sa_port(orig) == sa_port(&ul->bnd_addr)))
            continue;

        sa_cpy(sa, &ul->bnd_addr);
        return ul->us;
    }

    return NULL;
}
Exemple #11
0
static void udp_loop_recv(const struct sa *src, struct mbuf *mb,
			  void *arg)
{
	int err;

	(void)arg;

	sa_cpy(&turnc.loop_src, src);

	if (!turnc.tc) {
		DEBUG_WARNING("no turn client\n");
		return;
	}

	if (!sa_isset(turnc.peer, SA_ALL)) {
		DEBUG_WARNING("Peer not set\n");
		return;
	}

	err = udp_send(turnc.us, turnc.peer, mb);
	if (err) {
		DEBUG_WARNING("turnc send data: %m\n", err);
	}
}
Exemple #12
0
static int cand_alloc(struct cand **candp, struct icem *icem,
		      enum cand_type type, uint8_t compid,
		      uint32_t prio, const char *ifname,
		      enum ice_transp transp, const struct sa *addr)
{
	struct cand *cand;
	int err;

	if (!icem)
		return EINVAL;

	cand = mem_zalloc(sizeof(*cand), cand_destructor);
	if (!cand)
		return ENOMEM;

	list_append(&icem->lcandl, &cand->le, cand);

	cand->type   = type;
	cand->compid = compid;
	cand->prio   = prio;
	cand->transp = transp;

	sa_cpy(&cand->addr, addr);

	err = compute_foundation(cand);

	if (ifname)
		err |= str_dup(&cand->ifname, ifname);

	if (err)
		mem_deref(cand);
	else if (candp)
		*candp = cand;

	return err;
}
/**
 * Allocate a new NAT Hairpinning discovery session
 *
 * @param nhp      Pointer to allocated NAT Hairpinning object
 * @param proto    Transport protocol
 * @param srv      STUN Server IP address and port number
 * @param proto    Transport protocol
 * @param conf     STUN configuration (Optional)
 * @param hph      Hairpinning result handler
 * @param arg      Handler argument
 *
 * @return 0 if success, errorcode if failure
 */
int nat_hairpinning_alloc(struct nat_hairpinning **nhp,
			  const struct sa *srv, int proto,
			  const struct stun_conf *conf,
			  nat_hairpinning_h *hph, void *arg)
{
	struct nat_hairpinning *nh;
	struct sa local;
	int err;

	if (!srv || !hph)
		return EINVAL;

	nh = mem_zalloc(sizeof(*nh), hairpinning_destructor);
	if (!nh)
		return ENOMEM;

	err = stun_alloc(&nh->stun, conf, NULL, NULL);
	if (err)
		goto out;

	sa_cpy(&nh->srv, srv);
	nh->proto = proto;
	nh->hph   = hph;
	nh->arg   = arg;

	switch (proto) {

	case IPPROTO_UDP:
		err = udp_listen(&nh->us, NULL, udp_recv_handler, nh);
		break;

	case IPPROTO_TCP:
		sa_set_in(&local, 0, 0);

		/*
		 * Part I - Allocate and bind all sockets
		 */
		err = tcp_sock_alloc(&nh->ts, &local, tcp_conn_handler, nh);
		if (err)
			break;

		err = tcp_conn_alloc(&nh->tc, &nh->srv,
				     tcp_estab_handler, tcp_recv_handler,
				     tcp_close_handler, nh);
		if (err)
			break;

		err = tcp_sock_bind(nh->ts, &local);
		if (err)
			break;

		err = tcp_sock_local_get(nh->ts, &local);
		if (err)
			break;

		err = tcp_conn_bind(nh->tc, &local);
		if (err)
			break;

		/*
		 * Part II - Listen and connect all sockets
		 */
		err = tcp_sock_listen(nh->ts, 5);
		break;

	default:
		err = EPROTONOSUPPORT;
		break;
	}

 out:
	if (err)
		mem_deref(nh);
	else
		*nhp = nh;

	return err;
}
/**
 * Allocate a new NAT Mapping Behaviour Discovery session
 *
 * @param nmp       Pointer to allocated NAT Mapping object
 * @param laddr     Local IP address
 * @param srv       STUN Server IP address and port
 * @param proto     Transport protocol
 * @param conf      STUN configuration (Optional)
 * @param mh        Mapping handler
 * @param arg       Handler argument
 *
 * @return 0 if success, errorcode if failure
 */
int nat_mapping_alloc(struct nat_mapping **nmp, const struct sa *laddr,
		      const struct sa *srv, int proto,
		      const struct stun_conf *conf,
		      nat_mapping_h *mh, void *arg)
{
	struct nat_mapping *nm;
	int i, err;

	if (!nmp || !laddr || !srv || !mh)
		return EINVAL;

	nm = mem_zalloc(sizeof(*nm), mapping_destructor);
	if (!nm)
		return ENOMEM;

	err = stun_alloc(&nm->stun, conf, NULL, NULL);
	if (err)
		goto out;

	nm->proto = proto;
	sa_cpy(&nm->laddr, laddr);

	switch (proto) {

	case IPPROTO_UDP:
		err = udp_listen(&nm->us, &nm->laddr, udp_recv_handler, nm);
		if (err)
			goto out;
		err = udp_local_get(nm->us, &nm->laddr);
		if (err)
			goto out;
		break;

	case IPPROTO_TCP:

		/* Allocate and bind 3 TCP Sockets */
		for (i=0; i<3; i++) {
			err = tcp_conn_alloc(&nm->tcv[i], srv,
					     tcp_estab_handler,
					     tcp_recv_handler,
					     tcp_close_handler, nm);
			if (err)
				goto out;

			err = tcp_conn_bind(nm->tcv[i], &nm->laddr);
			if (err)
				goto out;

			err = tcp_conn_local_get(nm->tcv[i], &nm->laddr);
			if (err)
				goto out;
		}
		break;

	default:
		err = EPROTONOSUPPORT;
		goto out;
	}

	sa_cpy(&nm->srv, srv);
	nm->mh  = mh;
	nm->arg = arg;

	*nmp = nm;

 out:
	if (err)
		mem_deref(nm);
	return err;
}
Exemple #15
0
int udp_sock::send(const struct sa *dst, struct mbuf *mb)
{
	struct sa hdst;
	TRequestStatus stat;
	int err = 0;

	DEBUG_INFO("udp_sock::send %u bytes to %J\n", mbuf_get_left(mb), dst);

	/* Check for error in e.g. connected state */
	if (cerr) {
		err = cerr;
		cerr = 0; /* clear error */
		return err;
	}

	/* call helpers in reverse order */
	struct le *le = list_tail(&helpers);
	while (le) {
		struct udp_helper *uh;

		uh = (struct udp_helper *)le->data;
		le = le->prev;

		if (dst != &hdst) {
			sa_cpy(&hdst, dst);
			dst = &hdst;
		}

		if (uh->sendh(&err, &hdst, mb, uh->arg) || err)
			return err;
	}

	TInetAddr ia(sa_in(dst), sa_port(dst));

	const TPtrC8 buf_tx(mb->buf + mb->pos, mb->end - mb->pos);

	if (conn) {
		cus->iSocket.Connect(ia, stat);
		User::WaitForRequest(stat);

		if (KErrNone != stat.Int()) {
			DEBUG_WARNING("udp_sock::send Connect: kerr=%d\n",
				      stat.Int());
			if (KErrGeneral == stat.Int())
				return ECONNREFUSED;
		}

#if 0
		/* TODO: Cause Access-Violation in WINS emulator! */
		cus->iSocket.Send(buf_tx, 0, stat);
#else
		cus->iSocket.SendTo(buf_tx, ia, 0, stat);
#endif
	}
	else {
		cus->iSocket.SendTo(buf_tx, ia, 0, stat);
	}

	User::WaitForRequest(stat);

	return kerr2errno(stat.Int());
}
static void stun_response_handler(int err, uint16_t scode, const char *reason,
				  const struct stun_msg *msg, void *arg)
{
	struct nat_mapping *nm = arg;
	struct stun_attr *map, *other;

	if (err) {
		DEBUG_WARNING("stun_response_handler: (%m)\n", err);
		nm->mh(err, NAT_TYPE_UNKNOWN, nm->arg);
		return;
	}

	switch (scode) {

	case 0:
		other = stun_msg_attr(msg, STUN_ATTR_OTHER_ADDR);
		map = stun_msg_attr(msg, STUN_ATTR_XOR_MAPPED_ADDR);
		if (!map)
			map = stun_msg_attr(msg, STUN_ATTR_MAPPED_ADDR);

		if (!map || !other) {
			DEBUG_WARNING("missing attributes: %s %s\n",
				      map   ? "" : "MAPPED-ADDR",
				      other ? "" : "OTHER-ADDR");
			nm->mh(EPROTO, NAT_TYPE_UNKNOWN, nm->arg);
			return;
		}

		nm->map[nm->test_phase-1] = map->v.sa;
		break;

	default:
		DEBUG_WARNING("Binding Error Resp: %u %s\n", scode, reason);
		nm->mh(EPROTO, NAT_TYPE_UNKNOWN, nm->arg);
		return;
	}

	switch (nm->test_phase) {

	case 1:
		/* Test I completed */
		if (sa_cmp(&nm->laddr, &nm->map[0], SA_ALL)) {
			nm->mh(0, NAT_TYPE_ENDP_INDEP, nm->arg);
			return;
		}

		/* Start Test II - the client sends a Binding Request to the
		   alternate *address* */
		++nm->test_phase;

		sa_set_port(&other->v.other_addr, sa_port(&nm->srv));
		sa_cpy(&nm->srv, &other->v.other_addr);

		err = mapping_send(nm);
		if (err) {
			DEBUG_WARNING("stunc_request_send: (%m)\n", err);
			nm->mh(err, NAT_TYPE_UNKNOWN, nm->arg);
		}
		break;

	case 2:
		/* Test II completed */
		if (sa_cmp(&nm->map[0], &nm->map[1], SA_ALL)) {
			nm->mh(0, NAT_TYPE_ENDP_INDEP, nm->arg);
			return;
		}

		/* Start Test III - the client sends a Binding Request
		   to the alternate address and port */
		++nm->test_phase;

		sa_set_port(&nm->srv, sa_port(&other->v.other_addr));
		err = mapping_send(nm);
		if (err) {
			DEBUG_WARNING("stunc_request_send: (%m)\n", err);
			nm->mh(err, NAT_TYPE_UNKNOWN, nm->arg);
		}
		break;

	case 3:
		/* Test III completed */
		if (sa_cmp(&nm->map[1], &nm->map[2], SA_ALL)) {
			nm->mh(0, NAT_TYPE_ADDR_DEP, nm->arg);
		}
		else {
			nm->mh(0, NAT_TYPE_ADDR_PORT_DEP, nm->arg);
		}
		++nm->test_phase;
		break;

	default:
		DEBUG_WARNING("invalid test phase %d\n", nm->test_phase);
		nm->mh(EINVAL, NAT_TYPE_UNKNOWN, nm->arg);
		break;
	}
}
Exemple #17
0
static int add_transp_af(const struct sa *laddr)
{
	struct sa local;
	int err = 0;

	if (str_isset(uag.cfg->local)) {
		err = sa_decode(&local, uag.cfg->local,
				str_len(uag.cfg->local));
		if (err) {
			err = sa_set_str(&local, uag.cfg->local, 0);
			if (err) {
				warning("ua: decode failed: '%s'\n",
					uag.cfg->local);
				return err;
			}
		}

		if (!sa_isset(&local, SA_ADDR)) {
			uint16_t port = sa_port(&local);
			(void)sa_set_sa(&local, &laddr->u.sa);
			sa_set_port(&local, port);
		}

		if (sa_af(laddr) != sa_af(&local))
			return 0;
	}
	else {
		sa_cpy(&local, laddr);
		sa_set_port(&local, 0);
	}

	if (uag.use_udp)
		err |= sip_transp_add(uag.sip, SIP_TRANSP_UDP, &local);
	if (uag.use_tcp)
		err |= sip_transp_add(uag.sip, SIP_TRANSP_TCP, &local);
	if (err) {
		warning("ua: SIP Transport failed: %m\n", err);
		return err;
	}

#ifdef USE_TLS
	if (uag.use_tls) {
		/* Build our SSL context*/
		if (!uag.tls) {
			const char *cert = NULL;

			if (str_isset(uag.cfg->cert)) {
				cert = uag.cfg->cert;
				info("SIP Certificate: %s\n", cert);
			}

			err = tls_alloc(&uag.tls, TLS_METHOD_SSLV23,
					cert, NULL);
			if (err) {
				warning("ua: tls_alloc() failed: %m\n", err);
				return err;
			}
		}

		if (sa_isset(&local, SA_PORT))
			sa_set_port(&local, sa_port(&local) + 1);

		err = sip_transp_add(uag.sip, SIP_TRANSP_TLS, &local, uag.tls);
		if (err) {
			warning("ua: SIP/TLS transport failed: %m\n", err);
			return err;
		}
	}
#endif

	return err;
}