Beispiel #1
0
void write_auth(struct request *req, struct mbuf *mb)
{
    int err;
    struct realm *realm;
    uint8_t digest[MD5_SIZE];
    uint64_t cnonce;

    if(!req->auth)
        return;

    realm = req->auth;
    cnonce = rand_u64();

    err = mkdigest(digest, realm, req->meth, req->path, cnonce);

    err |= mbuf_write_str(mb, "Authorization: ");

    err |= mbuf_printf(mb, "Digest username=\"%s\"", realm->user);
    err |= mbuf_printf(mb, ", realm=\"%s\"", realm->realm);
    err |= mbuf_printf(mb, ", nonce=\"%s\"", realm->nonce);
    err |= mbuf_printf(mb, ", uri=\"%s\"", req->path);
    err |= mbuf_printf(mb, ", response=\"%w\"",
            digest, sizeof(digest));

    if (realm->opaque)
        err |= mbuf_printf(mb, ", opaque=\"%s\"", realm->opaque);

    if (realm->qop) {
        err |= mbuf_printf(mb, ", cnonce=\"%016llx\"", cnonce);
	err |= mbuf_write_str(mb, ", qop=auth");
    	err |= mbuf_printf(mb, ", nc=%08x", realm->nc);
    }
    ++realm->nc;
    err |= mbuf_write_str(mb, "\r\n");
}
Beispiel #2
0
int sip_auth_encode(struct mbuf *mb, struct sip_auth *auth, const char *met,
		    const char *uri)
{
	struct le *le;
	int err = 0;

	if (!mb || !auth || !met || !uri)
		return EINVAL;

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

		const uint64_t cnonce = rand_u64();
		struct realm *realm = le->data;
		uint8_t digest[MD5_SIZE];

		err = mkdigest(digest, realm, met, uri, cnonce);
		if (err)
			break;

		switch (realm->hdr) {

		case SIP_HDR_WWW_AUTHENTICATE:
			err = mbuf_write_str(mb, "Authorization: ");
			break;

		case SIP_HDR_PROXY_AUTHENTICATE:
			err = mbuf_write_str(mb, "Proxy-Authorization: ");
			break;

		default:
			continue;
		}

		err |= mbuf_printf(mb, "Digest username=\"%s\"", realm->user);
		err |= mbuf_printf(mb, ", realm=\"%s\"", realm->realm);
		err |= mbuf_printf(mb, ", nonce=\"%s\"", realm->nonce);
		err |= mbuf_printf(mb, ", uri=\"%s\"", uri);
		err |= mbuf_printf(mb, ", response=\"%w\"",
				   digest, sizeof(digest));

		if (realm->opaque)
			err |= mbuf_printf(mb, ", opaque=\"%s\"",
					   realm->opaque);

		if (realm->qop) {
			err |= mbuf_printf(mb, ", cnonce=\"%016llx\"", cnonce);
			err |= mbuf_write_str(mb, ", qop=auth");
			err |= mbuf_printf(mb, ", nc=%08x", realm->nc);
		}

		++realm->nc;

		err |= mbuf_write_str(mb, "\r\n");
		if (err)
			break;
	}

	return err;
}
Beispiel #3
0
static void tcp_estab_handler(void *arg)
{
    DEBUG_INFO("connection established\n");
    int ok;
    struct request * request = arg;
    struct mbuf *mb;

    char CN[256];

    if(request->secure) {
	ok = tls_verify_cert(request->ssl, CN, sizeof(CN));
	if(ok!=0)
            goto fail;

	DEBUG_INFO("https CN %s\n", CN);

	ok = strcmp(request->host, CN);
	if(ok!=0)
	    goto fail;
    }

    mb = mbuf_alloc(1024);
    mbuf_printf(mb, "%s %s HTTP/1.1\r\n", request->meth, request->path);
    mbuf_printf(mb, "Host: %s\r\n", request->host);
    write_auth(request, mb);
    mbuf_write_str(mb, "Connection: close\r\n");

    hash_apply(request->hdrht, hdr_write, mb);
    hash_flush(request->hdrht);

    if(request->post) {
        request->post->pos = 0;
        mbuf_printf(mb, "Content-Length: %d\r\n",
            mbuf_get_left(request->post));

	if(request->form)
            mbuf_printf(mb, "Content-Type: "
	        "application/x-www-form-urlencoded\r\n");
        mbuf_printf(mb, "\r\n");
        mbuf_write_mem(mb, mbuf_buf(request->post),
			   mbuf_get_left(request->post));
    } else {
        mbuf_write_str(mb, "\r\n");
    }

    mb->pos = 0;

    tcp_send(request->tcp, mb);
    mem_deref(mb);

    return;

fail:
    DEBUG_WARNING("ssl fail %p %d\n", request->app->tls, ok);
}
Beispiel #4
0
static void server_info(struct mbuf *mb)
{
	const uint32_t uptime = (uint32_t)(time(NULL) - stg.start);

	mbuf_write_str(mb, "<table>\n");
	mbuf_write_str(mb,
		       " <tr><td>Version:</td><td>" VERSION "</td></tr>\n");
	mbuf_write_str(mb,
		       " <tr><td>Built:</td><td>" __DATE__ " " __TIME__
		       "</td></tr>\n");
	mbuf_printf(mb, " <tr><td>Uptime:</td><td>%H</td></tr>\n",
		    fmt_human_time, &uptime);
	mbuf_write_str(mb, "</table>\n");
}
TEST(chunk, decode_message)
{
	struct mbuf *mb_chunked = mbuf_alloc(1024);
	struct mbuf *mb_data = mbuf_alloc(1024);
	int err = 0;

	ASSERT_TRUE(mb_chunked != NULL);
	ASSERT_TRUE(mb_data != NULL);

	mbuf_write_str(mb_chunked, encoded_data);
	mb_chunked->pos = 0;

	/* decode all chunks */
	for (int i=0; i<16; i++) {
		uint8_t *p;
		size_t n;

		err = chunk_decode(&p, &n, mb_chunked);
		if (err)
			break;

		if (n == 0)
			break;

		err = mbuf_write_mem(mb_data, p, n);
		if (err)
			break;
	}

	ASSERT_EQ(str_len(decoded_data), mb_data->end);
	ASSERT_TRUE(0 == memcmp(decoded_data, mb_data->buf, mb_data->end));

	mem_deref(mb_chunked);
	mem_deref(mb_data);
}
Beispiel #6
0
static int output_handler(const char *str)
{
	struct mbuf *mb;
	int err = 0;

	if (!str)
		return EINVAL;

	mb = mbuf_alloc(256);
	if (!mb)
		return ENOMEM;

	mbuf_write_str(mb, str);

	if (sa_isset(&cons->udp_peer, SA_ALL)) {
		mb->pos = 0;
		err |= udp_send(cons->us, &cons->udp_peer, mb);
	}

	if (cons->tc) {
		mb->pos = 0;
		err |= tcp_send(cons->tc, mb);
	}

	mem_deref(mb);

	return err;
}
/**
 * Send a SIP request with formatted arguments
 *
 * @param reqp     Pointer to allocated SIP request object
 * @param sip      SIP Stack
 * @param stateful Stateful client transaction
 * @param met      Null-terminated SIP Method string
 * @param uri      Null-terminated Request URI string
 * @param route    Next hop route URI (optional)
 * @param auth     SIP authentication state
 * @param sendh    Send handler
 * @param resph    Response handler
 * @param arg      Handler argument
 * @param fmt      Formatted SIP headers
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_requestf(struct sip_request **reqp, struct sip *sip, bool stateful,
		 const char *met, const char *uri, const struct uri *route,
		 struct sip_auth *auth, sip_send_h *sendh, sip_resp_h *resph,
		 void *arg, const char *fmt, ...)
{
	struct uri lroute;
	struct mbuf *mb;
	va_list ap;
	int err;

	if (!sip || !met || !uri || !fmt)
		return EINVAL;

	if (!route) {
		struct pl uripl;

		pl_set_str(&uripl, uri);

		err = uri_decode(&lroute, &uripl);
		if (err)
			return err;

		route = &lroute;
	}

	mb = mbuf_alloc(2048);
	if (!mb)
		return ENOMEM;

	err = mbuf_write_str(mb, "Max-Forwards: 70\r\n");

	if (auth)
		err |= sip_auth_encode(mb, auth, met, uri);

	if (err)
		goto out;

	va_start(ap, fmt);
	err = mbuf_vprintf(mb, fmt, ap);
	va_end(ap);

	if (err)
		goto out;

	mb->pos = 0;

	err = sip_request(reqp, sip, stateful, met, -1, uri, -1, route, mb,
			  sendh, resph, arg);
	if (err)
		goto out;

 out:
	mem_deref(mb);

	return err;
}
Beispiel #8
0
/**
 * Test parsing of various SDP messages from various vendors
 */
int test_sdp_parse(void)
{
	struct sdp_session *sess = NULL;
	struct sdp_media *audio;
	struct mbuf *mb;
	struct sa laddr;
	uint32_t i;
	int err;

	mb = mbuf_alloc(2048);
	if (!mb)
		return ENOMEM;

	sa_init(&laddr, AF_INET);

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

		sess = mem_deref(sess);

		err = sdp_session_alloc(&sess, &laddr);
		if (err)
			goto out;

		err = sdp_media_add(&audio, sess, sdp_media_audio, 5004,
				    sdp_proto_rtpavp);
		if (err)
			goto out;

		err = sdp_format_add(NULL, audio, false, ref_pt, ref_cname,
				     ref_srate, 1, NULL, NULL, NULL, false,
				     NULL);
		if (err)
			goto out;

		err = sdp_format_add(NULL, audio, false, "8", "PCMA", 8000, 1,
				     NULL, NULL, NULL, false, NULL);
		if (err)
			goto out;

		mbuf_rewind(mb);
		(void)mbuf_write_str(mb, msgs[i]);
		mb->pos = 0;

		err = sdp_decode(sess, mb, true);
		if (err)
			goto out;
	}

 out:
	mem_deref(sess);
	mem_deref(mb);

	return err;
}
Beispiel #9
0
static void httpd_handler(const struct pl *uri, struct mbuf *mb)
{
	struct pl cmd, params, r;
	uint32_t refresh = 0;

	if (re_regex(uri->p, uri->l, "/[^?]*[^]*", &cmd, &params))
		return;

	if (!re_regex(params.p, params.l, "[?&]1r=[0-9]+", NULL, &r))
		refresh = pl_u32(&r);

	mbuf_write_str(mb, "<html>\n<head>\n");
	mbuf_write_str(mb, " <title>Restund Server Status</title>\n");

	if (refresh)
		mbuf_printf(mb,
			    " <meta http-equiv=\"refresh\" content=\"%u\">\n",
			    refresh);

	mbuf_write_str(mb, "</head>\n<body>\n");
	mbuf_write_str(mb, "<h2>Restund Server Status</h2>\n");
	server_info(mb);
	mbuf_write_str(mb, "<hr size=\"1\"/>\n<pre>\n");
	restund_cmd(&cmd, mb);
	mbuf_write_str(mb, "</pre>\n</body>\n</html>\n");
}
Beispiel #10
0
static int request_copy(struct mbuf **mbp, struct sip_ctrans *ct,
			const char *met, const struct sip_msg *resp)
{
	struct mbuf *mb;
	int err;

	if (!ct->req) {
		err = sip_msg_decode(&ct->req, ct->mb);
		if (err)
			return err;
	}

	mb = mbuf_alloc(1024);
	if (!mb)
		return ENOMEM;

	err  = mbuf_printf(mb, "%s %r SIP/2.0\r\n", met, &ct->req->ruri);
	err |= mbuf_printf(mb, "Via: %r\r\n", &ct->req->via.val);
	err |= mbuf_write_str(mb, "Max-Forwards: 70\r\n");
	err |= sip_msg_hdr_apply(ct->req, true, SIP_HDR_ROUTE,
				 route_handler, mb) ? ENOMEM : 0;
	err |= mbuf_printf(mb, "To: %r\r\n",
			   resp ? &resp->to.val : &ct->req->to.val);
	err |= mbuf_printf(mb, "From: %r\r\n", &ct->req->from.val);
	err |= mbuf_printf(mb, "Call-ID: %r\r\n", &ct->req->callid);
	err |= mbuf_printf(mb, "CSeq: %u %s\r\n", ct->req->cseq.num, met);
	if (ct->sip->software)
		err |= mbuf_printf(mb, "User-Agent: %s\r\n",ct->sip->software);
	err |= mbuf_write_str(mb, "Content-Length: 0\r\n\r\n");

	mb->pos = 0;

	if (err)
		mem_deref(mb);
	else
		*mbp = mb;

	return err;
}
TEST(chunk, decode_too_short)
{
	struct mbuf *mb_chunked = mbuf_alloc(1024);
	int err = 0;

	mbuf_write_str(mb_chunked, "3\r\nab");
	mb_chunked->pos = 0;

	err = chunk_decode(NULL, NULL, mb_chunked);
	ASSERT_EQ(EBADMSG, err);

	mem_deref(mb_chunked);
}
TEST(chunk, decode_incomplete_header)
{
	struct mbuf *mb = mbuf_alloc(1024);
	int err = 0;

	mbuf_write_str(mb, "c8"); /* the CRLF is missing here */
	mb->pos = 0;

	err = chunk_decode(NULL, NULL, mb);
	ASSERT_EQ(EBADMSG, err);

	mem_deref(mb);
}
TEST(chunk, decode_invalid_header)
{
	struct mbuf *mb = mbuf_alloc(1024);
	int err = 0;

	mbuf_write_str(mb, "alfred\r\n");
	mb->pos = 0;

	err = chunk_decode(NULL, NULL, mb);
	ASSERT_EQ(EBADMSG, err);

	mem_deref(mb);
}
Beispiel #14
0
/**
 * Send a SIP dialog request with formatted arguments
 *
 * @param reqp     Pointer to allocated SIP request object
 * @param sip      SIP Stack
 * @param stateful Stateful client transaction
 * @param met      Null-terminated SIP Method string
 * @param dlg      SIP Dialog state
 * @param cseq     CSeq number
 * @param auth     SIP authentication state
 * @param sendh    Send handler
 * @param resph    Response handler
 * @param arg      Handler argument
 * @param fmt      Formatted SIP headers
 *
 * @return 0 if success, otherwise errorcode
 */
int sip_drequestf(struct sip_request **reqp, struct sip *sip, bool stateful,
		  const char *met, struct sip_dialog *dlg, uint32_t cseq,
		  struct sip_auth *auth, sip_send_h *sendh, sip_resp_h *resph,
		  void *arg, const char *fmt, ...)
{
	struct mbuf *mb;
	va_list ap;
	int err;

	if (!sip || !met || !dlg || !fmt)
		return EINVAL;

	mb = mbuf_alloc(2048);
	if (!mb)
		return ENOMEM;

	err = mbuf_write_str(mb, "Max-Forwards: 70\r\n");

	if (auth)
		err |= sip_auth_encode(mb, auth, met, sip_dialog_uri(dlg));

	err |= sip_dialog_encode(mb, dlg, cseq, met);

	if (sip->software)
		err |= mbuf_printf(mb, "User-Agent: %s\r\n", sip->software);

	if (err)
		goto out;

	va_start(ap, fmt);
	err = mbuf_vprintf(mb, fmt, ap);
	va_end(ap);

	if (err)
		goto out;

	mb->pos = 0;

	err = sip_request(reqp, sip, stateful, met, -1, sip_dialog_uri(dlg),
			  -1, sip_dialog_route(dlg), mb, sendh, resph, arg);
	if (err)
		goto out;

 out:
	mem_deref(mb);

	return err;
}
Beispiel #15
0
static int send_data(struct udp_sock *us, const struct sa *peer,
		     const char *data)
{
	struct mbuf *mb = mbuf_alloc(strlen(data) + 1);
	int err;
	if (!mb)
		return ENOMEM;

	(void)mbuf_write_str(mb, data);
	mb->pos = 0;

	err = udp_send(us, peer, mb);

	mem_deref(mb);

	return err;
}
Beispiel #16
0
static int uri_complete(struct ua *ua, struct mbuf *buf, const char *uri)
{
	size_t len;
	int err = 0;

	/* Skip initial whitespace */
	while (isspace(*uri))
		++uri;

	len = str_len(uri);

	/* Append sip: scheme if missing */
	if (0 != re_regex(uri, len, "sip:"))
		err |= mbuf_printf(buf, "sip:");

	err |= mbuf_write_str(buf, uri);

	/* Append domain if missing */
	if (0 != re_regex(uri, len, "[^@]+@[^]+", NULL, NULL)) {
#if HAVE_INET6
		if (AF_INET6 == ua->acc->luri.af)
			err |= mbuf_printf(buf, "@[%r]",
					   &ua->acc->luri.host);
		else
#endif
			err |= mbuf_printf(buf, "@%r",
					   &ua->acc->luri.host);

		/* Also append port if specified and not 5060 */
		switch (ua->acc->luri.port) {

		case 0:
		case SIP_PORT:
			break;

		default:
			err |= mbuf_printf(buf, ":%u", ua->acc->luri.port);
			break;
		}
	}

	return err;
}
Beispiel #17
0
static void tmr_ping_handler(void *arg)
{
	struct allocation *alloc = arg;
	struct mbuf *mb;

	tmr_start(&alloc->tmr_ping, PING_INTERVAL, tmr_ping_handler, alloc);

	mb = mbuf_alloc(256);
	if (!mb)
		return;

	mb->pos = 48;
	mbuf_write_str(mb, "PING");
	mb->pos = 48;

	turnc_send(alloc->turnc, &alloc->peer, mb);

	mem_deref(mb);
}
Beispiel #18
0
static bool udp_helper_send(int *err, struct sa *dst,
			    struct mbuf *mb, void *arg)
{
	struct udp_test *ut = arg;
	const size_t pos = mb->pos;

	if (!sa_cmp(dst, &ut->srv, SA_ALL)) {
		*err = EPROTO;
		return false;
	}

	if (!mbuf_compare(mb, data0)) {
		*err = EBADMSG;
		return false;
	}

	/* Append a fake protocol trailer */
	mb->pos = mb->end;
	*err = mbuf_write_str(mb, "XXXX");

	mb->pos = pos;

	return false;
}
Beispiel #19
0
static int media_encode(const struct sdp_media *m, struct mbuf *mb, bool offer)
{
	enum sdp_bandwidth i;
	int err, supc = 0;
	bool disabled;
	struct le *le;
	uint16_t port;

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

		const struct sdp_format *fmt = le->data;

		if (fmt->sup)
			++supc;
	}

	if (m->disabled || supc == 0 || (!offer && !sa_port(&m->raddr))) {
		disabled = true;
		port = 0;
	}
	else {
		disabled = false;
		port = sa_port(&m->laddr);
	}

	err = mbuf_printf(mb, "m=%s %u %s", m->name, port, m->proto);

	if (disabled) {
		err |= mbuf_write_str(mb, " 0\r\n");
		return err;
	}

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

		const struct sdp_format *fmt = le->data;

		if (!fmt->sup)
			continue;

		err |= mbuf_printf(mb, " %s", fmt->id);
	}

	err |= mbuf_write_str(mb, "\r\n");

	if (sa_isset(&m->laddr, SA_ADDR)) {
		const int ipver = sa_af(&m->laddr) == AF_INET ? 4 : 6;
		err |= mbuf_printf(mb, "c=IN IP%d %j\r\n", ipver, &m->laddr);
	}

	for (i=SDP_BANDWIDTH_MIN; i<SDP_BANDWIDTH_MAX; i++) {

		if (m->lbwv[i] < 0)
			continue;

		err |= mbuf_printf(mb, "b=%s:%i\r\n",
				   sdp_bandwidth_name(i), m->lbwv[i]);
	}

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

		const struct sdp_format *fmt = le->data;

		if (!fmt->sup || !str_len(fmt->name))
			continue;

		err |= mbuf_printf(mb, "a=rtpmap:%s %s/%u",
				   fmt->id, fmt->name, fmt->srate);

		if (fmt->ch > 1)
			err |= mbuf_printf(mb, "/%u", fmt->ch);

		err |= mbuf_printf(mb, "\r\n");

		if (str_len(fmt->params))
			err |= mbuf_printf(mb, "a=fmtp:%s %s\r\n",
					   fmt->id, fmt->params);
	}

	if (sa_isset(&m->laddr_rtcp, SA_ALL))
		err |= mbuf_printf(mb, "a=rtcp:%u IN IP%d %j\r\n",
				   sa_port(&m->laddr_rtcp),
				   (AF_INET == sa_af(&m->laddr_rtcp)) ? 4 : 6,
				   &m->laddr_rtcp);
	else if (sa_isset(&m->laddr_rtcp, SA_PORT))
		err |= mbuf_printf(mb, "a=rtcp:%u\r\n",
				   sa_port(&m->laddr_rtcp));

	err |= mbuf_printf(mb, "a=%s\r\n",
			   sdp_dir_name(offer ? m->ldir : m->ldir & m->rdir));

	for (le = m->lattrl.head; le; le = le->next)
		err |= mbuf_printf(mb, "%H", sdp_attr_print, le->data);

	return err;
}
Beispiel #20
0
static int editor_input(struct commands *commands, struct mbuf *mb, char key,
			struct re_printf *pf, bool *del, bool is_long)
{
	int err = 0;

	switch (key) {

	case KEYCODE_ESC:
		*del = true;
		return re_hprintf(pf, "\nCancel\n");

	case KEYCODE_NONE:
	case KEYCODE_REL:
		break;

	case '\n':
		*del = true;
		return re_hprintf(pf, "\n");

	case '\b':
	case KEYCODE_DEL:
		if (mb->pos > 0) {
			err |= re_hprintf(pf, "\b ");
			mb->pos = mb->end = (mb->pos - 1);
		}
		break;

	case '\t':
		if (is_long) {
			const struct cmd *cmd = NULL;
			size_t n;

			err = re_hprintf(pf,
					 "TAB completion for \"%b\":\n",
					 mb->buf, mb->end);
			if (err)
				return err;

			/* Find all long commands that matches the N
			 * first characters of the input string.
			 *
			 * If the number of matches is exactly one,
			 * we can regard it as TAB completion.
			 */

			err = cmd_print_all(pf, commands, true, false,
					    (char *)mb->buf, mb->end);
			if (err)
				return err;

			n = get_match(commands, &cmd,
				      (char *)mb->buf, mb->end);
			if (n == 1 && cmd) {

				mb->pos = 0;
				mbuf_write_str(mb, cmd->name);
			}
			else if (n == 0) {
				err = re_hprintf(pf, "(none)\n");
			}
		}
		else {
			err = mbuf_write_u8(mb, key);
		}
		break;

	default:
		err = mbuf_write_u8(mb, key);
		break;
	}

	if (is_long) {
		err |= re_hprintf(pf, "\r/%b",
				  mb->buf, mb->end);
	}
	else
		err |= re_hprintf(pf, "\r> %32b", mb->buf, mb->end);

	return err;
}
Beispiel #21
0
static int afb_encode_handler(struct mbuf *mb, void *arg)
{
	return mbuf_write_str(mb, arg);
}
Beispiel #22
0
/**
 * Send an HTTP request
 *
 * @param reqp      Pointer to allocated HTTP request object
 * @param cli       HTTP Client
 * @param met       Request method
 * @param uri       Request URI
 * @param resph     Response handler
 * @param datah     Content handler (optional)
 * @param arg       Handler argument
 * @param fmt       Formatted HTTP headers and body (optional)
 *
 * @return 0 if success, otherwise errorcode
 */
int http_request(struct http_req **reqp, struct http_cli *cli, const char *met,
		 const char *uri, http_resp_h *resph, http_data_h *datah,
		 void *arg, const char *fmt, ...)
{
	struct pl scheme, host, port, path;
	struct http_req *req;
	uint16_t defport;
	bool secure;
	va_list ap;
	int err;

	if (!reqp || !cli || !met || !uri)
		return EINVAL;

	if (re_regex(uri, strlen(uri), "[a-z]+://[^:/]+[:]*[0-9]*[^]+",
		     &scheme, &host, NULL, &port, &path) || scheme.p != uri)
		return EINVAL;

	if (!pl_strcasecmp(&scheme, "http") ||
	    !pl_strcasecmp(&scheme, "ws")) {
		secure  = false;
		defport = 80;
	}
#ifdef USE_TLS
	else if (!pl_strcasecmp(&scheme, "https") ||
		 !pl_strcasecmp(&scheme, "wss")) {
		secure  = true;
		defport = 443;
	}
#endif
	else
		return ENOTSUP;

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

	req->tls    = mem_ref(cli->tls);
	req->secure = secure;
	req->port   = pl_isset(&port) ? pl_u32(&port) : defport;
	req->resph  = resph;
	req->datah  = datah;
	req->arg    = arg;

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

	req->mbreq = mbuf_alloc(1024);
	if (!req->mbreq) {
		err = ENOMEM;
		goto out;
	}

	err = mbuf_printf(req->mbreq,
			  "%s %r HTTP/1.1\r\n"
			  "Host: %r\r\n",
			  met, &path, &host);
	if (fmt) {
		va_start(ap, fmt);
		err |= mbuf_vprintf(req->mbreq, fmt, ap);
		va_end(ap);
	}
	else {
		err |= mbuf_write_str(req->mbreq, "\r\n");
	}
	if (err)
		goto out;

	req->mbreq->pos = 0;

	if (!sa_set_str(&req->srvv[0], req->host, req->port)) {

		req->srvc = 1;

		err = req_connect(req);
		if (err)
			goto out;
	}
	else {
		err = dnsc_query(&req->dq, cli->dnsc, req->host,
				 DNS_TYPE_A, DNS_CLASS_IN, true,
				 query_handler, req);
		if (err)
			goto out;
	}

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

	return err;
}
Beispiel #23
0
int pcp_option_encode(struct mbuf *mb, enum pcp_option_code code,
		      const void *v)
{
	const struct sa *sa = v;
	const struct pcp_option_filter *filt = v;
	size_t start, len;
	int err = 0;

	if (!mb)
		return EINVAL;

	mb->pos += 4;
	start = mb->pos;

	switch (code) {

	case PCP_OPTION_THIRD_PARTY:
		if (!sa)
			return EINVAL;
		err |= pcp_ipaddr_encode(mb, sa);
		break;

	case PCP_OPTION_PREFER_FAILURE:
		/* no payload */
		break;

	case PCP_OPTION_FILTER:
		if (!filt)
			return EINVAL;
		err |= mbuf_write_u8(mb, 0x00);
		err |= mbuf_write_u8(mb, filt->prefix_length);
		err |= mbuf_write_u16(mb, htons(sa_port(&filt->remote_peer)));
		err |= pcp_ipaddr_encode(mb, &filt->remote_peer);
		break;

	case PCP_OPTION_DESCRIPTION:
		if (!v)
			return EINVAL;
		err |= mbuf_write_str(mb, v);
		break;

	default:
		(void)re_fprintf(stderr,
				 "pcp: unsupported option %d\n", code);
		return EINVAL;
	}

	/* header */
	len = mb->pos - start;

	mb->pos = start - 4;
	err |= mbuf_write_u8(mb, code);
	err |= mbuf_write_u8(mb, 0x00);
	err |= mbuf_write_u16(mb, htons(len));
	mb->pos += len;

	/* padding */
	while ((mb->pos - start) & 0x03)
		err |= mbuf_write_u8(mb, 0x00);

	return err;
}
Beispiel #24
0
int stun_attr_encode(struct mbuf *mb, uint16_t type, const void *v,
		     const uint8_t *tid, uint8_t padding)
{
	const struct stun_change_req *ch_req = v;
	const struct stun_errcode *err_code = v;
	const struct stun_unknown_attr *ua = v;
	const unsigned int *num = v;
	const struct mbuf *mbd = v;
	size_t start, len;
	uint32_t i, n;
	int err = 0;

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

	mb->pos += 4;
	start = mb->pos;

	switch (type) {

	case STUN_ATTR_MAPPED_ADDR:
	case STUN_ATTR_ALT_SERVER:
	case STUN_ATTR_RESP_ORIGIN:
	case STUN_ATTR_OTHER_ADDR:
		tid = NULL;
		/*@fallthrough@*/
	case STUN_ATTR_XOR_PEER_ADDR:
	case STUN_ATTR_XOR_RELAY_ADDR:
	case STUN_ATTR_XOR_MAPPED_ADDR:
		err |= stun_addr_encode(mb, v, tid);
		break;

	case STUN_ATTR_CHANGE_REQ:
		n = (uint32_t)ch_req->ip << 2 | (uint32_t)ch_req->port << 1;
		err |= mbuf_write_u32(mb, htonl(n));
		break;

	case STUN_ATTR_USERNAME:
	case STUN_ATTR_REALM:
	case STUN_ATTR_NONCE:
	case STUN_ATTR_SOFTWARE:
		err |= mbuf_write_str(mb, v);
		break;

	case STUN_ATTR_MSG_INTEGRITY:
		err |= mbuf_write_mem(mb, v, 20);
		break;

	case STUN_ATTR_ERR_CODE:
		err |= mbuf_write_u16(mb, 0x00);
		err |= mbuf_write_u8(mb,  err_code->code/100);
		err |= mbuf_write_u8(mb,  err_code->code%100);
		err |= mbuf_write_str(mb, err_code->reason);
		break;

	case STUN_ATTR_UNKNOWN_ATTR:
		for (i=0; i<ua->typec; i++)
			err |= mbuf_write_u16(mb, htons(ua->typev[i]));
		break;

	case STUN_ATTR_CHANNEL_NUMBER:
	case STUN_ATTR_RESP_PORT:
		err |= mbuf_write_u16(mb, htons(*num));
		err |= mbuf_write_u16(mb, 0x0000);
		break;

	case STUN_ATTR_LIFETIME:
	case STUN_ATTR_PRIORITY:
	case STUN_ATTR_FINGERPRINT:
		err |= mbuf_write_u32(mb, htonl(*num));
		break;

	case STUN_ATTR_DATA:
	case STUN_ATTR_PADDING:
		if (mb == mbd) {
			mb->pos = mb->end;
			break;
		}
		err |= mbuf_write_mem(mb, mbuf_buf(mbd), mbuf_get_left(mbd));
		break;

	case STUN_ATTR_REQ_ADDR_FAMILY:
	case STUN_ATTR_REQ_TRANSPORT:
		err |= mbuf_write_u8(mb, *num);
		err |= mbuf_write_u8(mb, 0x00);
		err |= mbuf_write_u16(mb, 0x0000);
		break;

	case STUN_ATTR_EVEN_PORT:
		err |= mbuf_write_u8(mb, ((struct stun_even_port *)v)->r << 7);
		break;

	case STUN_ATTR_DONT_FRAGMENT:
	case STUN_ATTR_USE_CAND:
		 /* no value */
		break;

	case STUN_ATTR_RSV_TOKEN:
	case STUN_ATTR_CONTROLLED:
	case STUN_ATTR_CONTROLLING:
		err |= mbuf_write_u64(mb, sys_htonll(*(uint64_t *)v));
		break;

	default:
		err = EINVAL;
		break;
	}

	/* header */
	len = mb->pos - start;

	mb->pos = start - 4;
	err |= mbuf_write_u16(mb, htons(type));
	err |= mbuf_write_u16(mb, htons(len));
	mb->pos += len;

	/* padding */
	while ((mb->pos - start) & 0x03)
		err |= mbuf_write_u8(mb, padding);

	return err;
}
Beispiel #25
0
int sdp_encode(struct mbuf **mbp, struct sdp_session *sess, bool offer)
{
	const int ipver = sa_af(&sess->laddr) == AF_INET ? 4 : 6;
	enum sdp_bandwidth i;
	struct mbuf *mb;
	struct le *le;
	int err;

	if (!mbp || !sess)
		return EINVAL;

	mb = mbuf_alloc(512);
	if (!mb)
		return ENOMEM;

	err  = mbuf_printf(mb, "v=%u\r\n", SDP_VERSION);
	err |= mbuf_printf(mb, "o=- %u %u IN IP%d %j\r\n",
			   sess->id, sess->ver++, ipver, &sess->laddr);
	err |= mbuf_write_str(mb, "s=-\r\n");
	err |= mbuf_printf(mb, "c=IN IP%d %j\r\n", ipver, &sess->laddr);

	for (i=SDP_BANDWIDTH_MIN; i<SDP_BANDWIDTH_MAX; i++) {

		if (sess->lbwv[i] < 0)
			continue;

		err |= mbuf_printf(mb, "b=%s:%i\r\n",
				   sdp_bandwidth_name(i), sess->lbwv[i]);
	}

	err |= mbuf_write_str(mb, "t=0 0\r\n");

	for (le = sess->lattrl.head; le; le = le->next)
		err |= mbuf_printf(mb, "%H", sdp_attr_print, le->data);

	for (le=sess->lmedial.head; offer && le;) {

		struct sdp_media *m = le->data;

		le = le->next;

		if (m->disabled)
			continue;

		list_unlink(&m->le);
		list_append(&sess->medial, &m->le, m);
	}

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

		struct sdp_media *m = le->data;

		err |= media_encode(m, mb, offer);
	}

	mb->pos = 0;

	if (err)
		mem_deref(mb);
	else
		*mbp = mb;

	return err;
}
Beispiel #26
0
Datei: pkt.c Projekt: kaija/libre
int rtcp_vencode(struct mbuf *mb, enum rtcp_type type, uint32_t count,
		 va_list ap)
{
	size_t i, pos;
	uint16_t len;
	const uint8_t *data;
	size_t data_len;
	const uint32_t *srcv;
	const char *reason;
	rtcp_encode_h *ench;
	void *arg;
	int err = 0;

	if (!mb)
		return EINVAL;

	pos = mb->pos;

	/* Skip header - encoded last */
	mb->pos = mb->end = (mb->pos + RTCP_HDR_SIZE);

	switch (type) {

	case RTCP_SR:
		for (i=0; i<6; i++)
			err |= mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		ench = va_arg(ap, rtcp_encode_h *);
		arg = va_arg(ap, void *);
		if (ench)
			err |= ench(mb, arg);
		break;

	case RTCP_RR:
		err = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		ench = va_arg(ap, rtcp_encode_h *);
		arg = va_arg(ap, void *);
		if (ench)
			err |= ench(mb, arg);
		break;

	case RTCP_SDES:
		ench = va_arg(ap, rtcp_encode_h *);
		arg = va_arg(ap, void *);
		if (ench)
			err |= ench(mb, arg);
		break;

	case RTCP_BYE:
		srcv   = va_arg(ap, uint32_t *);
		reason = va_arg(ap, char *);
		for (i=0; i<count && !err; i++) {
			err = mbuf_write_u32(mb, htonl(srcv[i]));
		}
		if (reason) {
			err |= mbuf_write_u8(mb, strlen(reason));
			err |= mbuf_write_str(mb, reason);
		}
		break;

	case RTCP_APP:
		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		err |= mbuf_write_mem(mb, va_arg(ap, uint8_t *), 4);
		data = va_arg(ap, const uint8_t *);
		data_len = va_arg(ap, size_t);
		if (data) {
			if (data_len % 4) {
				DEBUG_WARNING("not a multiple of 32bits\n");
				return EBADMSG;
			}
			err |= mbuf_write_mem(mb, data, data_len);
		}
		break;

	case RTCP_FIR:
		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		break;

	case RTCP_NACK:
		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		err |= mbuf_write_u16(mb, htons(va_arg(ap, uint32_t)));
		err |= mbuf_write_u16(mb, htons(va_arg(ap, uint32_t)));
		break;

	case RTCP_RTPFB:
	case RTCP_PSFB:
		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		err |= mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
		ench = va_arg(ap, rtcp_encode_h *);
		arg = va_arg(ap, void *);
		if (ench)
			err |= ench(mb, arg);
		break;

	default:
		return EINVAL;
	}
	if (err)
		return err;

	/* padding to 32 bits */
	while ((mb->end - pos) & 0x3)
		err |= mbuf_write_u8(mb, 0x00);
	if (err)
		return err;

	/* Encode RTCP Header */
	mb->pos = pos;
	len = (mb->end - pos - RTCP_HDR_SIZE)/sizeof(uint32_t);
	err = rtcp_hdr_encode(mb, count, type, len);
	if (err)
		return err;

	mb->pos = mb->end;

	return 0;
}