예제 #1
0
파일: turn.c 프로젝트: alfredh/restunc
int turn_init(const char *username, const char *password,
	      const struct sa *peer, uint16_t loop_port)
{
	int err = 0;

	turnc.username = username;
	turnc.password = password;
	turnc.peer = peer;

	err = udp_listen(&turnc.us, NULL, udp_recv, NULL);
	if (err) {
		DEBUG_WARNING("udp_listen: %m\n", err);
		goto out;
	}

	if (loop_port) {
		struct sa local;

		sa_set_in(&local, 0, loop_port);

		err = udp_listen(&turnc.loop_us, &local, udp_loop_recv, NULL);
		if (err) {
			DEBUG_WARNING("udp_listen: %m\n", err);
			goto out;
		}
		(void)re_printf("Local loop on port %u\n", loop_port);
	}

 out:
	return err;
}
예제 #2
0
파일: http.c 프로젝트: muromec/rehttp
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;
}
예제 #3
0
/**
 * Handle incoming connects
 */
void tcp_sock::tcp_conn_handler()
{
	if (!ctc) {
		DEBUG_WARNING("conn handler: no pending socket\n");
	}

	TInetAddr ia;
	struct sa peer;
	ctc->iSocket.RemoteName(ia);
	sa_set_in(&peer, ia.Address(), ia.Port());

	DEBUG_INFO("conn handler: incoming connect from %J\n", &peer);

	ctc->blank = false;

	/*
	 * Application handler might call tcp_accept(), tcp_reject()
	 * or do nothing
	 */
	if (connh)
		connh(&peer, arg);

	if (ctc) {
		DEBUG_INFO("delete ctc\n");
		delete ctc;
		ctc = NULL;
	}

	/* Create blank socket for the next incoming CONNECT */
	blank_socket();

	cts->Accepting();
}
예제 #4
0
static void dns_handler(int err, const struct dnshdr *hdr, struct list *ansl,
			struct list *authl, struct list *addl, void *arg)
{
	struct rst *rst = arg;
	struct dnsrr *rr;
	struct sa srv;

	(void)err;
	(void)hdr;
	(void)authl;
	(void)addl;

	rr = dns_rrlist_find(ansl, rst->host, DNS_TYPE_A, DNS_CLASS_IN, true);
	if (!rr) {
		re_printf("rst: unable to resolve: %s\n", rst->host);
		tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst);
		return;
	}

	sa_set_in(&srv, rr->rdata.a.addr, rst->port);

	err = tcp_connect(&rst->tc, &srv, estab_handler, recv_handler,
			  close_handler, rst);
	if (err) {
		re_printf("rst: tcp connect error: %m\n", err);
		tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst);
		return;
	}
}
예제 #5
0
/**
 * 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;
}
예제 #6
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;
}
예제 #7
0
int udp_sock::local_get(struct sa *local) const
{
	TInetAddr ia;

	cus->iSocket.LocalName(ia);
	sa_set_in(local, ia.Address(), ia.Port());

	return 0;
}
예제 #8
0
int tcp_conn_peer_get(const struct tcp_conn *tc, struct sa *peer)
{
	if (!tc || !peer)
		return EINVAL;

	TInetAddr ia;
	tc->ctc->iSocket.RemoteName(ia);
	sa_set_in(peer, ia.Address(), ia.Port());

	return 0;
}
예제 #9
0
int tcp_conn_local_get(const struct tcp_conn *tc, struct sa *local)
{
	if (!tc || !local)
		return EINVAL;

	TInetAddr ia;
	tc->ctc->iSocket.LocalName(ia);
	sa_set_in(local, ia.Address(), ia.Port());

	return 0;
}
예제 #10
0
int tcp_sock_local_get(const struct tcp_sock *ts, struct sa *local)
{
	if (!ts || !local)
		return EINVAL;

	TInetAddr ia;
	ts->cts->iSocket.LocalName(ia);
	sa_set_in(local, ia.Address(), ia.Port());

	return 0;
}
예제 #11
0
void udp_sock::recv()
{
	struct mbuf *mb = mbuf_alloc(rx_presz + cus->iBufRx.Length());
	if (!mb)
		return;

	mb->pos += rx_presz;
	mb->end += rx_presz;

	(void)mbuf_write_mem(mb, (uint8_t *)cus->iBufRx.Ptr(),
			     cus->iBufRx.Length());
	mb->pos = rx_presz;

	struct sa src;
	sa_set_in(&src, cus->iSource.Address(), cus->iSource.Port());

	/* call helpers */
	struct le *le = list_head(&helpers);
	while (le) {
		struct udp_helper *uh;
		bool hdld;

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

		hdld = uh->recvh(&src, mb, uh->arg);

		if (hdld)
			goto out;
	}

	DEBUG_INFO("udp recv %d bytes from %J\n", cus->iBufRx.Length(), &src);

	cus->StartReceiving();

	rh(&src, mb, arg);

 out:
	mem_deref(mb);
}
예제 #12
0
/**
 * Get the IP address of the host
 *
 * @param af  Address Family
 * @param ip  Returned IP address
 *
 * @return 0 if success, otherwise errorcode
 */
int net_hostaddr(int af, struct sa *ip)
{
	char hostname[256];
	struct in_addr in;
	struct hostent *he;

	if (-1 == gethostname(hostname, sizeof(hostname)))
		return errno;

	he = gethostbyname(hostname);
	if (!he)
		return ENOENT;

	if (af != he->h_addrtype)
		return EAFNOSUPPORT;

	/* Get the first entry */
	memcpy(&in, he->h_addr_list[0], sizeof(in));
	sa_set_in(ip, ntohl(in.s_addr), 0);

	return 0;
}
예제 #13
0
파일: client.c 프로젝트: chk-jxcn/libre
static bool rr_handler(struct dnsrr *rr, void *arg)
{
	struct http_req *req = arg;

	if (req->srvc >= ARRAY_SIZE(req->srvv))
		return true;

	switch (rr->type) {

	case DNS_TYPE_A:
		sa_set_in(&req->srvv[req->srvc++], rr->rdata.a.addr,
			  req->port);
		break;

	case DNS_TYPE_AAAA:
		sa_set_in6(&req->srvv[req->srvc++], rr->rdata.aaaa.addr,
			   req->port);
		break;
	}

	return false;
}
예제 #14
0
파일: natpmp.c 프로젝트: GGGO/baresip
static void extaddr_handler(int err, const struct natpmp_resp *resp, void *arg)
{
	(void)arg;

	if (err) {
		warning("natpmp: external address ERROR: %m\n", err);
		return;
	}

	if (resp->result != NATPMP_SUCCESS) {
		warning("natpmp: external address failed"
			" with result code: %d\n", resp->result);
		return;
	}

	if (resp->op != NATPMP_OP_EXTERNAL)
		return;

	sa_set_in(&natpmp_extaddr, resp->u.ext_addr, 0);

	info("natpmp: discovered External address: %j\n", &natpmp_extaddr);
}
예제 #15
0
static void a_handler(int err, const struct dnshdr *hdr, struct list *ansl,
		      struct list *authl, struct list *addl, void *arg)
{
	struct stun_dns *dns = arg;
	struct dnsrr *rr;

	(void)hdr;
	(void)authl;
	(void)addl;

	/* Find A answers */
	rr = dns_rrlist_find(ansl, NULL, DNS_TYPE_A, DNS_CLASS_IN, false);
	if (!rr) {
		err = err ? err : EDESTADDRREQ;
		goto out;
	}

	sa_set_in(&dns->srv, rr->rdata.a.addr, sa_port(&dns->srv));

	DEBUG_INFO("A answer: %j\n", &dns->srv);

 out:
	resolved(dns, err);
}
예제 #16
0
/**
 * 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;
}
예제 #17
0
/**
 * Do a DNS Discovery of a STUN Server
 *
 * @param dnsp    Pointer to allocated DNS Discovery object
 * @param dnsc    DNS Client
 * @param service Name of service to discover (e.g. "stun")
 * @param proto   Transport protocol (e.g. "udp")
 * @param af      Preferred Address Family
 * @param domain  Domain name or IP address of STUN server
 * @param port    Port number (if 0 do SRV lookup)
 * @param dnsh    DNS Response handler
 * @param arg     Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int stun_server_discover(struct stun_dns **dnsp, struct dnsc *dnsc,
			 const char *service, const char *proto,
			 int af, const char *domain, uint16_t port,
			 stun_dns_h *dnsh, void *arg)
{
	struct stun_dns *dns;
	int err;

	if (!dnsp || !service || !proto || !domain || !domain[0] || !dnsh)
		return EINVAL;

	dns = mem_zalloc(sizeof(*dns), dnsdisc_destructor);
	if (!dns)
		return ENOMEM;

	dns->port = service[strlen(service)-1] == 's' ? STUNS_PORT : STUN_PORT;
	dns->dnsh = dnsh;
	dns->arg  = arg;
	dns->dnsc = dnsc;
	dns->af   = af;

	/* Numeric IP address - no lookup */
	if (0 == sa_set_str(&dns->srv, domain, port ? port : dns->port)) {

		DEBUG_INFO("IP (%s)\n", domain);

		resolved(dns, 0);
		err = 0;
		goto out; /* free now */
	}
	/* Port specified - use AAAA or A lookup */
	else if (port) {
		sa_set_in(&dns->srv, 0, port);
		DEBUG_INFO("resolving A query: (%s)\n", domain);

		err = a_or_aaaa_query(dns, domain);
		if (err) {
			DEBUG_WARNING("%s: A/AAAA lookup failed (%m)\n",
				      domain, err);
			goto out;
		}
	}
	/* SRV lookup */
	else {
		char q[256];
		str_ncpy(dns->domain, domain, sizeof(dns->domain));
		(void)re_snprintf(q, sizeof(q), "_%s._%s.%s", service, proto,
				  domain);
		DEBUG_INFO("resolving SRV query: (%s)\n", q);
		err = dnsc_query(&dns->dq, dnsc, q, DNS_TYPE_SRV, DNS_CLASS_IN,
				 true, srv_handler, dns);
		if (err) {
			DEBUG_WARNING("%s: SRV lookup failed (%m)\n", q, err);
			goto out;
		}
	}

	*dnsp = dns;

	return 0;

 out:
	mem_deref(dns);
	return err;
}
예제 #18
0
static void srv_handler(int err, const struct dnshdr *hdr, struct list *ansl,
			struct list *authl, struct list *addl, void *arg)
{
	struct stun_dns *dns = arg;
	struct dnsrr *rr, *arr;

	(void)hdr;
	(void)authl;

	dns_rrlist_sort(ansl, DNS_TYPE_SRV);

	/* Find SRV answers */
	rr = dns_rrlist_find(ansl, NULL, DNS_TYPE_SRV, DNS_CLASS_IN, false);
	if (!rr) {
		DEBUG_INFO("no SRV entry, trying A lookup on \"%s\"\n",
			   dns->domain);

		sa_set_in(&dns->srv, 0, dns->port);

		err = a_or_aaaa_query(dns, dns->domain);
		if (err)
			goto out;

		return;
	}

	DEBUG_INFO("SRV answer: %s:%u\n", rr->rdata.srv.target,
		   rr->rdata.srv.port);

	/* Look for Additional information */
	switch (dns->af) {

	case AF_INET:
		arr = dns_rrlist_find(addl, rr->rdata.srv.target,
				      DNS_TYPE_A, DNS_CLASS_IN, true);
		if (arr) {
			sa_set_in(&dns->srv, arr->rdata.a.addr,
				  rr->rdata.srv.port);
			DEBUG_INFO("additional A: %j\n", &dns->srv);
			goto out;
		}
		break;

#ifdef HAVE_INET6
	case AF_INET6:
		arr = dns_rrlist_find(addl, rr->rdata.srv.target,
				      DNS_TYPE_AAAA, DNS_CLASS_IN, true);
		if (arr) {
			sa_set_in6(&dns->srv, arr->rdata.aaaa.addr,
				  rr->rdata.srv.port);
			DEBUG_INFO("additional AAAA: %j\n", &dns->srv);
			goto out;
		}
		break;
#endif
	}

	sa_set_in(&dns->srv, 0, rr->rdata.srv.port);

	err = a_or_aaaa_query(dns, rr->rdata.srv.target);
	if (err) {
		DEBUG_WARNING("SRV: A lookup failed (%m)\n", err);
		goto out;
	}

	DEBUG_INFO("SRV handler: doing A/AAAA lookup..\n");

	return;

 out:
	resolved(dns, err);
}