1 /*
2 * parsers.c
3 *
4 * $Id: ftypes.c,v 1.3 2006/02/20 08:02:24 andrzej Exp $
5 *
6 * Redboot Flash Configuration parser.
7 * Argument parsers.
8 *
9 * Copyright (C) 2006 Ekiert sp z o.o.
10 * Author: Andrzej Ekiert <a.ekiert@ekiert.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18 /* For inet_aton() and inet_ntoa() */
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22
23 /* For ether_aton */
24 #if defined(__FreeBSD__)
25 #include <sys/types.h>
26 #include <net/ethernet.h>
27 #else
28 #include <net/ethernet.h>
29 #include <netinet/ether.h>
30 #endif
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <stddef.h>
35 #include <stdint.h>
36 #include <string.h>
37 #include <errno.h>
38
39 #include "ftypes.h"
40 #include "debug.h"
41
42 /*
43 * The table of all supported types.
44 */
45 type_t types[NUM_TYPES] = {
46 {"empty", SIZE_EMPTY, NULL, NULL},
47 {"bool", SIZE_BOOL, parse_bool, print_bool},
48 {"int", SIZE_INT, parse_int, print_int},
49 {"string", SIZE_STRING, parse_string, print_string},
50 {"script", SIZE_SCRIPT, parse_script, print_script},
51 {"ip", SIZE_IP, parse_ip, print_ip},
52 {"esa", SIZE_ESA, parse_esa, print_esa},
53 {"netport", SIZE_NETPORT, parse_netport, print_netport}
54 };
55
verify_ftype(uint8_t type)56 int8_t verify_ftype(uint8_t type)
57 {
58 return (type < NUM_TYPES);
59 }
60
61 /* All parsers return non-zero code on failure */
62
63 /*
64 * Convert a string to a boolean.
65 * Buffer 'buf' must be at least 4 bytes long and aligned for uint32_t.
66 */
parse_bool(uint8_t * text,void * buf)67 int8_t parse_bool(uint8_t *text, void *buf)
68 {
69 if (strcasecmp(text, "TRUE")==0) {
70 *(uint32_t*)buf = 1;
71 return 0;
72 } else if (strcasecmp(text, "FALSE")==0) {
73 *(uint32_t*)buf = 0;
74 return 0;
75 } else {
76 return -1;
77 }
78 return 0;
79 }
80
81 /*
82 * Print 'TRUE' or 'FALSE'.
83 */
print_bool(void * buf)84 void print_bool(void *buf)
85 {
86 uint32_t val;
87 memcpy(&val, buf, sizeof(val));
88
89 if (val) {
90 printf("TRUE");
91 } else {
92 printf("FALSE");
93 }
94 }
95
96 /*
97 * Convert a string to a 32 bit unsigned integer.
98 * Buffer 'buf' must be at least 4 bytes long and aligned for uint32_t.
99 */
parse_int(uint8_t * text,void * buf)100 int8_t parse_int(uint8_t *text, void *buf)
101 {
102 errno = 0;
103 *(uint32_t*)buf = strtoul(text, (char**)NULL, 0);
104 return errno;
105 }
106
107 /*
108 * Print a 32 bit unsigned integer.
109 * 'buf' should point to such integer.
110 */
print_int(void * buf)111 void print_int(void *buf)
112 {
113 uint32_t val;
114 memcpy(&val, buf, sizeof(val));
115 printf("%d", val);
116 }
117
118 /*
119 * Parsing a string is nothing but copying up to MAX_STRING_LENGTH-1 characters
120 * from 'text' to 'buf'. Copying fails, if the result is not null-terminated.
121 */
parse_string(uint8_t * text,void * buf)122 int8_t parse_string(uint8_t *text, void *buf)
123 {
124 uint8_t *dest = (uint8_t*)buf;
125 dest[MAX_STRING_LENGTH-1]='\0';
126 strncpy(dest, text, MAX_STRING_LENGTH);
127 if (dest[MAX_STRING_LENGTH-1]!='\0') {
128 dest[MAX_STRING_LENGTH-1]='\0';
129 return -1;
130 }
131 return 0;
132 }
133
134 /*
135 * Print a string.
136 */
print_string(void * buf)137 void print_string(void *buf)
138 {
139 uint8_t *str = (uint8_t*)buf;
140 printf("%s", str);
141 }
142
143 /*
144 * Parsing a script is nothing but copying up to MAX_SCRIPT_LENGTH-1 characters
145 * from 'text' to 'buf', except that all '\' characters replaced with newlines.
146 * Copying fails, if the result is not null-terminated.
147 * Returns 0 on failure.
148 */
parse_script(uint8_t * text,void * buf)149 int8_t parse_script(uint8_t *text, void *buf)
150 {
151 uint8_t *dest = (uint8_t*)buf;
152 dest[MAX_SCRIPT_LENGTH-1]='\0';
153 strncpy(dest, text, MAX_SCRIPT_LENGTH);
154 if (dest[MAX_SCRIPT_LENGTH-1]!='\0') {
155 dest[MAX_SCRIPT_LENGTH-1]='\0';
156 return -1;
157 }
158 while (*dest!='\0') {
159 if (*dest == '\\') {
160 *dest = '\n';
161 }
162 dest++;
163 }
164 return 0;
165 }
166
167 /*
168 * Print a script.
169 */
print_script(void * buf)170 void print_script(void *buf)
171 {
172 uint8_t *str = (uint8_t*)buf;
173 printf("%s", str);
174 }
175
176 /*
177 * Convert dotted-decimal IPv4 address string into binary data.
178 * Buffer 'buf' must be able to hold 'struct in_addr' (4 bytes currently).
179 * The buffer must be aligned.
180 */
parse_ip(uint8_t * text,void * buf)181 int8_t parse_ip(uint8_t *text, void *buf)
182 {
183 return !inet_aton(text, buf);
184 }
185
186 /*
187 * Print an IPv4 address in dotted-decimal notation.
188 */
print_ip(void * buf)189 void print_ip(void *buf)
190 {
191 struct in_addr addr;
192 memcpy(&addr, buf, sizeof(addr));
193 printf("%s", inet_ntoa(addr));
194 }
195
196 /*
197 * Convert a string containing ethernet MAC address
198 * in a "01:23:45:67:89:ab" form to a 6 byte table.
199 * Buffer 'buf' must be able to hold 'struct ether_addr' (6 bytes currently).
200 */
parse_esa(uint8_t * text,void * buf)201 int8_t parse_esa(uint8_t *text, void *buf)
202 {
203 struct ether_addr *addr = ether_aton(text);
204 if (addr == NULL) {
205 return -1;
206 }
207 memcpy(buf, addr, sizeof(struct ether_addr));
208 return 0;
209 }
210
211 /*
212 * Convert to a standard colon-separated string and print
213 * an ethernet MAC address.
214 */
print_esa(void * buf)215 void print_esa(void *buf)
216 {
217 uint8_t *e = (uint8_t*)buf;
218 printf("%02x:%02x:%02x:%02x:%02x:%02x",
219 e[0], e[1], e[2], e[3], e[4], e[5]);
220 }
221
222 /*
223 * Parse 'netport' name.
224 * 'NETPORT' is just a string.
225 */
parse_netport(uint8_t * text,void * buf)226 int8_t parse_netport(uint8_t *text, void *buf)
227 {
228 return parse_string(text, buf);
229 }
230
231 /*
232 * Print 'netport' name.
233 * 'NETPORT' is just a string.
234 */
print_netport(void * buf)235 void print_netport(void *buf)
236 {
237 print_string(buf);
238 }
239
240