1 /**
2  * @file stun/rep.c  STUN reply
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #include <re_types.h>
7 #include <re_mem.h>
8 #include <re_mbuf.h>
9 #include <re_sa.h>
10 #include <re_list.h>
11 #include <re_stun.h>
12 #include "stun.h"
13 
14 
15 /**
16  * Send a STUN response message
17  *
18  * @param proto   Transport Protocol
19  * @param sock    Socket; UDP (struct udp_sock) or TCP (struct tcp_conn)
20  * @param dst     Destination network address
21  * @param presz   Number of bytes in preamble, if sending over TURN
22  * @param req     Matching STUN request
23  * @param key     Authentication key (optional)
24  * @param keylen  Number of bytes in authentication key
25  * @param fp      Use STUN Fingerprint attribute
26  * @param attrc   Number of attributes to encode (variable arguments)
27  * @param ...     Variable list of attribute-tuples
28  *                Each attribute has 2 arguments, attribute type and value
29  *
30  * @return 0 if success, otherwise errorcode
31  */
stun_reply(int proto,void * sock,const struct sa * dst,size_t presz,const struct stun_msg * req,const uint8_t * key,size_t keylen,bool fp,uint32_t attrc,...)32 int stun_reply(int proto, void *sock, const struct sa *dst, size_t presz,
33 	       const struct stun_msg *req, const uint8_t *key,
34 	       size_t keylen, bool fp, uint32_t attrc, ...)
35 {
36 	struct mbuf *mb = NULL;
37 	int err = ENOMEM;
38 	va_list ap;
39 
40 	if (!sock || !req)
41 		return EINVAL;
42 
43 	mb = mbuf_alloc(256);
44 	if (!mb)
45 		goto out;
46 
47 	va_start(ap, attrc);
48 	mb->pos = presz;
49 	err = stun_msg_vencode(mb, stun_msg_method(req),
50 			       STUN_CLASS_SUCCESS_RESP, stun_msg_tid(req),
51 			       NULL, key, keylen, fp, 0x00, attrc, ap);
52 	va_end(ap);
53 	if (err)
54 		goto out;
55 
56 	mb->pos = presz;
57 	err = stun_send(proto, sock, dst, mb);
58 
59  out:
60 	mem_deref(mb);
61 
62 	return err;
63 }
64 
65 
66 /**
67  * Send a STUN error response
68  *
69  * @param proto   Transport Protocol
70  * @param sock    Socket; UDP (struct udp_sock) or TCP (struct tcp_conn)
71  * @param dst     Destination network address
72  * @param presz   Number of bytes in preamble, if sending over TURN
73  * @param req     Matching STUN request
74  * @param scode   Status code
75  * @param reason  Reason string
76  * @param key     Authentication key (optional)
77  * @param keylen  Number of bytes in authentication key
78  * @param fp      Use STUN Fingerprint attribute
79  * @param attrc   Number of attributes to encode (variable arguments)
80  * @param ...     Variable list of attribute-tuples
81  *                Each attribute has 2 arguments, attribute type and value
82  *
83  * @return 0 if success, otherwise errorcode
84  */
stun_ereply(int proto,void * sock,const struct sa * dst,size_t presz,const struct stun_msg * req,uint16_t scode,const char * reason,const uint8_t * key,size_t keylen,bool fp,uint32_t attrc,...)85 int stun_ereply(int proto, void *sock, const struct sa *dst, size_t presz,
86 		const struct stun_msg *req, uint16_t scode,
87 		const char *reason, const uint8_t *key, size_t keylen,
88 		bool fp, uint32_t attrc, ...)
89 {
90 	struct stun_errcode ec;
91 	struct mbuf *mb = NULL;
92 	int err = ENOMEM;
93 	va_list ap;
94 
95 	if (!sock || !req || !scode || !reason)
96 		return EINVAL;
97 
98 	mb = mbuf_alloc(256);
99 	if (!mb)
100 		goto out;
101 
102 	ec.code = scode;
103 	ec.reason = (char *)reason;
104 
105 	va_start(ap, attrc);
106 	mb->pos = presz;
107 	err = stun_msg_vencode(mb, stun_msg_method(req), STUN_CLASS_ERROR_RESP,
108 			       stun_msg_tid(req), &ec, key, keylen,
109 			       fp, 0x00, attrc, ap);
110 	va_end(ap);
111 	if (err)
112 		goto out;
113 
114 	mb->pos = presz;
115 	err = stun_send(proto, sock, dst, mb);
116 
117  out:
118 	mem_deref(mb);
119 
120 	return err;
121 }
122