xref: /openbsd/sbin/isakmpd/field.c (revision a6445c1d)
1 /* $OpenBSD: field.c,v 1.19 2005/11/15 21:49:04 cloder Exp $	 */
2 /* $EOM: field.c,v 1.11 2000/02/20 19:58:37 niklas Exp $	 */
3 
4 /*
5  * Copyright (c) 1998, 1999 Niklas Hallqvist.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * This code was written under funding by Ericsson Radio Systems.
30  */
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "constants.h"
37 #include "field.h"
38 #include "log.h"
39 #include "util.h"
40 
41 static char    *field_debug_raw(u_int8_t *, size_t, struct constant_map **);
42 static char    *field_debug_num(u_int8_t *, size_t, struct constant_map **);
43 static char    *field_debug_mask(u_int8_t *, size_t, struct constant_map **);
44 static char    *field_debug_ign(u_int8_t *, size_t, struct constant_map **);
45 static char    *field_debug_cst(u_int8_t *, size_t, struct constant_map **);
46 
47 /* Contents must match the enum in struct field.  */
48 static char    *(*decode_field[]) (u_int8_t *, size_t,
49     struct constant_map **) = {
50 	field_debug_raw,
51 	field_debug_num,
52 	field_debug_mask,
53 	field_debug_ign,
54 	field_debug_cst
55 };
56 
57 /*
58  * Return a string showing the hexadecimal contents of the LEN-sized buffer
59  * BUF.  MAPS should be zero and is only here because the API requires it.
60  */
61 static char *
62 field_debug_raw(u_int8_t *buf, size_t len, struct constant_map **maps)
63 {
64 	return raw2hex(buf, len);
65 }
66 
67 /*
68  * Convert the unsigned LEN-sized number at BUF of network byteorder to a
69  * 32-bit unsigned integer of host byteorder pointed to by VAL.
70  */
71 static int
72 extract_val(u_int8_t *buf, size_t len, u_int32_t *val)
73 {
74 	switch (len) {
75 	case 1:
76 		*val = *buf;
77 		break;
78 	case 2:
79 		*val = decode_16(buf);
80 		break;
81 	case 4:
82 		*val = decode_32(buf);
83 		break;
84 	default:
85 		return -1;
86 	}
87 	return 0;
88 }
89 
90 /*
91  * Return a textual representation of the unsigned number pointed to by BUF
92  * which is LEN octets long.  MAPS should be zero and is only here because
93  * the API requires it.
94  */
95 static char *
96 field_debug_num(u_int8_t *buf, size_t len, struct constant_map **maps)
97 {
98 	char           *retval;
99 	u_int32_t       val;
100 
101 	if (extract_val(buf, len, &val))
102 		return 0;
103 	/* 3 decimal digits are enough to represent each byte.  */
104 	asprintf(&retval, "%u", val);
105 	return retval;
106 }
107 
108 /*
109  * Return the symbolic names of the flags pointed to by BUF which is LEN
110  * octets long, using the constant maps MAPS.
111  */
112 static char *
113 field_debug_mask(u_int8_t *buf, size_t len, struct constant_map **maps)
114 {
115 	u_int32_t       val;
116 	u_int32_t       bit;
117 	char           *retval, *new_buf, *name;
118 	size_t          buf_sz;
119 
120 	if (extract_val(buf, len, &val))
121 		return 0;
122 
123 	/* Size for brackets, two spaces and a NUL terminator.  */
124 	buf_sz = 4;
125 	retval = malloc(buf_sz);
126 	if (!retval)
127 		return 0;
128 
129 	strlcpy(retval, "[ ", buf_sz);
130 	for (bit = 1; bit; bit <<= 1) {
131 		if (val & bit) {
132 			name = constant_name_maps(maps, bit);
133 			buf_sz += strlen(name) + 1;
134 			new_buf = realloc(retval, buf_sz);
135 			if (!new_buf) {
136 				free(retval);
137 				return 0;
138 			}
139 			retval = new_buf;
140 			strlcat(retval, name, buf_sz);
141 			strlcat(retval, " ", buf_sz);
142 		}
143 	}
144 	strlcat(retval, "]", buf_sz);
145 	return retval;
146 }
147 
148 /*
149  * Just a dummy needed to skip the unused LEN sized space at BUF.  MAPS
150  * should be zero and is only here because the API requires it.
151  */
152 static char *
153 field_debug_ign(u_int8_t *buf, size_t len, struct constant_map **maps)
154 {
155 	return 0;
156 }
157 
158 /*
159  * Return the symbolic name of a constant pointed to by BUF which is LEN
160  * octets long, using the constant maps MAPS.
161  */
162 static char *
163 field_debug_cst(u_int8_t *buf, size_t len, struct constant_map **maps)
164 {
165 	u_int32_t       val;
166 
167 	if (extract_val(buf, len, &val))
168 		return 0;
169 
170 	return strdup(constant_name_maps(maps, val));
171 }
172 
173 /* Pretty-print a field from BUF as described by F.  */
174 void
175 field_dump_field(struct field *f, u_int8_t *buf)
176 {
177 	char	*value;
178 
179 	value = decode_field[(int) f->type] (buf + f->offset, f->len, f->maps);
180 	if (value) {
181 		LOG_DBG((LOG_MESSAGE, 70, "%s: %s", f->name, value));
182 		free(value);
183 	}
184 }
185 
186 /* Pretty-print all the fields of BUF as described in FIELDS.  */
187 void
188 field_dump_payload(struct field *fields, u_int8_t *buf)
189 {
190 	struct field   *field;
191 
192 	for (field = fields; field->name; field++)
193 		field_dump_field(field, buf);
194 }
195 
196 /* Return the numeric value of the field F of BUF.  */
197 u_int32_t
198 field_get_num(struct field *f, u_int8_t *buf)
199 {
200 	u_int32_t       val;
201 
202 	if (extract_val(buf + f->offset, f->len, &val))
203 		return 0;
204 	return val;
205 }
206 
207 /* Stash the number VAL into BUF's field F.  */
208 void
209 field_set_num(struct field *f, u_int8_t *buf, u_int32_t val)
210 {
211 	switch (f->len) {
212 	case 1:
213 		buf[f->offset] = val;
214 		break;
215 	case 2:
216 		encode_16(buf + f->offset, val);
217 		break;
218 	case 4:
219 		encode_32(buf + f->offset, val);
220 		break;
221 	}
222 }
223 
224 /* Stash BUF's raw field F into VAL.  */
225 void
226 field_get_raw(struct field *f, u_int8_t *buf, u_int8_t *val)
227 {
228 	memcpy(val, buf + f->offset, f->len);
229 }
230 
231 /* Stash the buffer VAL into BUF's field F.  */
232 void
233 field_set_raw(struct field *f, u_int8_t *buf, u_int8_t *val)
234 {
235 	memcpy(buf + f->offset, val, f->len);
236 }
237