1 /*:ts=8*/
2 /*****************************************************************************
3 * FIDOGATE --- Gateway UNIX Mail/News <-> FTN NetMail/EchoMail
4 *
5 *
6 * FTN-FTN gateway for NetMail, using the %Z:N/F.P addressing in the
7 * from/to fields.
8 *****************************************************************************
9 * Copyright (C) 1990-2002
10 * _____ _____
11 * | |___ | Martin Junius <mj@fidogate.org>
12 * | | | | | | Radiumstr. 18
13 * |_|_|_|@home| D-51069 Koeln, Germany
14 *
15 * This file is part of FIDOGATE.
16 *
17 * FIDOGATE is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2, or (at your option) any
20 * later version.
21 *
22 * FIDOGATE is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with FIDOGATE; see the file COPYING. If not, write to the Free
29 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30 *****************************************************************************/
31
32 #include "fidogate.h"
33 #include "getopt.h"
34
35 #define PROGRAM "ftn2ftn"
36 #define CONFIG DEFAULT_CONFIG_MAIN
37
38 /*
39 * Prototypes
40 */
41 void add_via(Textlist *, Node *);
42 int do_message(Node *, Message *, MsgBody *);
43 int unpack(Node *, FILE *, Packet *);
44 int unpack_file(Node *, char *);
45 int do_outbound(Node *, Node *);
46
47 void short_usage(void);
48 void usage(void);
49
50 static char *o_flag = NULL; /* -o --out-packet-file option */
51
52 /*
53 * Zone gate addresses
54 */
55 Node gate_a; /* FTN address in network A */
56 Node gate_b; /* FTN address in network B */
57 static bool strict;
58
59 /*
60 * Add our ^AVia line
61 */
add_via(Textlist * list,Node * gate)62 void add_via(Textlist * list, Node * gate)
63 {
64 #ifndef FTS_VIA
65 tl_appendf(list, "\001Via FIDOGATE/%s %s, %s\r",
66 PROGRAM, znf1(gate), date(DATE_VIA, NULL));
67 #else
68 tl_appendf(list, "\001Via %s @%s FIDOGATE/%s\r",
69 znf1(gate), date(DATE_VIA, NULL), PROGRAM);
70 #endif /* FTS_VIA */
71 }
72
73 /*
74 * Process one message for zone gate
75 */
do_message(Node * gate,Message * msg,MsgBody * body)76 int do_message(Node * gate, Message * msg, MsgBody * body)
77 {
78 static int last_zone = -1;
79 static FILE *fp;
80 char *from, *to;
81 char *p;
82 Node node;
83
84 from = msg->name_from;
85 to = msg->name_to;
86
87 debug(3, "Message to: %s", to);
88
89 p = strrchr(to, '%');
90 if (!p)
91 p = strrchr(to, '@');
92
93 /*
94 * Check for EchoMail
95 */
96 if (body->area) {
97 fglog("ftn2ftn: skipping EchoMail");
98 return ERROR;
99 }
100
101 /*
102 * Gateway addressing with "User Name%Z:N/F.P"
103 * "User Name@Z:N/F.P" found. Get address and push
104 * to the other side.
105 */
106 if (p && asc_to_node(p + 1, &node, FALSE) == OK) {
107 cf_set_zone(gate->zone);
108
109 /* Add gate addresses to ^Via lines */
110 add_via(&body->via, &msg->node_to);
111 add_via(&body->via, gate);
112
113 /* Strip % addressing */
114 *p = 0;
115 /* Add sender address to from name */
116 BUF_COPY2(buffer, "%", znf1(&msg->node_from));
117 if (strlen(from) + strlen(buffer) > MSG_MAXNAME - 1)
118 from[MSG_MAXNAME - 1 - strlen(buffer)] = 0;
119 str_append(from, MSG_MAXNAME, buffer);
120 /* Readdress */
121 msg->node_from = *gate;
122 msg->node_to = node;
123 }
124 /*
125 * Local message, simply readdress to our main AKA
126 */
127 else {
128 cf_set_zone(msg->node_to.zone);
129
130 /* Add gate addresses to ^Via lines */
131 add_via(&body->via, &msg->node_to);
132
133 /* Readdress */
134 msg->node_to = cf_n_addr();
135 }
136
137 /*
138 * Write this message to the output packet
139 */
140 if (!o_flag && cf_zone() != last_zone)
141 pkt_close();
142 if (!pkt_isopen())
143 if ((fp = pkt_open(o_flag, NULL, NULL, FALSE)) == NULL)
144 return ERROR;
145 last_zone = cf_zone();
146
147 msg->area = NULL;
148 if (pkt_put_msg_hdr(fp, msg, TRUE) != OK)
149 return ERROR;
150 if (msg_put_msgbody(fp, body) != OK)
151 return ERROR;
152
153 return OK;
154 }
155
156 /*
157 * Unpack and process messages
158 */
unpack(Node * gate,FILE * pkt_file,Packet * pkt)159 int unpack(Node * gate, FILE * pkt_file, Packet * pkt)
160 {
161 Message msg = { 0 };
162 Textlist tl;
163 MsgBody body;
164 int type;
165
166 tl_init(&tl);
167 msg_body_init(&body);
168
169 type = pkt_get_int16(pkt_file);
170 while ((type == MSG_TYPE) && !xfeof(pkt_file)) {
171 msg.node_from = pkt->from;
172 msg.node_to = pkt->to;
173 if (pkt_get_msg_hdr(pkt_file, &msg, strict) == ERROR)
174 TMPS_RETURN(ERROR);
175
176 if (pkt_get_body_parse(pkt_file, &body, &msg.node_from, &msg.node_to) !=
177 OK) {
178 fglog("ftn2ftn: error parsing message body");
179 TMPS_RETURN(ERROR);
180 }
181 /* Retrieve address information from body */
182 kludge_pt_intl(&body, &msg, TRUE);
183
184 if (do_message(gate, &msg, &body) != OK)
185 TMPS_RETURN(ERROR);
186 }
187
188 /* Close packet */
189 pkt_close();
190
191 TMPS_RETURN(OK);
192 }
193
194 /*
195 * Unpack one packet file
196 */
unpack_file(Node * gate,char * pkt_name)197 int unpack_file(Node * gate, char *pkt_name)
198 {
199 Packet pkt;
200 FILE *pkt_file;
201
202 debug(1, "Unpacking FTN packet %s", pkt_name);
203
204 /*
205 * Open packet and read header
206 */
207 pkt_file = fopen(pkt_name, R_MODE);
208 if (!pkt_file) {
209 fglog("$Can't open packet %s", pkt_name);
210 exit_free();
211 exit(EX_OSERR);
212 }
213 if (pkt_get_hdr(pkt_file, &pkt) == ERROR) {
214 fglog("Error reading header from %s", pkt_name);
215 exit_free();
216 exit(EX_OSERR);
217 }
218
219 /*
220 * Unpack it
221 */
222 if (unpack(gate, pkt_file, &pkt) != OK) {
223 fclose(pkt_file);
224 fglog("Error in unpacking %s", pkt_name);
225 exit_free();
226 exit(EX_OSERR);
227 }
228
229 fclose(pkt_file);
230
231 if (unlink(pkt_name)) {
232 fglog("$Could not unlink packet %s", pkt_name);
233 exit_free();
234 exit(EX_OSERR);
235 }
236
237 return OK;
238 }
239
240 /*
241 * Process packet for gateway address in Binkley outbound
242 */
do_outbound(Node * gate_outb,Node * gate_other)243 int do_outbound(Node * gate_outb, Node * gate_other)
244 {
245 char *name;
246
247 /* Create BSY file */
248 if (bink_bsy_create(gate_outb, NOWAIT) == ERROR)
249 return ERROR;
250
251 /* Find and process OUT packet file */
252 if ((name = bink_find_out(gate_outb, NULL)))
253 unpack_file(gate_other, name);
254
255 /* Delete BSY file */
256 if (bink_bsy_delete(gate_outb) == ERROR)
257 return ERROR;
258
259 return OK;
260 }
261
262 /*
263 * Usage messages
264 */
short_usage(void)265 void short_usage(void)
266 {
267 fprintf(stderr, "usage: %s [-options] [packet ...]\n", PROGRAM);
268 fprintf(stderr, " %s --help for more information\n", PROGRAM);
269 }
270
usage(void)271 void usage(void)
272 {
273 fprintf(stderr, "FIDOGATE %s %s %s\n\n",
274 version_global(), PROGRAM, version_local(VERSION));
275
276 fprintf(stderr, "usage: %s [-options] [packet ...]\n\n", PROGRAM);
277 fprintf(stderr, "\
278 options: -A --address-a Z:N/F.P FTN address in network A\n\
279 -B --address-b Z:N/F.P FTN address in network B\n\
280 -o --out-packet-file NAME set output packet file name\n\
281 -O --out-packet-dir NAME set output packet directory\n\
282 \n\
283 -v --verbose more verbose\n\
284 -h --help this help\n\
285 -c --config name read config file (\"\" = none)\n\
286 -a --addr Z:N/F.P set FTN address\n\
287 -u --uplink-addr Z:N/F.P set FTN uplink address\n");
288
289 exit(0);
290 }
291
292 /***** main() ****************************************************************/
293
main(int argc,char ** argv)294 int main(int argc, char **argv)
295 {
296 int c;
297 char *O_flag = NULL;
298 char *c_flag = NULL;
299 char *a_flag = NULL, *u_flag = NULL;
300
301 int option_index;
302 static struct option long_options[] = {
303 {"address-a", 1, 0, 'A'}, /* Address A */
304 {"address-b", 1, 0, 'B'}, /* Address B */
305 {"out-packet-file", 1, 0, 'o'}, /* Set packet file name */
306 {"out-dir", 1, 0, 'O'}, /* Set packet directory */
307
308 {"verbose", 0, 0, 'v'}, /* More verbose */
309 {"help", 0, 0, 'h'}, /* Help */
310 {"config", 1, 0, 'c'}, /* Config file */
311 {"addr", 1, 0, 'a'}, /* Set FIDO address */
312 {"uplink-addr", 1, 0, 'u'}, /* Set FIDO uplink address */
313 {0, 0, 0, 0}
314 };
315
316 log_program(PROGRAM);
317
318 /* Init configuration */
319 cf_initialize();
320
321 while ((c = getopt_long(argc, argv, "A:B:o:O:vhc:a:u:",
322 long_options, &option_index)) != EOF)
323 switch (c) {
324 /***** ftn2ftn options *****/
325 case 'A':
326 if (asc_to_node(optarg, &gate_a, FALSE) != OK) {
327 fprintf(stderr, "%s: option -A: illegal address %s\n",
328 PROGRAM, optarg);
329 exit_free();
330 exit(EX_USAGE);
331 }
332 break;
333 case 'B':
334 if (asc_to_node(optarg, &gate_b, FALSE) != OK) {
335 fprintf(stderr, "%s: option -B: illegal address %s\n",
336 PROGRAM, optarg);
337 exit_free();
338 exit(EX_USAGE);
339 }
340 break;
341 case 'o':
342 /* Set packet file name */
343 o_flag = optarg;
344 break;
345 case 'O':
346 /* Set packet dir */
347 O_flag = optarg;
348 break;
349
350 /***** Common options *****/
351 case 'v':
352 verbose++;
353 break;
354 case 'h':
355 usage();
356 exit(0);
357 break;
358 case 'c':
359 c_flag = optarg;
360 break;
361 case 'a':
362 a_flag = optarg;
363 break;
364 case 'u':
365 u_flag = optarg;
366 break;
367 default:
368 short_usage();
369 exit(EX_USAGE);
370 break;
371 }
372
373 /*
374 * Read config file
375 */
376 cf_read_config_file(c_flag ? c_flag : CONFIG);
377
378 /*
379 * Process config options
380 */
381 if (a_flag)
382 cf_set_addr(a_flag);
383 if (u_flag)
384 cf_set_uplink(u_flag);
385
386 cf_debug();
387 debug(4, "gateway address A: %s", znfp1(&gate_a));
388 debug(4, "gateway address B: %s", znfp1(&gate_b));
389
390 strict = (cf_get_string("FTNStrictPktCheck", TRUE) != NULL);
391
392 /*
393 * Process local options
394 */
395 if (O_flag)
396 pkt_outdir(O_flag, NULL);
397 else
398 pkt_outdir(cf_p_outpkt(), NULL);
399
400 passwd_init();
401
402 /*
403 * Process command line file args
404 */
405 if (optind >= argc) {
406 /* Process outbound packets for both addresses */
407 do_outbound(&gate_a, &gate_b);
408 tmps_freeall();
409 do_outbound(&gate_b, &gate_a);
410 tmps_freeall();
411 } else
412 for (; optind < argc; optind++) {
413 unpack_file(&gate_a, argv[optind]);
414 tmps_freeall();
415 }
416
417 exit_free();
418 exit(EX_OK);
419 }
420