Esempio n. 1
0
int pf_create(struct pf **pfp, struct udp_sock *us, const char *name)
{
	struct pf *pf;
	int err;

	if (!pfp || !us)
		return EINVAL;

	pf = mem_zalloc(sizeof(*pf), pf_destructor);
	if (!pf)
		return ENOMEM;

	pf->us = mem_ref(us);
	str_ncpy(pf->name, name, sizeof(pf->name));

	err = udp_register_helper(&pf->uh, us,
				  -1000, /* very low layer */
				  pf_send_handler, pf_recv_handler, pf);

	if (err)
		mem_deref(pf);
	else
		*pfp = pf;

	return err;
}
Esempio n. 2
0
/**
 * Start TLS on a UDP socket (aka DTLS). The UDP socket can act as a
 * client or a server, and multiple DTLS connections can be established to
 * multiple peers, all from the same UDP socket.
 *
 * @param tsp    Pointer to allocated TLS socket
 * @param tls    TLS context
 * @param us     UDP socket
 * @param layer  Protocol stack layer
 * @param bsize  Bucket size for hash table (0 for default)
 *
 * @return 0 if success, otherwise errorcode
 */
int tls_start_udp(struct tls_sock **tsp, struct tls *tls, struct udp_sock *us,
		  int layer, uint32_t bsize)
{
	struct tls_sock *ts;
	int err;

	if (!tsp || !tls || !us)
		return EINVAL;

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

	err = hash_alloc(&ts->ht_conn, bsize ? bsize : 4);
	if (err)
		goto out;

	err = udp_register_helper(&ts->uh, us, layer, send_handler,
				  recv_handler, ts);
	if (err)
		goto out;

	ts->us = mem_ref(us);
	ts->tls = mem_ref(tls);

 out:
	if (err)
		mem_deref(ts);
	else
		*tsp = ts;

	return err;
}
Esempio n. 3
0
int test_udp(void)
{
	struct udp_sock *uss2;
	struct udp_test *ut;
	int err;

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

	err  = sa_set_str(&ut->cli, "127.0.0.1", 0);
	err |= sa_set_str(&ut->srv, "127.0.0.1", 0);
	if (err)
		goto out;

	err  = udp_listen(&ut->usc, &ut->cli, udp_recv_client, ut);
	err |= udp_listen(&ut->uss, &ut->srv, udp_recv_server, ut);
	if (err)
		goto out;

	udp_rxbuf_presz_set(ut->uss, 16);

	err  = udp_local_get(ut->usc, &ut->cli);
	err |= udp_local_get(ut->uss, &ut->srv);
	if (err)
		goto out;

	err = udp_register_helper(&ut->uh, ut->usc, 0,
				  udp_helper_send, udp_helper_recv, ut);
	if (err)
		goto out;

	/* expect failure */
	if (!udp_listen(&uss2, &ut->srv, udp_recv_client, ut)) {
		err = EBUSY;
		goto out;
	}

	/* Send from connected client UDP socket */
	err = udp_connect(ut->usc, &ut->srv);
	if (err)
		goto out;

	/* Start test */
	err = send_data(ut->usc, &ut->srv, data0);
	if (err)
		goto out;

	err = re_main_timeout(100);
	if (err)
		goto out;

	if (ut->err)
		err = ut->err;

 out:
	mem_deref(ut);

	return err;
}
Esempio n. 4
0
static int media_alloc(struct menc_media **stp, struct menc_sess *sess,
		       struct rtp_sock *rtp,
		       int proto, void *rtpsock, void *rtcpsock,
		       struct sdp_media *sdpm)
{
	struct menc_media *st;
	zrtp_status_t s;
	int layer = 10; /* above zero */
	int err = 0;
	(void)rtcpsock;

	if (!stp || !sess || proto != IPPROTO_UDP)
		return EINVAL;

	st = *stp;
	if (st)
		goto start;

	st = mem_zalloc(sizeof(*st), media_destructor);
	if (!st)
		return ENOMEM;

	st->sess = sess;
	st->rtpsock = mem_ref(rtpsock);

	err = udp_register_helper(&st->uh, rtpsock, layer,
				  udp_helper_send, udp_helper_recv, st);
	if (err)
		goto out;

	s = zrtp_stream_attach(sess->zrtp_session, &st->zrtp_stream);
	if (s != zrtp_status_ok) {
		warning("zrtp: zrtp_stream_attach failed (status=%d)\n", s);
		err = EPROTO;
		goto out;
	}

	zrtp_stream_set_userdata(st->zrtp_stream, st);

 out:
	if (err) {
		mem_deref(st);
		return err;
	}
	else
		*stp = st;

 start:
	if (sa_isset(sdp_media_raddr(sdpm), SA_ALL)) {
		st->raddr = *sdp_media_raddr(sdpm);

		s = zrtp_stream_start(st->zrtp_stream, rtp_sess_ssrc(rtp));
		if (s != zrtp_status_ok) {
			warning("zrtp: zrtp_stream_start: status = %d\n", s);
		}
	}

	return err;
}
Esempio n. 5
0
int dtls_flow_alloc(struct dtls_flow **flowp, struct tls *tls,
		    struct udp_sock *us, dtls_estab_h *estabh, void *arg)
{
	struct dtls_flow *flow;
	int err = ENOMEM;

	if (!flowp || !tls || !us || !estabh)
		return EINVAL;

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

	flow->tls    = tls;
	flow->us     = mem_ref(us);
	flow->estabh = estabh;
	flow->arg    = arg;

	err = udp_register_helper(&flow->uh, us, LAYER_DTLS, NULL,
				  recv_handler, flow);
	if (err)
		goto out;

	flow->ssl = SSL_new(tls->ctx);
	if (!flow->ssl) {
		ERR_clear_error();
		goto out;
	}

	flow->sbio_in = BIO_new(BIO_s_mem());
	if (!flow->sbio_in)
		goto out;

	flow->sbio_out = BIO_new(&bio_udp_send);
	if (!flow->sbio_out) {
		BIO_free(flow->sbio_in);
		goto out;
	}
	flow->sbio_out->ptr = flow;

	SSL_set_bio(flow->ssl, flow->sbio_in, flow->sbio_out);

	tmr_init(&flow->tmr);

	err = 0;

 out:
	if (err)
		mem_deref(flow);
	else
		*flowp = flow;

	return err;
}
Esempio n. 6
0
File: comp.c Progetto: soramimi/qSIP
int icem_comp_alloc(struct icem_comp **cp, struct icem *icem, int id,
		    void *sock)
{
	struct icem_comp *comp;
	struct sa local;
	int err;

	if (!cp || !icem || id<1 || id>255 || !sock)
		return EINVAL;

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

	comp->id = id;
	comp->sock = mem_ref(sock);
	comp->icem = icem;

	err = udp_register_helper(&comp->uh, sock, icem->layer,
				  NULL, helper_recv_handler, comp);
	if (err)
		goto out;

	err = udp_local_get(comp->sock, &local);
	if (err)
		goto out;

	comp->lport = sa_port(&local);

 out:
	if (err)
		mem_deref(comp);
	else
		*cp = comp;

	return err;
}
Esempio n. 7
0
/**
 * Allocate a TURN Client
 *
 * @param turncp    Pointer to allocated TURN Client
 * @param conf      Optional STUN Configuration
 * @param proto     Transport Protocol
 * @param sock      Transport socket
 * @param layer     Transport layer
 * @param srv       TURN Server IP-address
 * @param username  Authentication username
 * @param password  Authentication password
 * @param lifetime  Allocate lifetime in [seconds]
 * @param th        TURN handler
 * @param arg       Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int turnc_alloc(struct turnc **turncp, const struct stun_conf *conf, int proto,
		void *sock, int layer, const struct sa *srv,
		const char *username, const char *password,
		uint32_t lifetime, turnc_h *th, void *arg)
{
	struct turnc *turnc;
	int err;

	if (!turncp || !sock || !srv || !username || !password || !th)
		return EINVAL;

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

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

	err = str_dup(&turnc->username, username);
	if (err)
		goto out;

	err = str_dup(&turnc->password, password);
	if (err)
		goto out;

	err = turnc_perm_hash_alloc(&turnc->perms, PERM_HASH_SIZE);
	if (err)
		goto out;

	err =  turnc_chan_hash_alloc(&turnc->chans, CHAN_HASH_SIZE);
	if (err)
		goto out;

	tmr_init(&turnc->tmr);
	turnc->proto = proto;
	turnc->sock = mem_ref(sock);
	turnc->psrv = *srv;
	turnc->srv = *srv;
	turnc->lifetime = lifetime;
	turnc->th = th;
	turnc->arg = arg;

	switch (proto) {

	case IPPROTO_UDP:
		err = udp_register_helper(&turnc->uh, sock, layer,
					  udp_send_handler, udp_recv_handler,
					  turnc);
		break;

	default:
		err = 0;
		break;
	}

	if (err)
		goto out;

	err = allocate_request(turnc);
	if (err)
		goto out;

 out:
	if (err)
		mem_deref(turnc);
	else
		*turncp = turnc;

	return err;
}
Esempio n. 8
0
File: lcand.c Progetto: alfredh/rew
/*
 * you can call this at any time
 *
 * @param addr HOST:     SA_ADDR portion is used
 *             non-HOST: SA_ADDR + SA_PORT portion is used
 *
 * @param base_addr  Optional
 * @param rel_addr   Optional
 *
 * @param layer  mandatory for HOST and RELAY candidates
 */
int trice_lcand_add(struct ice_lcand **lcandp, struct trice *icem,
		    unsigned compid, int proto,
		    uint32_t prio, const struct sa *addr,
		    const struct sa *base_addr,
		    enum ice_cand_type type, const struct sa *rel_addr,
		    enum ice_tcptype tcptype,
		    void *sock, int layer)
{
	struct ice_lcand *lcand;
	int err = 0;

	if (!icem || !compid || !proto || !addr)
		return EINVAL;

	if (!sa_isset(addr, SA_ADDR)) {
		DEBUG_WARNING("lcand_add: SA_ADDR is not set\n");
		return EINVAL;
	}
	if (type != ICE_CAND_TYPE_HOST) {
		if (!sa_isset(addr, SA_PORT)) {
			DEBUG_WARNING("lcand_add: %s: SA_PORT"
				      " must be set (%J)\n",
				      ice_cand_type2name(type), addr);
			return EINVAL;
		}
	}

	/* lookup candidate, replace if PRIO is higher */

	/* TODO: dont look up TCP-ACTIVE types for now (port is zero) */
	if (proto == IPPROTO_UDP) {

		lcand = trice_lcand_find(icem, -1, compid, proto, addr);
		if (lcand) {
			trice_printf(icem,
				    "add_local[%s.%J] --"
				    " candidate already exists"
				    " (%H)\n",
				    ice_cand_type2name(type), addr,
				    trice_cand_print, lcand);

			if (prio > lcand->attr.prio)
				lcand = mem_deref(lcand);
			else {
				goto out;
			}
		}
	}

	err = trice_add_lcandidate(&lcand, icem, &icem->lcandl, compid, NULL,
				   proto, prio, addr, base_addr,
				   type, rel_addr, tcptype);
	if (err)
		return err;

	if (type == ICE_CAND_TYPE_HOST) {

		switch (proto) {

		case IPPROTO_UDP:
			if (sock) {
				struct sa laddr;

				lcand->us = mem_ref(sock);

				err = udp_local_get(lcand->us,
						    &laddr);
				if (err)
					goto out;

				lcand->attr.addr = *addr;
				sa_set_port(&lcand->attr.addr,
					    sa_port(&laddr));
			}
			else {
				err = udp_listen(&lcand->us, addr,
						 dummy_udp_recv, lcand);
				if (err)
					goto out;

				err = udp_local_get(lcand->us,
						    &lcand->attr.addr);
				if (err)
					goto out;
			}

			err = udp_register_helper(&lcand->uh, lcand->us,
						  layer,
						  udp_helper_send_handler,
						  udp_helper_recv_handler,
						  lcand);
			if (err)
				goto out;
			break;

		case IPPROTO_TCP:

			/* TCP-transport has 3 variants:
			   active, passive, so */

			if (lcand->attr.tcptype == ICE_TCP_ACTIVE) {

				/* the port MUST be set to 9 (i.e., Discard) */
				/*sa_set_port(&lcand->attr.addr, 9); */
			}
			else if (lcand->attr.tcptype == ICE_TCP_PASSIVE ||
				 lcand->attr.tcptype == ICE_TCP_SO) {

				err = tcp_listen(&lcand->ts, addr,
						 tcp_conn_handler, lcand);
				if (err)
					goto out;
				err = tcp_local_get(lcand->ts,
						    &lcand->attr.addr);
				if (err)
					goto out;
			}
			else {
				err = EPROTONOSUPPORT;
				goto out;
			}
			break;

		default:
			err = EPROTONOSUPPORT;
			goto out;
		}
	}
	else if (type == ICE_CAND_TYPE_RELAY) {

		switch (proto) {

		case IPPROTO_UDP:

			if (sock) {
				lcand->us = mem_ref(sock);
			}
			else {
				err = udp_listen(&lcand->us, NULL,
						 dummy_udp_recv, lcand);
				if (err)
					goto out;
			}

			err = udp_register_helper(&lcand->uh, lcand->us,
						  layer,
						  udp_helper_send_handler,
						  udp_helper_recv_handler,
						  lcand);
			if (err)
				goto out;

			break;

		default:
			err = EPROTONOSUPPORT;
			goto out;
		}
	}
	else if (type == ICE_CAND_TYPE_SRFLX ||
		 type == ICE_CAND_TYPE_PRFLX) {

		/* Special case for SRFLX UDP candidates, if he has
		 * its own UDP-socket that can be used.
		 */
		if (proto == IPPROTO_UDP && sock) {

			lcand->us = mem_ref(sock);

			err = udp_register_helper(&lcand->uh, lcand->us,
						  layer,
						  udp_helper_send_handler,
						  udp_helper_recv_handler,
						  lcand);
			if (err)
				goto out;
		}
	}

	lcand->layer = layer;

	/* pair this local-candidate with all existing remote-candidates */
	err = trice_candpair_with_local(icem, lcand);
	if (err)
		goto out;

	/* new pair -- refresh the checklist timer */
	trice_checklist_refresh(icem);

 out:
	if (err)
		mem_deref(lcand);
	else if (lcandp)
		*lcandp = lcand;

	return err;
}
Esempio n. 9
0
static void turnc_handler(int err, uint16_t scode, const char *reason,
			  const struct sa *relay_addr,
			  const struct sa *mapped_addr,
			  const struct stun_msg *msg,
			  void *arg)
{
	struct candidate *cand = arg;
	struct ice_lcand *lcand_relay=0, *lcand_srflx=0, *base = cand->base;
	uint32_t prio;

	if (err || scode) {
		re_printf("TURN client error: %u %s (%m)\n",
			  scode, reason, err);
		goto out;
	}

	/* check if the relayed address is of the same Address Family
	 * as the base candidate */
	if (sa_af(relay_addr) != sa_af(&base->attr.addr)) {
		re_printf("could not use RELAY address (AF mismatch)\n");
		goto out;
	}

	if (stun_msg_method(msg) == STUN_METHOD_ALLOCATE) {
		re_printf("TURN allocation okay (turn-proto=%s)\n",
			  net_proto2name(cand->turn_proto));
		cand->turn_ok = true;
	}

	/* RELAY */

	re_printf("adding RELAY candidate %s.%J\n",
		  net_proto2name(base->attr.proto), relay_addr);

	prio = calc_prio(ICE_CAND_TYPE_RELAY, base->attr.proto,
			 base->attr.tcptype, sa_af(&base->attr.addr),
			 cand->turn_proto);

	err = trice_lcand_add(&lcand_relay, base->icem,
			      base->attr.compid,
			      base->attr.proto, prio, relay_addr,
			      relay_addr, ICE_CAND_TYPE_RELAY,
			      mapped_addr,
			      base->attr.tcptype, base->us,
			      LAYER_ICE);
	if (err) {
		re_fprintf(stderr, "failed to add RELAY candidate (%m)\n",
			   err);
		goto out;
	}

	if (cand->turn_proto == IPPROTO_TCP) {

		/* NOTE: this is needed to snap up outgoing UDP-packets */

		err = udp_register_helper(&cand->uh_turntcp,
					  lcand_relay->us,
					  LAYER_TURN,
					  turntcp_send_handler,
					  NULL,
					  cand);
		if (err) {
			re_printf("helper error\n");
			goto out;
		}
	}

	/* SRFLX */
	if (cand->turn_proto == base->attr.proto) {
		re_printf("adding SRFLX candidate %s.%J\n",
			  net_proto2name(base->attr.proto), mapped_addr);

		prio = calc_prio(ICE_CAND_TYPE_SRFLX, base->attr.proto,
				 base->attr.tcptype, sa_af(&base->attr.addr),
				 base->attr.proto);

		err = trice_lcand_add(&lcand_srflx, base->icem,
				      base->attr.compid,
				      base->attr.proto, prio,
				      mapped_addr, &base->attr.addr,
				      ICE_CAND_TYPE_SRFLX,
				      &base->attr.addr,
				      base->attr.tcptype,
				      NULL, LAYER_ICE);
		if (err) {
			re_fprintf(stderr, "failed to add SRFLX"
				   " candidate (%m)\n",
				   err);
			goto out;
		}
	}

	err = control_send_message(cand->ag->cli,
				   "a=candidate:%H\r\n"
				   "a=candidate:%H\r\n"
				   ,
				   ice_cand_attr_encode, &lcand_relay->attr,
				   ice_cand_attr_encode,
				   lcand_srflx ? &lcand_srflx->attr : 0);
	if (err)
		goto out;

	candidate_add_permissions(cand);

 out:
	candidate_done(cand);
}
Esempio n. 10
0
static int alloc(struct menc_media **stp, struct menc_sess *sess,
		 struct rtp_sock *rtp,
		 int proto, void *rtpsock, void *rtcpsock,
		 struct sdp_media *sdpm)
{
	struct menc_st *st;
	const char *rattr = NULL;
	int layer = 10; /* above zero */
	int err = 0;
	bool mux = (rtpsock == rtcpsock);
	(void)sess;
	(void)rtp;

	if (!stp || !sdpm)
		return EINVAL;
	if (proto != IPPROTO_UDP)
		return EPROTONOSUPPORT;

	st = (struct menc_st *)*stp;
	if (!st) {

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

		st->sdpm = mem_ref(sdpm);

		err = sdp_media_set_alt_protos(st->sdpm, 4,
					       "RTP/AVP",
					       "RTP/AVPF",
					       "RTP/SAVP",
					       "RTP/SAVPF");
		if (err)
			goto out;

		if (rtpsock) {
			st->rtpsock = mem_ref(rtpsock);
			err |= udp_register_helper(&st->uh_rtp, rtpsock,
						   layer, send_handler,
						   recv_handler, st);
		}
		if (rtcpsock && !mux) {
			st->rtcpsock = mem_ref(rtcpsock);
			err |= udp_register_helper(&st->uh_rtcp, rtcpsock,
						   layer, send_handler,
						   recv_handler, st);
		}
		if (err)
			goto out;

		/* set our preferred crypto-suite */
		err |= str_dup(&st->crypto_suite, aes_cm_128_hmac_sha1_80);
		if (err)
			goto out;

		err = setup_srtp(st);
		if (err)
			goto out;
	}

	/* SDP handling */

	if (sdp_media_rattr(st->sdpm, "crypto")) {

		rattr = sdp_media_rattr_apply(st->sdpm, "crypto",
					      sdp_attr_handler, st);
		if (!rattr) {
			DEBUG_WARNING("no valid a=crypto attribute from"
				      " remote peer\n");
		}
	}

	if (!rattr)
		err = sdp_enc(st, sdpm, 0, st->crypto_suite);

 out:
	if (err)
		mem_deref(st);
	else
		*stp = (struct menc_media *)st;

	return err;
}
Esempio n. 11
0
static int media_alloc(struct menc_media **stp, struct menc_sess *sess,
		 struct rtp_sock *rtp,
		 struct udp_sock *rtpsock, struct udp_sock *rtcpsock,
	         const struct sa *raddr_rtp,
	         const struct sa *raddr_rtcp,
		 struct sdp_media *sdpm)
{
	struct menc_st *st;
	const char *rattr = NULL;
	int layer = 10; /* above zero */
	int err = 0;
	bool mux = (rtpsock == rtcpsock);
	(void)sess;
	(void)rtp;
	(void)raddr_rtp;
	(void)raddr_rtcp;

	if (!stp || !sdpm || !sess)
		return EINVAL;

	st = (struct menc_st *)*stp;
	if (!st) {

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

		st->sess = sess;
		st->sdpm = mem_ref(sdpm);

		if (0 == str_cmp(sdp_media_proto(sdpm), "RTP/AVP")) {
			err = sdp_media_set_alt_protos(st->sdpm, 4,
						       "RTP/AVP",
						       "RTP/AVPF",
						       "RTP/SAVP",
						       "RTP/SAVPF");
			if (err)
				goto out;
		}

		if (rtpsock) {
			st->rtpsock = mem_ref(rtpsock);
			err |= udp_register_helper(&st->uh_rtp, rtpsock,
						   layer, send_handler,
						   recv_handler, st);
		}
		if (rtcpsock && !mux) {
			st->rtcpsock = mem_ref(rtcpsock);
			err |= udp_register_helper(&st->uh_rtcp, rtcpsock,
						   layer, send_handler,
						   recv_handler, st);
		}
		if (err)
			goto out;

		/* set our preferred crypto-suite */
		err |= str_dup(&st->crypto_suite, preferred_suite);
		if (err)
			goto out;

		rand_bytes(st->key_tx, sizeof(st->key_tx));
	}

	/* SDP handling */

	if (sdp_media_rport(sdpm))
		st->got_sdp = true;

	if (sdp_media_rattr(st->sdpm, "crypto")) {

		rattr = sdp_media_rattr_apply(st->sdpm, "crypto",
					      sdp_attr_handler, st);
		if (!rattr) {
			warning("srtp: no valid a=crypto attribute from"
				" remote peer\n");
		}
	}

	if (!rattr)
		err = sdp_enc(st, sdpm, 1, st->crypto_suite);

 out:
	if (err)
		mem_deref(st);
	else
		*stp = (struct menc_media *)st;

	return err;
}