xref: /openbsd-src/sbin/isakmpd/field.c (revision 91c43901001bef6fd1d7ab0409f35a9b307f8f3e)
1*91c43901Stom /* $OpenBSD: field.c,v 1.22 2017/04/02 21:23:44 tom Exp $	 */
251ca15aeSniklas /* $EOM: field.c,v 1.11 2000/02/20 19:58:37 niklas Exp $	 */
32040585eSniklas 
42040585eSniklas /*
5eb840acdSniklas  * Copyright (c) 1998, 1999 Niklas Hallqvist.  All rights reserved.
62040585eSniklas  *
72040585eSniklas  * Redistribution and use in source and binary forms, with or without
82040585eSniklas  * modification, are permitted provided that the following conditions
92040585eSniklas  * are met:
102040585eSniklas  * 1. Redistributions of source code must retain the above copyright
112040585eSniklas  *    notice, this list of conditions and the following disclaimer.
122040585eSniklas  * 2. Redistributions in binary form must reproduce the above copyright
132040585eSniklas  *    notice, this list of conditions and the following disclaimer in the
142040585eSniklas  *    documentation and/or other materials provided with the distribution.
152040585eSniklas  *
162040585eSniklas  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
172040585eSniklas  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
182040585eSniklas  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
192040585eSniklas  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
202040585eSniklas  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
212040585eSniklas  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222040585eSniklas  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232040585eSniklas  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242040585eSniklas  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
252040585eSniklas  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262040585eSniklas  */
272040585eSniklas 
282040585eSniklas /*
292040585eSniklas  * This code was written under funding by Ericsson Radio Systems.
302040585eSniklas  */
312040585eSniklas 
322040585eSniklas #include <stdio.h>
332040585eSniklas #include <stdlib.h>
342040585eSniklas #include <string.h>
3512e5c931Sguenther #include <netinet/in.h>
362040585eSniklas 
372040585eSniklas #include "constants.h"
382040585eSniklas #include "field.h"
392040585eSniklas #include "log.h"
402040585eSniklas #include "util.h"
412040585eSniklas 
422040585eSniklas static char    *field_debug_raw(u_int8_t *, size_t, struct constant_map **);
432040585eSniklas static char    *field_debug_num(u_int8_t *, size_t, struct constant_map **);
442040585eSniklas static char    *field_debug_mask(u_int8_t *, size_t, struct constant_map **);
452040585eSniklas static char    *field_debug_ign(u_int8_t *, size_t, struct constant_map **);
462040585eSniklas static char    *field_debug_cst(u_int8_t *, size_t, struct constant_map **);
472040585eSniklas 
482040585eSniklas /* Contents must match the enum in struct field.  */
4950eea14cSho static char    *(*decode_field[]) (u_int8_t *, size_t,
5050eea14cSho     struct constant_map **) = {
512040585eSniklas 	field_debug_raw,
522040585eSniklas 	field_debug_num,
532040585eSniklas 	field_debug_mask,
542040585eSniklas 	field_debug_ign,
552040585eSniklas 	field_debug_cst
562040585eSniklas };
572040585eSniklas 
582040585eSniklas /*
592040585eSniklas  * Return a string showing the hexadecimal contents of the LEN-sized buffer
602040585eSniklas  * BUF.  MAPS should be zero and is only here because the API requires it.
612040585eSniklas  */
622040585eSniklas static char *
field_debug_raw(u_int8_t * buf,size_t len,struct constant_map ** maps)632040585eSniklas field_debug_raw(u_int8_t *buf, size_t len, struct constant_map **maps)
642040585eSniklas {
65d6d7f0d1Scloder 	return raw2hex(buf, len);
662040585eSniklas }
672040585eSniklas 
682040585eSniklas /*
692040585eSniklas  * Convert the unsigned LEN-sized number at BUF of network byteorder to a
702040585eSniklas  * 32-bit unsigned integer of host byteorder pointed to by VAL.
712040585eSniklas  */
722040585eSniklas static int
extract_val(u_int8_t * buf,size_t len,u_int32_t * val)732040585eSniklas extract_val(u_int8_t *buf, size_t len, u_int32_t *val)
742040585eSniklas {
75fb9475d6Sderaadt 	switch (len) {
762040585eSniklas 	case 1:
772040585eSniklas 		*val = *buf;
782040585eSniklas 		break;
792040585eSniklas 	case 2:
802040585eSniklas 		*val = decode_16(buf);
812040585eSniklas 		break;
822040585eSniklas 	case 4:
832040585eSniklas 		*val = decode_32(buf);
842040585eSniklas 		break;
852040585eSniklas 	default:
862040585eSniklas 		return -1;
872040585eSniklas 	}
882040585eSniklas 	return 0;
892040585eSniklas }
902040585eSniklas 
912040585eSniklas /*
922040585eSniklas  * Return a textual representation of the unsigned number pointed to by BUF
932040585eSniklas  * which is LEN octets long.  MAPS should be zero and is only here because
942040585eSniklas  * the API requires it.
952040585eSniklas  */
962040585eSniklas static char *
field_debug_num(u_int8_t * buf,size_t len,struct constant_map ** maps)972040585eSniklas field_debug_num(u_int8_t *buf, size_t len, struct constant_map **maps)
982040585eSniklas {
99*91c43901Stom 	char           *retval;
1002040585eSniklas 	u_int32_t       val;
1012040585eSniklas 
1022040585eSniklas 	if (extract_val(buf, len, &val))
103*91c43901Stom 		return NULL;
104*91c43901Stom 	if (asprintf(&retval, "%u", val) == -1)
105*91c43901Stom 		return NULL;
1062040585eSniklas 	return retval;
1072040585eSniklas }
1082040585eSniklas 
1092040585eSniklas /*
1102040585eSniklas  * Return the symbolic names of the flags pointed to by BUF which is LEN
1112040585eSniklas  * octets long, using the constant maps MAPS.
1122040585eSniklas  */
1132040585eSniklas static char *
field_debug_mask(u_int8_t * buf,size_t len,struct constant_map ** maps)1142040585eSniklas field_debug_mask(u_int8_t *buf, size_t len, struct constant_map **maps)
1152040585eSniklas {
1162040585eSniklas 	u_int32_t       val;
1172040585eSniklas 	u_int32_t       bit;
1182040585eSniklas 	char           *retval, *new_buf, *name;
1192040585eSniklas 	size_t          buf_sz;
1202040585eSniklas 
1212040585eSniklas 	if (extract_val(buf, len, &val))
122*91c43901Stom 		return NULL;
1232040585eSniklas 
1242040585eSniklas 	/* Size for brackets, two spaces and a NUL terminator.  */
1250f76d02aSniklas 	buf_sz = 4;
1262040585eSniklas 	retval = malloc(buf_sz);
1272040585eSniklas 	if (!retval)
128*91c43901Stom 		return NULL;
1292040585eSniklas 
130b8380d91Sho 	strlcpy(retval, "[ ", buf_sz);
131fb9475d6Sderaadt 	for (bit = 1; bit; bit <<= 1) {
132fb9475d6Sderaadt 		if (val & bit) {
1332040585eSniklas 			name = constant_name_maps(maps, bit);
1340f76d02aSniklas 			buf_sz += strlen(name) + 1;
1352040585eSniklas 			new_buf = realloc(retval, buf_sz);
136fb9475d6Sderaadt 			if (!new_buf) {
1372040585eSniklas 				free(retval);
138*91c43901Stom 				return NULL;
1392040585eSniklas 			}
1402040585eSniklas 			retval = new_buf;
141b8380d91Sho 			strlcat(retval, name, buf_sz);
142b8380d91Sho 			strlcat(retval, " ", buf_sz);
1432040585eSniklas 		}
1442040585eSniklas 	}
145b8380d91Sho 	strlcat(retval, "]", buf_sz);
1462040585eSniklas 	return retval;
1472040585eSniklas }
1482040585eSniklas 
1492040585eSniklas /*
1502040585eSniklas  * Just a dummy needed to skip the unused LEN sized space at BUF.  MAPS
1512040585eSniklas  * should be zero and is only here because the API requires it.
1522040585eSniklas  */
1532040585eSniklas static char *
field_debug_ign(u_int8_t * buf,size_t len,struct constant_map ** maps)1542040585eSniklas field_debug_ign(u_int8_t *buf, size_t len, struct constant_map **maps)
1552040585eSniklas {
156*91c43901Stom 	return NULL;
1572040585eSniklas }
1582040585eSniklas 
1592040585eSniklas /*
1602040585eSniklas  * Return the symbolic name of a constant pointed to by BUF which is LEN
1612040585eSniklas  * octets long, using the constant maps MAPS.
1622040585eSniklas  */
1632040585eSniklas static char *
field_debug_cst(u_int8_t * buf,size_t len,struct constant_map ** maps)1642040585eSniklas field_debug_cst(u_int8_t *buf, size_t len, struct constant_map **maps)
1652040585eSniklas {
1662040585eSniklas 	u_int32_t       val;
1672040585eSniklas 
1682040585eSniklas 	if (extract_val(buf, len, &val))
169*91c43901Stom 		return NULL;
1702040585eSniklas 
1712040585eSniklas 	return strdup(constant_name_maps(maps, val));
1722040585eSniklas }
1732040585eSniklas 
1742040585eSniklas /* Pretty-print a field from BUF as described by F.  */
1752040585eSniklas void
field_dump_field(struct field * f,u_int8_t * buf)1762040585eSniklas field_dump_field(struct field *f, u_int8_t *buf)
1772040585eSniklas {
1782040585eSniklas 	char	*value;
1792040585eSniklas 
1802040585eSniklas 	value = decode_field[(int) f->type] (buf + f->offset, f->len, f->maps);
181fb9475d6Sderaadt 	if (value) {
18251ca15aeSniklas 		LOG_DBG((LOG_MESSAGE, 70, "%s: %s", f->name, value));
1832040585eSniklas 		free(value);
1842040585eSniklas 	}
1852040585eSniklas }
1862040585eSniklas 
1872040585eSniklas /* Pretty-print all the fields of BUF as described in FIELDS.  */
1882040585eSniklas void
field_dump_payload(struct field * fields,u_int8_t * buf)1892040585eSniklas field_dump_payload(struct field *fields, u_int8_t *buf)
1902040585eSniklas {
1912040585eSniklas 	struct field   *field;
1922040585eSniklas 
1932040585eSniklas 	for (field = fields; field->name; field++)
1942040585eSniklas 		field_dump_field(field, buf);
1952040585eSniklas }
1962040585eSniklas 
1972040585eSniklas /* Return the numeric value of the field F of BUF.  */
1982040585eSniklas u_int32_t
field_get_num(struct field * f,u_int8_t * buf)1992040585eSniklas field_get_num(struct field *f, u_int8_t *buf)
2002040585eSniklas {
2012040585eSniklas 	u_int32_t       val;
2022040585eSniklas 
2032040585eSniklas 	if (extract_val(buf + f->offset, f->len, &val))
2042040585eSniklas 		return 0;
2052040585eSniklas 	return val;
2062040585eSniklas }
2072040585eSniklas 
2082040585eSniklas /* Stash the number VAL into BUF's field F.  */
2092040585eSniklas void
field_set_num(struct field * f,u_int8_t * buf,u_int32_t val)2102040585eSniklas field_set_num(struct field *f, u_int8_t *buf, u_int32_t val)
2112040585eSniklas {
212fb9475d6Sderaadt 	switch (f->len) {
2132040585eSniklas 	case 1:
2142040585eSniklas 		buf[f->offset] = val;
2152040585eSniklas 		break;
2162040585eSniklas 	case 2:
2172040585eSniklas 		encode_16(buf + f->offset, val);
2182040585eSniklas 		break;
2192040585eSniklas 	case 4:
2202040585eSniklas 		encode_32(buf + f->offset, val);
2212040585eSniklas 		break;
2222040585eSniklas 	}
2232040585eSniklas }
2242040585eSniklas 
2252040585eSniklas /* Stash BUF's raw field F into VAL.  */
2262040585eSniklas void
field_get_raw(struct field * f,u_int8_t * buf,u_int8_t * val)2272040585eSniklas field_get_raw(struct field *f, u_int8_t *buf, u_int8_t *val)
2282040585eSniklas {
2292040585eSniklas 	memcpy(val, buf + f->offset, f->len);
2302040585eSniklas }
2312040585eSniklas 
2322040585eSniklas /* Stash the buffer VAL into BUF's field F.  */
2332040585eSniklas void
field_set_raw(struct field * f,u_int8_t * buf,u_int8_t * val)2342040585eSniklas field_set_raw(struct field *f, u_int8_t *buf, u_int8_t *val)
2352040585eSniklas {
2362040585eSniklas 	memcpy(buf + f->offset, val, f->len);
2372040585eSniklas }
238