1 /*
2 * binkleyforce -- unix FTN mailer project
3 *
4 * Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * $Id: u_ftn.c,v 1.1.1.1 2004/09/09 09:52:39 kstepanenkov Exp $
12 */
13
14 #include "includes.h"
15 #include "confread.h"
16 #include "logger.h"
17 #include "util.h"
18
19 #define ADDRNUM_MIN 0x0000
20 #define ADDRNUM_MAX 0x7fff
21
addrstr2int(const char * s)22 static int addrstr2int(const char *s)
23 {
24 int val = atoi(s);
25
26 if( val < ADDRNUM_MIN )
27 val = ADDRNUM_MIN;
28 else if( val > ADDRNUM_MAX )
29 val = ADDRNUM_MAX;
30
31 return val;
32 }
33
addrint2str(char * buffer,int val)34 char *addrint2str(char *buffer, int val)
35 {
36 if( val == -1 )
37 strcpy(buffer, "*");
38 else if( val < ADDRNUM_MIN )
39 strcpy(buffer, "MIN");
40 else if( val > ADDRNUM_MAX )
41 strcpy(buffer, "MAX");
42 else
43 sprintf(buffer, "%d", val);
44
45 return buffer;
46 }
47
ftn_addrparse_fido(s_faddr * addr,const char * s,bool wildcard)48 static int ftn_addrparse_fido(s_faddr *addr, const char *s, bool wildcard)
49 {
50 bool badaddr = 0;
51 bool stop = 0;
52 bool gotzone = 0;
53 bool gotnet = 0;
54 bool gotnode = 0;
55 bool gotpoint = 0;
56 const char *p = s;
57
58 ASSERT(s != NULL);
59
60 while( !stop && !badaddr )
61 {
62 switch(*p) {
63 case ':':
64 if( !gotzone && isdigit(*s) )
65 {
66 gotzone = 1;
67 addr->zone = addrstr2int(s);
68 s = ++p;
69 }
70 else if( !gotzone && wildcard && *s == '*' )
71 {
72 gotzone = 1;
73 addr->zone = -1;
74 s = ++p;
75 }
76 else badaddr = 1;
77 break;
78
79 case '/':
80 if( !gotnet && isdigit(*s) )
81 {
82 gotnet = 1;
83 addr->net = addrstr2int(s);
84 s = ++p;
85 }
86 else if( !gotnet && wildcard && *s == '*' )
87 {
88 gotnet = 1;
89 addr->net = -1;
90 s = ++p;
91 }
92 else if( *s != '/' ) badaddr = 1;
93 else ++p;
94 break;
95
96 case '.':
97 if( *s == '/' ) ++s;
98 if( !gotnode && isdigit(*s) )
99 {
100 gotnode = 1;
101 addr->node = addrstr2int(s);
102 s = ++p;
103 }
104 else if( !gotnode && wildcard && *s == '*' )
105 {
106 gotnode = 1;
107 addr->node = -1;
108 s = ++p;
109 }
110 else if( *s != '.' ) badaddr = 1;
111 else ++p;
112 break;
113
114 case '@':
115 case '\0':
116 if( gotzone && !gotnet ) { badaddr = 1; break; }
117
118 if( *s == '/' )
119 {
120 ++s;
121 if( !gotnode && isdigit(*s) )
122 {
123 gotnode = 1;
124 addr->node = addrstr2int(s);
125 }
126 else if( !gotnode && wildcard && *s == '*' )
127 {
128 gotnode = 1;
129 addr->node = -1;
130 }
131 else badaddr = 1;
132 }
133 else if( *s == '.' )
134 {
135 ++s;
136 if( !gotpoint && isdigit(*s) )
137 {
138 gotpoint = 1;
139 addr->point = addrstr2int(s);
140 }
141 else if( !gotpoint && wildcard && *s == '*' )
142 {
143 gotpoint = 1;
144 addr->point = -1;
145 }
146 else badaddr = 1;
147 }
148 else if( isdigit(*s) )
149 {
150 if( !gotnode )
151 {
152 gotnode = 1;
153 addr->node = addrstr2int(s);
154 }
155 else if( !gotpoint )
156 {
157 gotpoint = 1;
158 addr->point = addrstr2int(s);
159 }
160 else badaddr = 1;
161 }
162 else if( wildcard && *s == '*' )
163 {
164 if( !gotnode )
165 {
166 gotnode = 1;
167 addr->node = -1;
168 }
169 else if( !gotpoint )
170 {
171 gotpoint = 1;
172 addr->point = -1;
173 }
174 else badaddr = 1;
175 }
176 else badaddr = 1;
177 stop = 1;
178 break;
179
180 default:
181 if( isdigit(*p) || (wildcard && *p == '*') )
182 { ++p; }
183 else
184 { badaddr = 1; }
185 }
186 }
187
188 if( !badaddr && *p++ == '@' && *p )
189 {
190 strnxcpy(addr->domain, string_printable(p), sizeof(addr->domain));
191 }
192
193 return badaddr;
194 }
195
ftn_addrparse_inet(s_faddr * addr,const char * s,bool wildcard)196 static int ftn_addrparse_inet(s_faddr *addr, const char *s, bool wildcard)
197 {
198 bool badaddr = 0;
199 bool stop = 0;
200 bool gotzone = 0;
201 bool gotnet = 0;
202 bool gotnode = 0;
203 bool gotpoint = 0;
204 const char *p = s;
205
206 ASSERT(s != NULL);
207
208 while( !stop && !badaddr )
209 {
210 if( *p == '.' || *p == '\0' )
211 {
212 if( *p == '\0' ) stop = 1;
213
214 switch(*s++) {
215 case 'p':
216 case 'P':
217 if( !gotpoint && isdigit(*s) )
218 {
219 gotpoint = 1;
220 addr->point = addrstr2int(s);
221 s = ++p;
222 }
223 else badaddr = 1;
224 break;
225 case 'f':
226 case 'F':
227 if( !gotnet && !gotzone && !gotnode && isdigit(*s) )
228 {
229 gotnode = 1;
230 addr->node = addrstr2int(s);
231 s = ++p;
232 }
233 else badaddr = 1;
234 break;
235 case 'n':
236 case 'N':
237 if( gotnode && !gotzone && !gotnet && isdigit(*s) )
238 {
239 gotnet = 1;
240 addr->net = addrstr2int(s);
241 s = ++p;
242 }
243 else badaddr = 1;
244 break;
245 case 'z':
246 case 'Z':
247 if( gotnode && gotnet && !gotzone && isdigit(*s) )
248 {
249 gotzone = 1;
250 addr->zone = addrstr2int(s);
251 if( *p++ == '.' && *p )
252 {
253 strnxcpy(addr->domain, string_printable(p), sizeof(addr->domain));
254 }
255 stop = 1;
256 }
257 else badaddr = 1;
258 break;
259 default:
260 badaddr = 1;
261 break;
262 }
263 }
264 else
265 {
266 ++p;
267 }
268 }
269
270 return badaddr;
271 }
272
273 /*****************************************************************************
274 * Parse FTN address (can be specified in traditional form (X:X/X.X) as
275 * well as in domain form (pX.fX.nX.zX.domain))
276 *
277 * Arguments:
278 * addr we will put parsed address here
279 * s pointer to the null-terminated string with address
280 * wildcard set FALSE if you want forbid wildcards processing
281 *
282 * Return value:
283 * zero value if addres was parsed successfuly, and non-zero if wasn't
284 */
ftn_addrparse(s_faddr * addr,const char * s,bool wildcard)285 int ftn_addrparse(s_faddr *addr, const char *s, bool wildcard)
286 {
287 const char *p;
288 bool stop = 0;
289 bool badaddr = 0;
290
291 ASSERT(s != NULL);
292
293 memset(addr, '\0', sizeof(s_faddr));
294
295 /*
296 * Detect the address form (domain or traditional)
297 */
298 for( p = s; *p && !stop && !badaddr; p++ )
299 {
300 switch( *p ) {
301 case '*':
302 if( wildcard == FALSE ) badaddr = 1;
303 case '@':
304 stop = 1;
305 case ':':
306 case '/':
307 case '.':
308 addr->inetform = 0;
309 break;
310 case 'p':
311 case 'P':
312 case 'f':
313 case 'F':
314 addr->inetform = 1;
315 stop = 1;
316 break;
317 default:
318 if( !isdigit(*p) ) badaddr = 1;
319 }
320 }
321
322 if( !badaddr )
323 {
324 addr->zone = DEFAULT_ZONE;
325 addr->net = DEFAULT_NET;
326 addr->node = DEFAULT_NODE;
327 addr->point = 0;
328
329 if( addr->inetform )
330 badaddr = ftn_addrparse_inet(addr, s, wildcard);
331 else
332 badaddr = ftn_addrparse_fido(addr, s, wildcard);
333 }
334
335 return badaddr;
336 }
337
ftn_addrstr_fido(char * buf,s_faddr addr)338 char *ftn_addrstr_fido(char *buf, s_faddr addr)
339 {
340 char str1[10];
341 char str2[10];
342 char str3[10];
343 char str4[10];
344
345 if( addr.point )
346 {
347 sprintf(buf, "%s:%s/%s.%s",
348 addrint2str(str1, addr.zone), addrint2str(str2, addr.net),
349 addrint2str(str3, addr.node), addrint2str(str4, addr.point));
350 }
351 else
352 {
353 sprintf(buf, "%s:%s/%s",
354 addrint2str(str1, addr.zone), addrint2str(str2, addr.net),
355 addrint2str(str3, addr.node));
356 }
357
358 if( *addr.domain )
359 {
360 strnxcat(buf, "@", BF_MAXADDRSTR);
361 strnxcat(buf, addr.domain, BF_MAXADDRSTR);
362 }
363
364 return buf;
365 }
366
ftn_addrstr_inet(char * buf,s_faddr addr)367 char *ftn_addrstr_inet(char *buf, s_faddr addr)
368 {
369 char str1[10];
370 char str2[10];
371 char str3[10];
372 char str4[10];
373
374 if( addr.point )
375 {
376 sprintf(buf, "p%s.f%s.n%s.z%s",
377 addrint2str(str1, addr.point), addrint2str(str2, addr.node),
378 addrint2str(str3, addr.net), addrint2str(str4, addr.zone));
379 }
380 else
381 {
382 sprintf(buf, "f%s.n%s.z%s",
383 addrint2str(str1, addr.node), addrint2str(str2, addr.net),
384 addrint2str(str3, addr.zone));
385 }
386
387 if( *addr.domain )
388 {
389 strnxcat(buf, ".", BF_MAXADDRSTR);
390 strnxcat(buf, addr.domain, BF_MAXADDRSTR);
391 }
392
393 return buf;
394 }
395
396 /*****************************************************************************
397 * Put FTN address as the null-terminated string to the buffer
398 *
399 * Arguments:
400 * buf pointer to the destination buffer (must be at least
401 * BF_MAXADDRSTR bytes length)
402 * addr FTN address
403 *
404 * Return value:
405 * pointer to the buffer start
406 */
ftn_addrstr(char * buf,s_faddr addr)407 char *ftn_addrstr(char *buf, s_faddr addr)
408 {
409 ASSERT(buf != NULL);
410
411 return addr.inetform ? ftn_addrstr_inet(buf, addr)
412 : ftn_addrstr_fido(buf, addr);
413 }
414
415 /*****************************************************************************
416 * Compare two FTN addresses
417 *
418 * Arguments:
419 * addr1 first FTN address
420 * addr2 second FTN address
421 *
422 * Return value:
423 * zero value if addresses are equal, and non-zero if not
424 */
ftn_addrcomp(s_faddr addr1,s_faddr addr2)425 int ftn_addrcomp(s_faddr addr1, s_faddr addr2)
426 {
427 return !( addr1.zone == addr2.zone && addr1.net == addr2.net
428 && addr1.node == addr2.node && addr1.point == addr2.point );
429 }
430
431 /*****************************************************************************
432 * Compare two FTN addresses
433 *
434 * Arguments:
435 * addr1 first FTN address
436 * operator logical operator (EQ|GT|LT)
437 * addr2 second FTN address
438 *
439 * Return value:
440 * zero value if expression is true, and non-zero if not
441 */
ftn_addrcomp_logic(s_faddr addr1,int operator,s_faddr addr2)442 int ftn_addrcomp_logic(s_faddr addr1, int operator, s_faddr addr2)
443 {
444 int i;
445 int matr1[4] = { addr1.zone, addr1.net, addr1.node, addr1.point };
446 int matr2[4] = { addr2.zone, addr2.net, addr2.node, addr2.point };
447
448 for( i = 0; i < 4; i++ )
449 {
450 switch(operator) {
451 case ADDR_EQ:
452 if( matr1[i] != matr2[i] )
453 return 1;
454 break;
455 case ADDR_GT:
456 if( matr1[i] > matr2[i] )
457 return 0;
458 else if( matr1[i] < matr2[i] )
459 return 1;
460 break;
461 case ADDR_LT:
462 if( matr1[i] < matr2[i] )
463 return 0;
464 else if( matr1[i] > matr2[i] )
465 return 1;
466 break;
467 default:
468 ASSERT(0);
469 }
470 }
471
472 return 0;
473 }
474 /*****************************************************************************
475 * Compare two FTN addresses (second address can contain wildcards)
476 *
477 * Arguments:
478 * addr first FTN address
479 * mask second FTN address (with wildcards)
480 *
481 * Return value:
482 * zero value if addresses are equal, and non-zero if not
483 */
ftn_addrcomp_mask(s_faddr addr,s_faddr mask)484 int ftn_addrcomp_mask(s_faddr addr, s_faddr mask)
485 {
486 return !( (addr.zone == mask.zone || mask.zone == -1)
487 && (addr.net == mask.net || mask.net == -1)
488 && (addr.node == mask.node || mask.node == -1)
489 && (addr.point == mask.point || mask.point == -1) );
490 }
491
492 /*****************************************************************************
493 * Get the metric of matching two addresses
494 *
495 * Arguments:
496 * addr1 first FTN address
497 * addr2 second FTN address
498 *
499 * Return value:
500 * from 0 to 4 (0 - no matching, 4 - equal addresses)
501 */
ftn_addrsmetric(s_faddr addr1,s_faddr addr2)502 int ftn_addrsmetric(s_faddr addr1, s_faddr addr2)
503 {
504 int metric = 0;
505
506 if( addr1.zone == addr2.zone )
507 {
508 ++metric;
509 if( addr1.net == addr2.net )
510 {
511 ++metric;
512 if( addr1.node == addr2.node )
513 {
514 ++metric;
515 if( addr1.point == addr2.point )
516 {
517 ++metric;
518 }
519 }
520 }
521 }
522
523 return metric;
524 }
525
526