Ejemplo n.º 1
0
Archivo: rtp.c Proyecto: hbowden/re
/**
 * Encode the RTP header into a buffer
 *
 * @param mb  Buffer to encode into
 * @param hdr RTP Header to be encoded
 *
 * @return 0 if success, otherwise errorcode
 */
int rtp_hdr_encode(struct mbuf *mb, const struct rtp_header *hdr)
{
	uint8_t buf[2];
	int err, i;

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

	buf[0]  = (hdr->ver & 0x02) << 6;
	buf[0] |= (hdr->pad & 0x01) << 5;
	buf[0] |= (hdr->ext & 0x01) << 4;
	buf[0] |= (hdr->cc  & 0x0f) << 0;
	buf[1]  = (hdr->m   & 0x01) << 7;
	buf[1] |= (hdr->pt  & 0x7f) << 0;

	err  = mbuf_write_mem(mb, buf, sizeof(buf));
	err |= mbuf_write_u16(mb, htons(hdr->seq));
	err |= mbuf_write_u32(mb, htonl(hdr->ts));
	err |= mbuf_write_u32(mb, htonl(hdr->ssrc));

	for (i=0; i<hdr->cc; i++) {
		err |= mbuf_write_u32(mb, htonl(hdr->csrc[i]));
	}

	return err;
}
Ejemplo n.º 2
0
static int sli_encode(struct mbuf *mb, void *arg)
{
	int err = 0, n=2;
	(void)arg;

	while (n--) {
		err |= mbuf_write_u32(mb, htonl(0xcafecafe));
	}

	return err;
}
Ejemplo n.º 3
0
static int encode_handler(struct mbuf *mb, void *arg)
{
	int err = 0;
	size_t i;

	(void)arg;

	for (i=0; i<6 && !err; i++)
		err = mbuf_write_u32(mb, htonl(0x12345678));

	return err;
}
Ejemplo n.º 4
0
int stun_hdr_encode(struct mbuf *mb, const struct stun_hdr *hdr)
{
	int err = 0;

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

	err |= mbuf_write_u16(mb, htons(hdr->type & 0x3fff));
	err |= mbuf_write_u16(mb, htons(hdr->len));
	err |= mbuf_write_u32(mb, htonl(hdr->cookie));
	err |= mbuf_write_mem(mb, hdr->tid, sizeof(hdr->tid));

	return err;
}
Ejemplo n.º 5
0
Archivo: sdes.c Proyecto: soramimi/qSIP
/**
 * Encode one SDES chunk into mbuffer
 *
 * @param mb    Buffer to encode into
 * @param src   First SSRC/CSRC
 * @param itemc Number of SDES items to encode
 *
 * @return 0 if success, otherwise errorcode
 */
int rtcp_sdes_encode(struct mbuf *mb, uint32_t src, uint32_t itemc, ...)
{
	va_list ap;
	size_t start;
	int err = 0;

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

	va_start(ap, itemc);

	start = mb->pos;
	err = mbuf_write_u32(mb, htonl(src));

	/* add all SDES items */
	while (itemc-- && !err) {
		const uint8_t type = va_arg(ap, int);
		const char *v = va_arg(ap, const char *);
		size_t len;
		if (!v)
			continue;

		len = strlen(v); /* note: max 255 chars */
		if (len > 255) {
			err = EINVAL;
			goto out;
		}

		err  = mbuf_write_u8(mb, type);
		err |= mbuf_write_u8(mb, len & 0xff);
		err |= mbuf_write_mem(mb, (uint8_t *)v, len);
	}

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

 out:
	va_end(ap);

	return err;
}
Ejemplo n.º 6
0
/**
 * Encode an RTCP Slice Loss Indication (SLI) message
 *
 * @param mb     Buffer to encode into
 * @param first  Macroblock (MB) address of the first lost macroblock
 * @param number Number of lost macroblocks
 * @param picid  Picture ID
 *
 * @return 0 for success, otherwise errorcode
 */
int rtcp_psfb_sli_encode(struct mbuf *mb, uint16_t first, uint16_t number,
			 uint8_t picid)
{
	const uint32_t v = first<<19 | number<<6 | picid;
	return mbuf_write_u32(mb, htonl(v));
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
int srtp_decrypt(struct srtp *srtp, struct mbuf *mb)
{
	struct srtp_stream *strm;
	struct rtp_header hdr;
	struct comp *comp;
	uint64_t ix;
	size_t start;
	int diff;
	int err;

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

	comp = &srtp->rtp;

	start = mb->pos;

	err = rtp_hdr_decode(&hdr, mb);
	if (err)
		return err;

	err = stream_get_seq(&strm, srtp, hdr.ssrc, hdr.seq);
	if (err)
		return err;

	diff = seq_diff(strm->s_l, hdr.seq);
	if (diff > 32768)
		return ETIMEDOUT;

	/* Roll-Over Counter (ROC) */
	if (diff <= -32768) {
		strm->roc++;
		strm->s_l = 0;
	}

	ix = srtp_get_index(strm->roc, strm->s_l, hdr.seq);

	if (comp->hmac) {
		uint8_t tag_calc[SHA_DIGEST_LENGTH];
		uint8_t tag_pkt[SHA_DIGEST_LENGTH];
		size_t pld_start, tag_start;

		if (mbuf_get_left(mb) < comp->tag_len)
			return EBADMSG;

		pld_start = mb->pos;
		tag_start = mb->end - comp->tag_len;

		mb->pos = tag_start;

		err = mbuf_read_mem(mb, tag_pkt, comp->tag_len);
		if (err)
			return err;

		mb->pos = mb->end = tag_start;

		err = mbuf_write_u32(mb, htonl(strm->roc));
		if (err)
			return err;

		mb->pos = start;

		err = hmac_digest(comp->hmac, tag_calc, sizeof(tag_calc),
				  mbuf_buf(mb), mbuf_get_left(mb));
		if (err)
			return err;

		mb->pos = pld_start;
		mb->end = tag_start;

		if (0 != memcmp(tag_calc, tag_pkt, comp->tag_len))
			return EAUTH;

		/*
		 * 3.3.2.  Replay Protection
		 *
		 * Secure replay protection is only possible when
		 * integrity protection is present.
		 */
		if (!srtp_replay_check(&strm->replay_rtp, ix))
			return EALREADY;
	}

	if (comp->aes) {

		union vect128 iv;
		uint8_t *p = mbuf_buf(mb);

		srtp_iv_calc(&iv, &comp->k_s, strm->ssrc, ix);

		aes_set_iv(comp->aes, iv.u8);
		err = aes_decr(comp->aes, p, p, mbuf_get_left(mb));
		if (err)
			return err;
	}

	if (hdr.seq > strm->s_l)
		strm->s_l = hdr.seq;

	mb->pos = start;

	return 0;
}
Ejemplo n.º 9
0
int srtp_encrypt(struct srtp *srtp, struct mbuf *mb)
{
	struct srtp_stream *strm;
	struct rtp_header hdr;
	struct comp *comp;
	size_t start;
	uint64_t ix;
	int err;

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

	comp = &srtp->rtp;

	start = mb->pos;

	err = rtp_hdr_decode(&hdr, mb);
	if (err)
		return err;

	err = stream_get_seq(&strm, srtp, hdr.ssrc, hdr.seq);
	if (err)
		return err;

	/* Roll-Over Counter (ROC) */
	if (seq_diff(strm->s_l, hdr.seq) <= -32768) {
		strm->roc++;
		strm->s_l = 0;
	}

	ix = 65536ULL * strm->roc + hdr.seq;

	if (comp->aes) {
		union vect128 iv;
		uint8_t *p = mbuf_buf(mb);

		srtp_iv_calc(&iv, &comp->k_s, strm->ssrc, ix);

		aes_set_iv(comp->aes, iv.u8);
		err = aes_encr(comp->aes, p, p, mbuf_get_left(mb));
		if (err)
			return err;
	}

	if (comp->hmac) {
		const size_t tag_start = mb->end;
		uint8_t tag[SHA_DIGEST_LENGTH];

		mb->pos = tag_start;

		err = mbuf_write_u32(mb, htonl(strm->roc));
		if (err)
			return err;

		mb->pos = start;

		err = hmac_digest(comp->hmac, tag, sizeof(tag),
				  mbuf_buf(mb), mbuf_get_left(mb));
		if (err)
			return err;

		mb->pos = mb->end = tag_start;

		err = mbuf_write_mem(mb, tag, comp->tag_len);
		if (err)
			return err;
	}

	if (hdr.seq > strm->s_l)
		strm->s_l = hdr.seq;

	mb->pos = start;

	return 0;
}
Ejemplo n.º 10
0
Archivo: pkt.c Proyecto: 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;
}