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