1 /* $OpenBSD: field.c,v 1.16 2004/06/14 09:55:41 ho Exp $ */
2 /* $EOM: field.c,v 1.11 2000/02/20 19:58:37 niklas Exp $ */
5 * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
29 * This code was written under funding by Ericsson Radio Systems.
38 #include "constants.h"
43 static char *field_debug_raw(u_int8_t
*, size_t, struct constant_map
**);
44 static char *field_debug_num(u_int8_t
*, size_t, struct constant_map
**);
45 static char *field_debug_mask(u_int8_t
*, size_t, struct constant_map
**);
46 static char *field_debug_ign(u_int8_t
*, size_t, struct constant_map
**);
47 static char *field_debug_cst(u_int8_t
*, size_t, struct constant_map
**);
49 /* Contents must match the enum in struct field. */
50 static char *(*decode_field
[]) (u_int8_t
*, size_t,
51 struct constant_map
**) = {
60 * Return a string showing the hexadecimal contents of the LEN-sized buffer
61 * BUF. MAPS should be zero and is only here because the API requires it.
64 field_debug_raw(u_int8_t
*buf
, size_t len
, struct constant_map
**maps
)
70 retval
= malloc(3 + len
* 2);
73 strlcpy(retval
, "0x", 3 + len
* 2);
75 for (; len
> 0; len
--) {
76 snprintf(p
, 1 + len
* 2, "%02x", *buf
++);
83 * Convert the unsigned LEN-sized number at BUF of network byteorder to a
84 * 32-bit unsigned integer of host byteorder pointed to by VAL.
87 extract_val(u_int8_t
*buf
, size_t len
, u_int32_t
*val
)
94 *val
= decode_16(buf
);
97 *val
= decode_32(buf
);
106 * Return a textual representation of the unsigned number pointed to by BUF
107 * which is LEN octets long. MAPS should be zero and is only here because
108 * the API requires it.
111 field_debug_num(u_int8_t
*buf
, size_t len
, struct constant_map
**maps
)
116 if (extract_val(buf
, len
, &val
))
118 /* 3 decimal digits are enough to represent each byte. */
119 retval
= malloc(3 * len
);
120 snprintf(retval
, 3 * len
, "%u", val
);
125 * Return the symbolic names of the flags pointed to by BUF which is LEN
126 * octets long, using the constant maps MAPS.
129 field_debug_mask(u_int8_t
*buf
, size_t len
, struct constant_map
**maps
)
133 char *retval
, *new_buf
, *name
;
136 if (extract_val(buf
, len
, &val
))
139 /* Size for brackets, two spaces and a NUL terminator. */
141 retval
= malloc(buf_sz
);
145 strlcpy(retval
, "[ ", buf_sz
);
146 for (bit
= 1; bit
; bit
<<= 1) {
148 name
= constant_name_maps(maps
, bit
);
149 buf_sz
+= strlen(name
) + 1;
150 new_buf
= realloc(retval
, buf_sz
);
156 strlcat(retval
, name
, buf_sz
);
157 strlcat(retval
, " ", buf_sz
);
160 strlcat(retval
, "]", buf_sz
);
165 * Just a dummy needed to skip the unused LEN sized space at BUF. MAPS
166 * should be zero and is only here because the API requires it.
169 field_debug_ign(u_int8_t
*buf
, size_t len
, struct constant_map
**maps
)
175 * Return the symbolic name of a constant pointed to by BUF which is LEN
176 * octets long, using the constant maps MAPS.
179 field_debug_cst(u_int8_t
*buf
, size_t len
, struct constant_map
**maps
)
183 if (extract_val(buf
, len
, &val
))
186 return strdup(constant_name_maps(maps
, val
));
189 /* Pretty-print a field from BUF as described by F. */
191 field_dump_field(struct field
*f
, u_int8_t
*buf
)
195 value
= decode_field
[(int) f
->type
] (buf
+ f
->offset
, f
->len
, f
->maps
);
197 LOG_DBG((LOG_MESSAGE
, 70, "%s: %s", f
->name
, value
));
202 /* Pretty-print all the fields of BUF as described in FIELDS. */
204 field_dump_payload(struct field
*fields
, u_int8_t
*buf
)
208 for (field
= fields
; field
->name
; field
++)
209 field_dump_field(field
, buf
);
212 /* Return the numeric value of the field F of BUF. */
214 field_get_num(struct field
*f
, u_int8_t
*buf
)
218 if (extract_val(buf
+ f
->offset
, f
->len
, &val
))
223 /* Stash the number VAL into BUF's field F. */
225 field_set_num(struct field
*f
, u_int8_t
*buf
, u_int32_t val
)
229 buf
[f
->offset
] = val
;
232 encode_16(buf
+ f
->offset
, val
);
235 encode_32(buf
+ f
->offset
, val
);
240 /* Stash BUF's raw field F into VAL. */
242 field_get_raw(struct field
*f
, u_int8_t
*buf
, u_int8_t
*val
)
244 memcpy(val
, buf
+ f
->offset
, f
->len
);
247 /* Stash the buffer VAL into BUF's field F. */
249 field_set_raw(struct field
*f
, u_int8_t
*buf
, u_int8_t
*val
)
251 memcpy(buf
+ f
->offset
, val
, f
->len
);