ucspi-tcp6 1.13.02
ucspi-tcp6
Loading...
Searching...
No Matches
tcprules.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "logmsg.h"
3#include "stralloc.h"
4#include "getln.h"
5#include "buffer.h"
6#include "exit.h"
7#include "fmt.h"
8#include "byte.h"
9#include "cdbmake.h"
10#include "ip.h"
11#include "scan.h"
12#include "open.h"
13#include "ip_bit.h"
14
15#define WHO "tcprules"
16
17extern int rename(const char *,const char *); /* declared in stdio, ugh */
18
19unsigned long linenum = 0;
20char *fntemp;
21char *fn;
22
23stralloc line = {0};
24int match = 1;
25
26stralloc address = {0};
27stralloc ipstring = {0};
28stralloc data = {0};
29stralloc key = {0};
30
31struct cdb_make c;
32
33void nomem(void) {
34 logmsg(WHO,111,FATAL,"out of memory");
35}
36
37void usage(void) {
38 logmsg(WHO,100,USAGE,"tcprules rules.cdb rules.tmp");
39}
40
41void die_bad(void) {
42 if (!stralloc_0(&line)) nomem();
43 logmsg(WHO,101,SYNTAX,B("unable to parse this line: ",line.s));
44}
45
46void die_write(void) {
47 logmsg(WHO,111,FATAL,B("unable to write to: ",fntemp));
48}
49
50void die_length(void) {
51 if (!stralloc_0(&line)) nomem();
52 logmsg(WHO,101,SYNTAX,B("invalid prefix length on line: ",line.s));
53}
54
55void die_ip(void) {
56 if (!stralloc_0(&line)) nomem();
57 logmsg(WHO,101,SYNTAX,B("invalid address on line: ",line.s));
58}
59void die_ip4c(void) {
60 if (!stralloc_0(&line)) nomem();
61 logmsg(WHO,101,SYNTAX,B("invalid IPv4 CIDR address on line: ",line.s));
62}
63void die_ip6(void) {
64 if (!stralloc_0(&line)) nomem();
65 logmsg(WHO,101,SYNTAX,B("invalid IPv6 address: on line: ",line.s));
66}
67void die_ip6c(void) {
68 if (!stralloc_0(&line)) nomem();
69 logmsg(WHO,101,SYNTAX,B("invalid IPv6 CIDR address on line: ",line.s));
70}
71
72static char strnum[FMT_ULONG];
73static stralloc sanum = {0};
74
75void getnum(char *buf, int len, unsigned long *u) {
76 if (!stralloc_copyb(&sanum,buf,len)) nomem();
77 if (!stralloc_0(&sanum)) nomem();
78 if (sanum.s[scan_ulong(sanum.s,u)]) die_bad();
79}
80
81void doaddressdata(void) {
82 int i;
83 int ipv6 = 0;
84 int cidr = 0;
85 int info = 0;
86 int left;
87 int right;
88 unsigned long bot;
89 unsigned long top;
90 unsigned long prefix;
91 stralloc ip6address = {0};
92
93 if (byte_chr(address.s,address.len,'=') < address.len) goto CDB;
94 if (byte_chr(address.s,address.len,':') < address.len) ipv6 = 1;
95 if (byte_chr(address.s,address.len,'/') < address.len) cidr = 1;
96 if (byte_chr(address.s,address.len,'@') < address.len) info = 1;
97
98 if (info) {
99 if (ipv6 && !cidr) {
100 i = byte_chr(address.s,address.len,'@');
101 if (!stralloc_copyb(&key,address.s,i)) nomem();
102 if (!stralloc_cats(&key,"@")) nomem();
103 if (!stralloc_copyb(&ipstring,address.s + i + 1,address.len - i - 1)) nomem();
104 if (!stralloc_0(&ipstring)) nomem();
105 if (!ip6_fmt_str(&ip6address,ipstring.s)) {
106 if (!stralloc_catb(&key,ip6address.s,ip6address.len)) nomem();
107 if (cdb_make_add(&c,key.s,key.len,data.s,data.len) == -1) die_write();
108 return;
109 }
110 else
111 die_ip6();
112 }
113 goto CDB;
114 }
115
116 if (!ipv6) {
117 if (cidr) {
118 i = byte_chr(address.s,address.len,'/');
119 getnum(address.s + i + 1,address.len - i - 1,&prefix);
120 if (prefix > 32 || prefix <= 0) die_length();
121 address.s[i] = '\0';
122
123 switch (ip4_bitstring(&ipstring,address.s,prefix)) {
124 case -1: nomem();
125 case 0: if (!stralloc_copys(&key,"_")) nomem();
126 if (!stralloc_catb(&key,ipstring.s,ipstring.len)) nomem();
127 if (cdb_make_add(&c,key.s,key.len,data.s,data.len) == -1) die_write();
128 break;
129 case 1: die_ip4c();
130 }
131 return;
132 }
133 else if ((i = byte_chr(address.s,address.len,'-')) < address.len) {
134 left = byte_rchr(address.s,i,'.');
135 if (left == i) left = 0; else ++left;
136
137 ++i;
138 right = i + byte_chr(address.s + i,address.len - i,'.');
139
140 getnum(address.s + left,i - 1 - left,&bot);
141 getnum(address.s + i,right - i,&top);
142 if (top > 255) top = 255;
143 while (bot <= top) {
144 if (!stralloc_copyb(&key,address.s,left)) nomem();
145 if (!stralloc_catb(&key,strnum,fmt_ulong(strnum,bot))) nomem();
146 if (!stralloc_catb(&key,address.s + right,address.len - right)) nomem();
147 if (cdb_make_add(&c,key.s,key.len,data.s,data.len) == -1) die_write();
148 ++bot;
149 }
150 return;
151 }
152 }
153
154 if (ipv6) {
155 if (cidr) {
156 i = byte_chr(address.s,address.len,'/');
157 getnum(address.s + i + 1,address.len - i - 1,&prefix);
158 if (prefix > 128 ) die_length();
159 switch (ip6_bitstring(&ipstring,address.s,prefix)) {
160 case -1: nomem();
161 case 0: if (!stralloc_copys(&key,"^")) nomem();
162 if (!stralloc_catb(&key,ipstring.s,ipstring.len)) nomem();
163 if (cdb_make_add(&c,key.s,key.len,data.s,data.len) == -1) die_write();
164 break;
165 case 1: die_ip6c();
166 }
167 return;
168 }
169 else {
170 if (!stralloc_copyb(&ipstring,address.s,address.len)) nomem();
171 if (!stralloc_0(&ipstring)) nomem();
172 switch (ip6_fmt_str(&ip6address,ipstring.s)) {
173 case -1: nomem();
174 case 0: if (cdb_make_add(&c,ip6address.s,ip6address.len,data.s,data.len) == -1)
175 die_write();
176 break;
177 case 1: die_ip6();
178 }
179 return;
180 }
181 }
182
183 CDB:
184 if (cdb_make_add(&c,address.s,address.len,data.s,data.len) == -1) die_write();
185 return;
186}
187
188int main(int argc,char * const *argv) {
189 int colon;
190 char *x;
191 int len;
192 int fd;
193 int i;
194 char ch;
195
196 fn = argv[1];
197 if (!fn) usage();
198 fntemp = argv[2];
199 if (!fntemp) usage();
200
201 fd = open_trunc(fntemp);
202 if (fd == -1)
203 logmsg(WHO,111,ERROR,B("unable to create: ",fntemp));
204 if (cdb_make_start(&c,fd) == -1) die_write();
205
206 while (match) {
207 if (getln(buffer_0,&line,&match,'\n') == -1)
208 logmsg(WHO,111,FATAL,"unable to read input");
209
210 x = line.s;
211 len = line.len;
212
213 if (!len) break;
214 if (x[0] == '#') continue; /* ignore comments */
215 if (x[0] == '\n') continue; /* ignore empty lines */
216
217 while (len) {
218 ch = x[len - 1];
219 if (ch != '\n') if (ch != ' ') if (ch != '\t') break;
220 --len;
221 }
222 line.len = len; /* for die_bad() */
223
224/* Need to distinguish between IPv(4|6) address and FQDN ... */
225
226 i = byte_chr(x,len,','); /* environment variables start */
227 colon = byte_rchr(x,i,':');
228
229 if (colon == len) continue;
230
231 if (!stralloc_copyb(&address,x,colon)) nomem();
232 if (!stralloc_copys(&data,"")) nomem();
233
234 x += colon + 1; len -= colon + 1;
235
236 if ((len >= 4) && byte_equal(x,4,"deny")) {
237 if (!stralloc_catb(&data,"D",2)) nomem();
238 x += 4; len -= 4;
239 }
240 else if ((len >= 5) && byte_equal(x,5,"allow")) {
241 x += 5; len -= 5;
242 }
243 else
244 die_bad();
245
246 while (len)
247 switch (*x) {
248 case ',': i = byte_chr(x,len,'=');
249 if (i == len) die_bad();
250 if (!stralloc_catb(&data,"+",1)) nomem();
251 if (!stralloc_catb(&data,x + 1,i)) nomem();
252 x += i + 1; len -= i + 1;
253 if (!len) die_bad();
254 ch = *x;
255 x += 1; len -= 1;
256 i = byte_chr(x,len,ch);
257 if (i == len) die_bad();
258 if (!stralloc_catb(&data,x,i)) nomem();
259 if (!stralloc_0(&data)) nomem();
260 x += i + 1; len -= i + 1;
261 break;
262 default: die_bad();
263 }
264
266 }
267
268 if (cdb_make_finish(&c) == -1) die_write();
269 if (fsync(fd) == -1) die_write();
270 if (close(fd) == -1) die_write(); /* NFS stupidity */
271 if (rename(fntemp,fn))
272 logmsg(WHO,111,ERROR,B("unable to move ",fntemp," to: ",fn));
273
274 _exit(0);
275}
void die_write(void)
Definition: tcprules.c:46
stralloc key
Definition: tcprules.c:29
void die_ip6c(void)
Definition: tcprules.c:67
void die_length(void)
Definition: tcprules.c:50
stralloc ipstring
Definition: tcprules.c:27
unsigned long linenum
Definition: tcprules.c:19
void die_bad(void)
Definition: tcprules.c:41
int rename(const char *, const char *)
stralloc address
Definition: tcprules.c:26
void nomem(void)
Definition: tcprules.c:33
stralloc data
Definition: tcprules.c:28
void die_ip4c(void)
Definition: tcprules.c:59
void die_ip(void)
Definition: tcprules.c:55
void die_ip6(void)
Definition: tcprules.c:63
void doaddressdata(void)
Definition: tcprules.c:81
stralloc line
Definition: tcprules.c:23
struct cdb_make c
Definition: tcprules.c:31
char * fn
Definition: tcprules.c:21
char * fntemp
Definition: tcprules.c:20
int match
Definition: tcprules.c:24
#define WHO
Definition: tcprules.c:15
void usage(void)
Definition: tcprules.c:37
void getnum(char *buf, int len, unsigned long *u)
Definition: tcprules.c:75
int main()
Definition: addcr.c:4
int ip6_bitstring(stralloc *ip6string, char *ip6addr, unsigned int prefix)
Definition: ip6_bit.c:48
unsigned int ip6_fmt_str(stralloc *dest, char *src)
Definition: ip6_bit.c:161
int ip4_bitstring(stralloc *ip4string, char *ip, unsigned int prefix)
Definition: ip4_bit.c:26
int close(int)