Restore plen setting in the same place
[sipe-libnice.git] / stun / stun-msg.h
blob71d875b405e8601ff1784270798dd928e2270772
1 /*
2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006, 2007 Collabora Ltd.
5 * Contact: Dafydd Harries
6 * (C) 2006, 2007 Nokia Corporation. All rights reserved.
7 * Contact: Rémi Denis-Courmont
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
17 * License.
19 * The Original Code is the Nice GLib ICE library.
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
24 * Contributors:
25 * Rémi Denis-Courmont, Nokia
27 * Alternatively, the contents of this file may be used under the terms of the
28 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
29 * case the provisions of LGPL are applicable instead of those above. If you
30 * wish to allow use of your version of this file only under the terms of the
31 * LGPL and not to allow others to use your version of this file under the
32 * MPL, indicate your decision by deleting the provisions above and replace
33 * them with the notice and other provisions required by the LGPL. If you do
34 * not delete the provisions above, a recipient may use your version of this
35 * file under either the MPL or the LGPL.
38 #ifndef STUN_MSG_H
39 # define STUN_MSG_H 1
41 /**
42 * @file stun-msg.h
43 * @brief STUN low-level message formatting and parsing
47 # ifndef NDEBUG
48 # include <stdio.h>
49 # include <stdarg.h>
50 static inline void DBG (const char *fmt, ...)
52 va_list ap;
53 va_start (ap, fmt);
54 vfprintf (stderr, fmt, ap);
55 va_end (ap);
58 static inline void DBG_bytes (const void *data, size_t len)
60 size_t i;
62 DBG ("0x");
63 for (i = 0; i < len; i++)
64 DBG ("%02x", ((const unsigned char *)data)[i]);
66 # else
67 # define DBG( ... ) (void)0
68 # define DBG_bytes( data, len ) (void)0
69 # endif
71 # include <stdint.h>
72 # include <sys/types.h>
73 # include <stdbool.h>
75 # define STUN_MAXMSG 65552 /* bytes */
76 # define STUN_MAXCHR 127u
77 # define STUN_MAXSTR ((STUN_MAXCHR * 6u) + 1)
79 # define STUN_COOKIE 0x2112A442
81 typedef struct stun_hdr_s
83 uint16_t msg_type;
84 uint16_t msg_len;
85 uint32_t msg_cookie;
86 uint32_t msg_id[3];
87 } stun_hdr_t;
90 typedef uint8_t stun_msg_t[STUN_MAXMSG];
92 /* Message classes */
93 typedef enum
95 STUN_REQUEST=0,
96 STUN_INDICATION=1,
97 STUN_RESPONSE=2,
98 STUN_ERROR=3
99 } stun_class_t;
101 /* Message methods */
102 typedef enum
104 STUN_BINDING=0x001, /* RFC3489bis-11 */
105 STUN_OLD_SHARED_SECRET=0x002, /* old RFC3489 */
106 STUN_ALLOCATE=0x003, /* TURN-04 */
107 STUN_SET_ACTIVE_DST=0x004, /* TURN-04 */
108 STUN_CONNECT=0x005, /* TURN-04 */
109 STUN_IND_SEND=0x006, /* TURN-04 */
110 STUN_IND_DATA=0x007, /* TURN-04 */
111 STUN_IND_CONNECT_STATUS=0x008 /* TURN-04 */
112 } stun_method_t;
115 * STUN attribute types
116 * Should be in sync with stun_is_unknown()
118 typedef enum
120 /* Mandatory attributes */
121 /* 0x0000 */ /* reserved */
122 STUN_MAPPED_ADDRESS=0x0001, /* RFC3489bis-11 */
123 STUN_OLD_RESPONSE_ADDRESS=0x0002, /* old RFC3489 */
124 STUN_OLD_CHANGE_REQUEST=0x0003, /* old RFC3489 */
125 STUN_OLD_SOURCE_ADDRESS=0x0004, /* old RFC3489 */
126 STUN_OLD_CHANGED_ADDRESS=0x0005, /* old RFC3489 */
127 STUN_USERNAME=0x0006, /* RFC3489bis-11 */
128 STUN_OLD_PASSWORD=0x0007, /* old RFC3489 */
129 STUN_MESSAGE_INTEGRITY=0x0008, /* RFC3489bis-11 */
130 STUN_ERROR_CODE=0x0009, /* RFC3489bis-11 */
131 STUN_UNKNOWN_ATTRIBUTES=0x000A, /* RFC3489bis-11 */
132 STUN_OLD_REFLECTED_FROM=0x000B, /* old RFC3489 */
133 /* 0x000C */ /* reserved */
134 STUN_LIFETIME=0x000D, /* TURN-04 */
135 /* 0x000E */ /* reserved */
136 /* 0x000F */ /* reserved */
137 STUN_BANDWIDTH=0x0010, /* TURN-04 */
138 /* 0x0011 */ /* reserved */
139 STUN_REMOTE_ADDRESS=0x0012, /* TURN-04 */
140 STUN_DATA=0x0013, /* TURN-04 */
141 STUN_REALM=0x0014, /* RFC3489bis-11 */
142 STUN_NONCE=0x0015, /* RFC3489bis-11 */
143 STUN_RELAY_ADDRESS=0x0016, /* TURN-04 */
144 STUN_REQUESTED_ADDRESS_TYPE=0x0017, /* TURN-IPv6-03 */
145 STUN_REQUESTED_PORT_PROPS=0x0018, /* TURN-04 */
146 STUN_REQUESTED_TRANSPORT=0x0019, /* TURN-04 */
147 /* 0x001A */ /* reserved */
148 /* 0x001B */ /* reserved */
149 /* 0x001C */ /* reserved */
150 /* 0x001D */ /* reserved */
151 /* 0x001E */ /* reserved */
152 /* 0x001F */ /* reserved */
153 STUN_XOR_MAPPED_ADDRESS=0x0020, /* RFC3489bis-11 */
154 STUN_TIMER_VAL=0x0021, /* TURN-04 */
155 STUN_REQUESTED_IP=0x0022, /* TURN-04 */
156 STUN_CONNECT_STAT=0x0023, /* TURN-04 */
157 STUN_PRIORITY=0x0024, /* ICE-18 */
158 STUN_USE_CANDIDATE=0x0025, /* ICE-18 */
159 /* 0x0026 */ /* reserved */
160 /* 0x0027 */ /* reserved */
161 /* 0x0028 */ /* reserved */
162 STUN_XOR_INTERNAL_ADDRESS=0x0029, /* wing-nat-control-04 */
163 /* 0x002A-0x7fff */ /* reserved */
165 /* Optional attributes */
166 /* 0x8000-0x8021 */ /* reserved */
167 STUN_SERVER=0x8022, /* RFC3489bis-11 */
168 STUN_ALTERNATE_SERVER=0x8023, /* RFC3489bis-11 */
169 STUN_REFRESH_INTERVAL=0x8024, /* wing-nat-control-04 */
170 /* 0x8025 */ /* reserved */
171 /* 0x8026 */ /* reserved */
172 /* 0x8027 */ /* reserved */
173 STUN_FINGERPRINT=0x8028, /* RFC3489bis-11 */
174 STUN_ICE_CONTROLLED=0x8029, /* ICE-18 */
175 STUN_ICE_CONTROLLING=0x802A, /* ICE-18 */
176 /* 0x802B-0xFFFF */ /* reserved */
177 } stun_attr_type_t;
180 static inline bool stun_optional (uint16_t t)
182 return (t >> 15) == 1;
185 typedef uint8_t stun_transid_t[12];
188 * STUN error codes
189 * Should be in sync with stun_strerror()
191 typedef enum
193 STUN_TRY_ALTERNATE=300, /* RFC3489bis-11 */
194 STUN_BAD_REQUEST=400, /* RFC3489bis-11 */
195 STUN_UNAUTHORIZED=401, /* RFC3489bis-11 */
196 STUN_UNKNOWN_ATTRIBUTE=420, /* RFC3489bis-11 */
197 STUN_NO_BINDING=437, /* TURN-04 */
198 STUN_STALE_NONCE=438, /* RFC3489bis-11 */
199 STUN_ACT_DST_ALREADY=439, /* TURN-04 */
200 STUN_UNSUPP_FAMILY=440, /* TURN-IPv6-03 */
201 STUN_UNSUPP_TRANSPORT=442, /* TURN-04 */
202 STUN_INVALID_IP=443, /* TURN-04 */
203 STUN_INVALID_PORT=444, /* TURN-04 */
204 STUN_OP_TCP_ONLY=445, /* TURN-04 */
205 STUN_CONN_ALREADY=446, /* TURN-04 */
206 STUN_ALLOC_OVER_QUOTA=486, /* TURN-04 */
207 STUN_ROLE_CONFLICT=487, /* ICE-18 */
208 STUN_SERVER_ERROR=500, /* RFC3489bis-11 */
209 STUN_SERVER_CAPACITY=507, /* TURN-04 */
210 STUN_ERROR_MAX=699
211 } stun_error_t;
215 * @return complement to the next multiple of 4.
217 static inline size_t stun_padding (size_t l)
219 return (4 - (l & 3)) & 3;
224 * Rounds up an integer to the next multiple of 4.
226 static inline size_t stun_align (size_t l)
228 return (l + 3) & ~3;
233 * Reads a word from a non-aligned buffer.
234 * @return host byte order word value.
236 static inline uint16_t stun_getw (const uint8_t *ptr)
238 return ((ptr)[0] << 8) | ptr[1];
241 static inline uint16_t stun_length (const uint8_t *ptr)
243 return stun_getw (ptr + 2);
248 * @return STUN message class in host byte order (value from 0 to 3)
250 static inline stun_class_t stun_get_class (const uint8_t *msg)
252 uint16_t t = stun_getw (msg);
253 return (stun_class_t)(((t & 0x0100) >> 7) | ((t & 0x0010) >> 4));
257 * @return STUN message method (value from 0 to 0xfff)
259 static inline stun_method_t stun_get_method (const uint8_t *msg)
261 uint16_t t = stun_getw (msg);
262 return (stun_method_t)(((t & 0x3e00) >> 2) | ((t & 0x00e0) >> 1) |
263 (t & 0x000f));
266 bool stun_has_cookie (const uint8_t *msg);
270 * @return STUN message transaction ID
272 static inline const uint8_t *stun_id (const uint8_t *msg)
274 //assert (stun_valid (req));
275 return msg + 8;
279 # ifdef __cplusplus
280 extern "C" {
281 # endif
284 * Computes the FINGERPRINT checksum of a STUN message.
285 * @param msg pointer to the STUN message
286 * @param len size of the message from header (inclusive) and up to
287 * FINGERPRINT attribute (inclusive)
289 * @return fingerprint value in <b>host</b> byte order.
291 uint32_t stun_fingerprint (const uint8_t *msg, size_t len);
294 * Computes the MESSAGE-INTEGRITY hash of a STUN message.
295 * @param msg pointer to the STUN message
296 * @param len size of the message from header (inclusive) and up to
297 * MESSAGE-INTEGRITY attribute (inclusive)
298 * @param sha output buffer for SHA1 hash (20 bytes)
299 * @param key HMAC key
300 * @param keylen HMAC key bytes length
302 * @return fingerprint value in <b>host</b> byte order.
304 void stun_sha1 (const uint8_t *msg, size_t len,
305 uint8_t *sha, const void *key, size_t keylen);
308 * SIP H(A1) computation
310 void stun_hash_creds (const char *realm, const char *login, const char *pw,
311 unsigned char md5[16]);
314 * Generates a pseudo-random secure STUN transaction ID.
316 void stun_make_transid (stun_transid_t id);
318 int stun_xor_address (const uint8_t *msg,
319 struct sockaddr *addr, socklen_t addrlen);
322 * @section stunrecv
323 * @brief STUN message processing functions
326 # ifndef STUN_VALIDATE_DECLARATION
327 # define STUN_VALIDATE_DECLARATION 1
329 * Verifies that a packet is a valid STUN message.
331 * @return actual byte length of the message if valid (>0),
332 * 0 if it the packet is incomplete or -1 in case of other error.
334 ssize_t stun_validate (const uint8_t *msg, size_t len);
337 * Checks whether a packet on a mutiplexed STUN/non-STUN channel looks like a
338 * STUN message. It is assumed that stun_validate succeeded first (i.e.
339 * returned a stricly positive value).
341 * @return true if STUN message with cookie and fingerprint, 0 otherwise.
343 bool stun_demux (const uint8_t *msg);
345 #endif
348 * Matches a response (or error response) to a request.
350 * @param msg valid STUN message
351 * @param method STUN method number (host byte order)
352 * @param id STUN transaction id
353 * @param key HMAC key, or NULL if there is no authentication
354 * @param keylen HMAC key byte length, 0 is no authentication
355 * @param error [OUT] set to -1 if the response is not an error,
356 * to the error code if it is an error response.
358 * @return true if and only if the message is a response or an error response
359 * with the STUN cookie and specified method and transaction identifier.
361 bool stun_match_messages (const uint8_t *restrict resp,
362 const uint8_t *restrict req,
363 const uint8_t *key, size_t keylen,
364 int *restrict error);
365 int stun_verify_key (const uint8_t *msg, const void *key, size_t keylen);
366 int stun_verify_password (const uint8_t *msg, const char *pw);
367 int stun_verify_username (const uint8_t *msg, const char *local_ufrag, uint32_t compat);
370 * Looks for an attribute in a *valid* STUN message.
371 * @param msg message buffer
372 * @param type STUN attribute type (host byte order)
373 * @param palen [OUT] pointer to store the byte length of the attribute
374 * @return a pointer to the start of the attribute payload if found,
375 * otherwise NULL.
377 const void *
378 stun_find (const uint8_t *restrict msg, stun_attr_type_t type,
379 uint16_t *restrict palen);
382 * Checks if an attribute is present within a STUN message.
384 * @param msg valid STUN message
385 * @param type STUN attribute type (host byte order)
387 * @return whether there is a MESSAGE-INTEGRITY attribute
389 static inline bool stun_present (const uint8_t *msg, stun_attr_type_t type)
391 uint16_t dummy;
392 return stun_find (msg, type, &dummy) != NULL;
397 * Looks for a flag attribute within a valid STUN message.
398 * @param msg valid STUN message buffer
399 * @param type STUN attribute type (host byte order)
400 * @return 0 if flag is present, ENOENT if it is not, EINVAL if flag payload
401 * size is not zero.
403 int stun_find_flag (const uint8_t *msg, stun_attr_type_t type);
406 * Extracts a 32-bits attribute from a valid STUN message.
407 * @param msg valid STUN message buffer
408 * @param type STUN attribute type (host byte order)
409 * @param pval [OUT] where to store the host byte ordered value
411 * @return 0 on success, ENOENT if attribute not found,
412 * EINVAL if attribute payload was not 32-bits.
413 * In case of error, @a *pval is not modified.
415 int stun_find32 (const uint8_t *msg, stun_attr_type_t type, uint32_t *pval);
418 * Extracts a 64-bits attribute from a valid STUN message.
419 * @param msg valid STUN message buffer
420 * @param type STUN attribute type (host byte order)
421 * @param pval [OUT] where to store the host byte ordered value
422 * @return 0 on success, ENOENT if attribute not found,
423 * EINVAL if attribute payload was not 64-bits.
424 * In case of error, @a *pval is not modified.
426 int stun_find64 (const uint8_t *msg, stun_attr_type_t type, uint64_t *pval);
429 * Extracts an UTF-8 string from a valid STUN message.
430 * @param msg valid STUN message buffer
431 * @param type STUN attribute type (host byte order)
432 * @param buf buffer to store the extracted string
433 * @param maxcp maximum number of code points allowed
434 * (@a buf should be (6*maxcp+1) bytes long)
436 * @return 0 on success, ENOENT if attribute not found, EINVAL if attribute
437 * improperly encoded, ENOBUFS if the buffer size was too small.
439 * @note A nul-byte is appended at the end.
441 int stun_find_string (const uint8_t *restrict msg, stun_attr_type_t type,
442 char *buf, size_t buflen);
444 # define STUN_MAX_STR (763u)
445 # define STUN_MAX_CP (127u)
448 * Extracts a network address attribute from a valid STUN message.
449 * @param msg valid STUN message buffer
450 * @param type STUN attribute type (host byte order)
451 * @param addr [OUT] where to store the socket address
452 * @param addrlen [IN/OUT] pointer to the size of the socket address
453 * buffer upon entry, set to the length of the extracted socket
454 * address upon return,
455 * @return 0 on success, ENOENT if attribute not found,
456 * EINVAL if attribute payload size was wrong or addrlen too small,
457 * EAFNOSUPPORT if address family is unknown.
459 int stun_find_addr (const uint8_t *restrict msg, stun_attr_type_t type,
460 struct sockaddr *restrict addr,
461 socklen_t *restrict addrlen);
464 * Extracts an obfuscated network address attribute from a valid STUN message.
465 * @param msg valid STUN message buffer
466 * @param type STUN attribute type (host byte order)
467 * @param addr [OUT] where to store the socket address
468 * @param addrlen [IN/OUT] pointer to the size of the socket address
469 * buffer upon entry, set to the length of the extracted socket
470 * address upon return,
471 * @return 0 on success, ENOENT if attribute not found,
472 * EINVAL if attribute payload size was wrong or addrlen too small,
473 * EAFNOSUPPORT if address family is unknown.
475 int stun_find_xor_addr (const uint8_t *restrict msg, stun_attr_type_t type,
476 struct sockaddr *restrict addr,
477 socklen_t *restrict addrlen);
480 * Compares the length and content of an attribute.
482 * @param msg valid STUN message buffer
483 * @param type STUN attribute type (host byte order)
484 * @param data pointer to value to compare with
485 * @param len byte length of the value
486 * @return 0 in case of match, ENOENT if attribute was not found,
487 * EINVAL if it did not match (different length, or same length but
488 * different content)
490 int stun_memcmp (const uint8_t *msg, stun_attr_type_t type,
491 const void *data, size_t len);
494 * Compares the content of an attribute with a string.
495 * @param msg valid STUN message buffer
496 * @param type STUN attribute type (host byte order)
497 * @param str string to compare with
498 * @return 0 in case of match, ENOENT if attribute was not found,
499 * EINVAL if it did not match
501 int stun_strcmp (const uint8_t *msg, stun_attr_type_t type,
502 const char *str);
505 * @param type host-byte order STUN attribute type
507 * @return true if @a type is an attribute type unknown to this library
508 * (regardless of being a mandatory or optional attribute type)
510 bool stun_is_unknown (uint16_t type);
513 * Looks for unknown mandatory attributes in a valid STUN message.
514 * @param msg valid STUN message
515 * @param list [OUT] table pointer to store unknown attributes IDs
516 * @param max size of the table in units of uint16_t
517 * @return the number of unknown mandatory attributes up to max.
519 unsigned stun_find_unknown (const uint8_t *msg, uint16_t *list, unsigned max);
522 * @section stunsend
523 * @brief Message formatting functions
527 * Initializes a STUN request message buffer, with no attributes.
528 * @param m STUN message method (host byte order)
530 void stun_init_request (uint8_t *msg, stun_method_t m);
533 * Initializes a STUN indication message buffer, with no attributes.
534 * @param m STUN message method (host byte order)
536 void stun_init_indication (uint8_t *msg, stun_method_t m);
539 * Initializes a STUN message buffer with a SERVER attribute (if there is
540 * enough room for it), in response to a given valid STUN request messsage.
541 * STUN method and transaction ID are copied from the request message.
543 * @param ans [OUT] STUN message buffer
544 * @param msize STUN message buffer size
545 * @param req STUN message query
547 * ans == req is allowed.
549 void stun_init_response (uint8_t *ans, size_t msize, const uint8_t *req, int compat);
552 * Initializes a STUN error response message buffer with an ERROR-CODE
553 * and a SERVER attributes, in response to a given valid STUN request
554 * messsage. STUN method and transaction ID are copied from the request
555 * message.
557 * @param ans [OUT] STUN message buffer
558 * @param msize STUN message buffer size
559 * @param req STUN message to copy method and transaction ID from
560 * @param err host-byte order STUN integer error code
562 * @return 0 on success, ENOBUFS on error
564 * ans == req is allowed.
566 int stun_init_error (uint8_t *ans, size_t msize, const uint8_t *req,
567 stun_error_t err, int compat);
570 * Initializes a STUN error response message buffer, in response to a valid
571 * STUN request messsage with unknown attributes. STUN method, transaction ID
572 * and unknown attribute IDs are copied from the request message.
574 * @param ans [OUT] STUN message buffer
575 * @param msize STUN message buffer size
576 * @param req STUN request message
577 * @return 0 on success, ENOBUFS otherwise
579 * ans == req is allowed.
581 int stun_init_error_unknown (uint8_t *ans, size_t msize, const uint8_t *req,
582 int compat);
584 size_t
585 stun_finish_long (uint8_t *msg, size_t *restrict plen,
586 const char *realm, const char *username, const char *nonce,
587 const void *restrict key, size_t keylen, int compat);
590 * Completes a STUN message structure before sending it, and
591 * authenticates it with short-term credentials.
592 * No further attributes shall be added.
594 * @param msg STUN message buffer
595 * @param plen [IN/OUT] buffer size on entry, message length on return
596 * @param username nul-terminated STUN username (or NULL if none)
597 * @param password nul-terminated STUN secret password (or NULL if none)
598 * @param nonce STUN authentication nonce (or NULL if none)
600 * @return 0 on success, ENOBUFS on error.
602 size_t stun_finish_short (uint8_t *msg, size_t *restrict plen,
603 const char *username, const char *password,
604 const char *nonce, int compat);
607 * Completes a STUN message structure before sending it.
608 * No further attributes shall be added.
610 * @param msg STUN message buffer
611 * @param plen [IN/OUT] buffer size on entry, message length on return
613 * @return 0 on success, ENOBUFS on error.
615 size_t stun_finish (uint8_t *restrict msg, size_t *restrict plen, int compat);
618 void *stun_append (uint8_t *msg, size_t msize, stun_attr_type_t type,
619 size_t length);
620 int stun_append_bytes (uint8_t *restrict msg, size_t msize,
621 stun_attr_type_t type, const void *data, size_t len);
624 * Appends an empty ("flag") attribute to a STUN message.
625 * @param msg STUN message buffer
626 * @param msize STUN message buffer size
627 * @param type attribute type (host byte order)
628 * @return 0 on success, ENOBUFS on error.
630 int stun_append_flag (uint8_t *msg, size_t msize, stun_attr_type_t type);
633 * Appends an attribute consisting of a 32-bits value to a STUN message.
634 * @param msg STUN message buffer
635 * @param msize STUN message buffer size
636 * @param type attribute type (host byte order)
637 * @param value payload (host byte order)
638 * @return 0 on success, ENOBUFS on error.
640 int stun_append32 (uint8_t *msg, size_t msize,
641 stun_attr_type_t type, uint32_t value);
644 * Appends an attribute consisting of a 64-bits value to a STUN message.
645 * @param msg STUN message buffer
646 * @param msize STUN message buffer size
647 * @param type attribute type (host byte order)
648 * @param value payload (host byte order)
649 * @return 0 on success, ENOBUFS on error.
651 int stun_append64 (uint8_t *msg, size_t msize,
652 stun_attr_type_t type, uint64_t value);
655 * Appends an attribute from a nul-terminated string.
656 * @param msg STUN message buffer
657 * @param msize STUN message buffer size
658 * @param type attribute type (host byte order)
659 * @param str nul-terminated string
660 * @return 0 on success, ENOBUFS on error.
662 int stun_append_string (uint8_t *restrict msg, size_t msize,
663 stun_attr_type_t type, const char *str);
666 * Appends an attribute consisting of a network address to a STUN message.
667 * @param msg STUN message buffer
668 * @param msize STUN message buffer size
669 * @param type attribyte type (host byte order)
670 * @param addr socket address to convert into an attribute
671 * @param addrlen byte length of socket address
672 * @return 0 on success, ENOBUFS if the message buffer overflowed,
673 * EAFNOSUPPORT is the socket address family is not supported,
674 * EINVAL if the socket address length is too small w.r.t. the address family.
676 int stun_append_addr (uint8_t *restrict msg, size_t msize,
677 stun_attr_type_t type,
678 const struct sockaddr *restrict addr,
679 socklen_t addrlen);
682 * Appends an attribute consisting of a xor'ed network address.
683 * @param msg STUN message buffer
684 * @param msize STUN message buffer size
685 * @param type attribyte type (host byte order)
686 * @param addr socket address to convert into an attribute
687 * @param addrlen byte length of socket address
688 * @return 0 on success, ENOBUFS if the message buffer overflowed,
689 * EAFNOSUPPORT is the socket address family is not supported,
690 * EINVAL if the socket address length is too small w.r.t. the address family.
692 int stun_append_xor_addr (uint8_t *restrict msg, size_t msize,
693 stun_attr_type_t type,
694 const struct sockaddr *restrict addr,
695 socklen_t addrlen);
697 # ifdef __cplusplus
699 # endif
703 * @param msg valid STUN message
704 * @return true if there is at least one unknown mandatory attribute.
706 static inline bool stun_has_unknown (const void *msg)
708 uint16_t dummy;
709 return stun_find_unknown (msg, &dummy, 1);
713 # ifndef NDEBUG
715 * This function is for debugging only, which is why it is only defined under
716 * !NDEBUG. It should really only be used in run-time assertions, as it cannot
717 * detect all possible errors. stun_validate() should be used instead in real
718 * code.
720 * @param msg pointer to a potential STUN message
721 * @return whether the pointer refers to a valid STUN message
723 static inline bool stun_valid (const uint8_t *msg)
725 size_t length = 20u + stun_length (msg);
726 return stun_validate (msg, length) == (ssize_t)length;
728 # endif
730 #endif