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