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