xref: /freebsd/sbin/ipf/libipf/ipft_hx.c (revision 2e3f49888ec8851bafb22011533217487764fdb0)
1 
2 /*
3  * Copyright (C) 2012 by Darren Reed.
4  *
5  * See the IPFILTER.LICENCE file for details on licencing.
6  */
7 
8 #include <ctype.h>
9 
10 #include "ipf.h"
11 #include "ipt.h"
12 
13 
14 extern	int	opts;
15 
16 static	int	hex_open(char *);
17 static	int	hex_close(void);
18 static	int	hex_readip(mb_t *, char **, int *);
19 static	char	*readhex(char *, char *);
20 
21 struct	ipread	iphex = { hex_open, hex_close, hex_readip, 0 };
22 static	FILE	*tfp = NULL;
23 static	int	tfd = -1;
24 
25 static int
26 hex_open(char *fname)
27 {
28 	if (tfp && tfd != -1) {
29 		rewind(tfp);
30 		return (tfd);
31 	}
32 
33 	if (!strcmp(fname, "-")) {
34 		tfd = 0;
35 		tfp = stdin;
36 	} else {
37 		tfd = open(fname, O_RDONLY);
38 		if (tfd != -1)
39 			tfp = fdopen(tfd, "r");
40 	}
41 	return (tfd);
42 }
43 
44 
45 static int
46 hex_close(void)
47 {
48 	int	cfd = tfd;
49 
50 	tfd = -1;
51 	return (close(cfd));
52 }
53 
54 
55 static int
56 hex_readip(mb_t *mb, char **ifn, int *dir)
57 {
58 	register char *s, *t, *u;
59 	char	line[513];
60 	ip_t	*ip;
61 	char	*buf;
62 
63 	buf = (char *)mb->mb_buf;
64 	/*
65 	 * interpret start of line as possibly "[ifname]" or
66 	 * "[in/out,ifname]".
67 	 */
68 	if (ifn)
69 		*ifn = NULL;
70 	if (dir)
71 		*dir = 0;
72  	ip = (ip_t *)buf;
73 	while (fgets(line, sizeof(line)-1, tfp)) {
74 		if ((s = strchr(line, '\n'))) {
75 			if (s == line) {
76 				mb->mb_len = (char *)ip - buf;
77 				return (mb->mb_len);
78 			}
79 			*s = '\0';
80 		}
81 		if ((s = strchr(line, '#')))
82 			*s = '\0';
83 		if (!*line)
84 			continue;
85 		if ((opts & OPT_DEBUG) != 0) {
86 			printf("input: %s", line);
87 		}
88 
89 		if ((*line == '[') && (s = strchr(line, ']'))) {
90 			t = line + 1;
91 			if (s - t > 0) {
92 				*s++ = '\0';
93 				if ((u = strchr(t, ',')) && (u < s)) {
94 					u++;
95 					if (ifn)
96 						*ifn = strdup(u);
97 					if (dir) {
98 						if (*t == 'i')
99 							*dir = 0;
100 						else if (*t == 'o')
101 							*dir = 1;
102 					}
103 				} else if (ifn)
104 					*ifn = t;
105 			}
106 
107 			while (*s++ == '+') {
108 				if (!strncasecmp(s, "mcast", 5)) {
109 					mb->mb_flags |= M_MCAST;
110 					s += 5;
111 				}
112 				if (!strncasecmp(s, "bcast", 5)) {
113 					mb->mb_flags |= M_BCAST;
114 					s += 5;
115 				}
116 				if (!strncasecmp(s, "mbcast", 6)) {
117 					mb->mb_flags |= M_MBCAST;
118 					s += 6;
119 				}
120 			}
121 			while (ISSPACE(*s))
122 				s++;
123 		} else
124 			s = line;
125 		t = (char *)ip;
126 		ip = (ip_t *)readhex(s, (char *)ip);
127 		if ((opts & OPT_DEBUG) != 0) {
128 			if (opts & OPT_ASCII) {
129 				int c = *t;
130 				if (t < (char *)ip)
131 					putchar('\t');
132 				while (t < (char *)ip) {
133 					if (isprint(c) && isascii(c))
134 						putchar(c);
135 					else
136 						putchar('.');
137 					t++;
138 				}
139 			}
140 			putchar('\n');
141 			fflush(stdout);
142 		}
143 	}
144 	if (feof(tfp))
145 		return (0);
146 	return (-1);
147 }
148 
149 
150 static char
151 *readhex(register char *src, register char *dst)
152 {
153 	int	state = 0;
154 	char	c;
155 
156 	while ((c = *src++)) {
157 		if (ISSPACE(c)) {
158 			if (state) {
159 				dst++;
160 				state = 0;
161 			}
162 			continue;
163 		} else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
164 			   (c >= 'A' && c <= 'F')) {
165 			c = ISDIGIT(c) ? (c - '0') : (TOUPPER(c) - 55);
166 			if (state == 0) {
167 				*dst = (c << 4);
168 				state++;
169 			} else {
170 				*dst++ |= c;
171 				state = 0;
172 			}
173 		} else
174 			break;
175 	}
176 	return (dst);
177 }
178