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