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: sess_main.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 "bforce.h"
18 #include "util.h"
19 #include "nodelist.h"
20 #include "session.h"
21 #include "prot_zmodem.h"
22 #include "prot_yoohoo.h"
23 #include "prot_emsi.h"
24 #include "prot_binkp.h"
25
26 /* All session information stores here */
27 s_state state;
28
29 int hydra(s_protinfo *pi, bool flag_RH1);
30
session_get_bestaka(s_faddr addr)31 s_faddr *session_get_bestaka(s_faddr addr)
32 {
33 s_cval_entry *addr_ptr;
34 s_cval_entry *hide_ptr;
35 s_faddr *best = NULL;
36 int bestl = 0;
37 int curl = 0;
38
39 for( addr_ptr = conf_first(cf_address); addr_ptr;
40 addr_ptr = conf_next(addr_ptr) )
41 {
42 for( hide_ptr = conf_first(cf_hide_our_aka); hide_ptr;
43 hide_ptr = conf_next(hide_ptr) )
44 {
45 if( !ftn_addrcomp(hide_ptr->d.falist.addr, addr_ptr->d.falist.addr) )
46 break;
47 }
48
49 if( !hide_ptr )
50 {
51 curl = ftn_addrsmetric(addr_ptr->d.falist.addr, addr);
52
53 if( curl > bestl || best == NULL )
54 {
55 bestl = curl;
56 best = &addr_ptr->d.falist.addr;
57 }
58 }
59 }
60
61 return best;
62 }
63
session_addrs_lock(s_sysaddr * addrs,int anum)64 int session_addrs_lock(s_sysaddr *addrs, int anum)
65 {
66 int i;
67 char abuf[BF_MAXADDRSTR+1];
68 bool one_lock = FALSE;
69
70 for( i = 0; i < anum; i++ )
71 {
72 if( addrs[i].good )
73 {
74 #ifdef BFORCE_USE_CSY
75 if( out_bsy_lock(addrs[i].addr, FALSE) )
76 #else
77 if( out_bsy_lock(addrs[i].addr) )
78 #endif
79 {
80 bf_log("exclude address %s: allready locked",
81 ftn_addrstr(abuf, addrs[i].addr));
82 addrs[i].busy = TRUE;
83 }
84 else
85 one_lock = TRUE;
86 }
87 }
88
89 return one_lock ? 0 : -1;
90 }
91
session_addrs_add(s_sysaddr ** addrs,int * anum,s_faddr addr)92 int session_addrs_add(s_sysaddr **addrs, int *anum, s_faddr addr)
93 {
94 int i;
95 char abuf[BF_MAXADDRSTR+1];
96
97 if( *anum && *addrs )
98 {
99 /* Check for addresses duplication */
100 for( i = 0; i < *anum; i++ )
101 {
102 if( !ftn_addrcomp((*addrs)[i].addr, addr) )
103 {
104 bf_log("exclude address %s: duplicated address",
105 ftn_addrstr(abuf, addr));
106 return -1;
107 }
108 }
109 }
110
111 if( *addrs && *anum )
112 *addrs = xrealloc(*addrs, sizeof(s_sysaddr)*(*anum+1));
113 else
114 *addrs = xmalloc(sizeof(s_sysaddr));
115
116 memset(&(*addrs)[*anum], '\0', sizeof(s_sysaddr));
117
118 (*addrs)[*anum].addr = addr;
119 (*addrs)[*anum].busy = FALSE;
120 (*addrs)[*anum].good = FALSE;
121
122 ++(*anum);
123
124 return 0;
125 }
126
session_addrs_check(s_sysaddr * addrs,int anum,const char * passwd,const char * challenge,int challenge_length)127 int session_addrs_check(s_sysaddr *addrs, int anum, const char *passwd,
128 const char *challenge, int challenge_length)
129 {
130 int i;
131 char abuf[BF_MAXADDRSTR+1];
132 char pbuf[32];
133 bool failure = FALSE;
134 bool success = FALSE;
135 bool cram = (challenge && *challenge);
136
137 if( !anum )
138 return -1;
139
140 for( i = 0; i < anum; i++ )
141 {
142 if( session_check_addr(addrs[i].addr) )
143 {
144 bf_log("exclude address %s: not acceptable",
145 ftn_addrstr(abuf, addrs[i].addr));
146 continue;
147 }
148
149 if( !session_get_password(addrs[i].addr, pbuf, sizeof(pbuf)) )
150 {
151 bool good_passwd = FALSE;
152
153 if( passwd && *passwd )
154 {
155 if( cram )
156 {
157 char digest_bin[16];
158 char digest_hex[33];
159
160 md5_cram_get(pbuf, challenge, challenge_length, digest_bin);
161
162 /* Encode digest to the hex string */
163 string_bin_to_hex(digest_hex, digest_bin, 16);
164
165 if( strcasecmp(passwd, digest_hex) == 0 )
166 good_passwd = TRUE;
167 }
168 else if( strcasecmp(passwd, pbuf) == 0 )
169 good_passwd = TRUE;
170 }
171
172 if( good_passwd )
173 {
174 /* correct password */
175 addrs[i].good = TRUE;
176 state.protected = TRUE;
177 success = TRUE;
178 }
179 else
180 {
181 bf_log("exclude address %s: bad password",
182 ftn_addrstr(abuf, addrs[i].addr));
183 addrs[i].good = FALSE;
184 failure = TRUE;
185 }
186 }
187 else
188 /* not password protected address */
189 addrs[i].good = TRUE;
190 }
191
192 /*
193 * Return error, if received password is incorrect for all AKAs
194 */
195 if( failure && !success )
196 return -1;
197
198 return 0;
199 }
200
session_addrs_to_falist(s_sysaddr * addrs,int anum,s_falist ** dest)201 int session_addrs_to_falist(s_sysaddr *addrs, int anum, s_falist **dest)
202 {
203 int i;
204
205 for( i = 0; i < anum; i++ )
206 {
207 if( !addrs[i].busy && addrs[i].good )
208 {
209 (*dest) = (s_falist *)xmalloc(sizeof(s_falist));
210 memset(*dest, '\0', sizeof(s_falist));
211 (*dest)->addr = addrs[i].addr;
212 dest = (s_falist**)&((*dest)->next);
213 }
214 }
215
216 return 0;
217 }
218
session_addrs_check_genuine(s_sysaddr * addrs,int anum,s_faddr expected)219 int session_addrs_check_genuine(s_sysaddr *addrs, int anum, s_faddr expected)
220 {
221 int i;
222
223 for( i = 0; i < anum; i++ )
224 {
225 if( !ftn_addrcomp(addrs[i].addr, expected) )
226 return 0;
227 }
228
229 return 1;
230 }
231
232 /* ------------------------------------------------------------------------- */
233 /* Return non-zero value if current speed too low */
234 /* ------------------------------------------------------------------------- */
session_check_speed(void)235 int session_check_speed(void)
236 {
237 state.minspeed = conf_number(cf_min_speed_in);
238
239 if( state.connspeed > 0 && state.minspeed > state.connspeed )
240 return 1;
241
242 return 0;
243 }
244
session_check_addr(s_faddr addr)245 int session_check_addr(s_faddr addr)
246 {
247 s_cval_entry *addr_ptr;
248
249 for( addr_ptr = conf_first(cf_address); addr_ptr;
250 addr_ptr = conf_next(addr_ptr) )
251 {
252 if( !ftn_addrcomp(addr, addr_ptr->d.falist.addr) )
253 return 1;
254 }
255
256 return 0;
257 }
258
259 /* ------------------------------------------------------------------------- */
260 /* Get session password for address $addr, put it in $buf */
261 /* If no password found - return non-zero value */
262 /* ------------------------------------------------------------------------- */
session_get_password(s_faddr addr,char * buffer,size_t buflen)263 int session_get_password(s_faddr addr, char *buffer, size_t buflen)
264 {
265 s_cval_entry *pwd_ptr;
266
267 for( pwd_ptr = conf_first(cf_password); pwd_ptr;
268 pwd_ptr = conf_next(pwd_ptr) )
269 {
270 if( !ftn_addrcomp(addr, pwd_ptr->d.falist.addr) )
271 {
272 strnxcpy(buffer, pwd_ptr->d.falist.what, buflen);
273 return 0;
274 }
275 }
276
277 return 1;
278 }
279
session_remote_lookup(s_sysaddr * addrs,int anum)280 int session_remote_lookup(s_sysaddr *addrs, int anum)
281 {
282 int i;
283
284 for( i = 0; i < anum; i++ )
285 {
286 if( addrs[i].good )
287 {
288 nodelist_lookup(&state.node, addrs[i].addr);
289 state.node.addr.domain[0] = '\0';
290 state.listed = state.node.listed;
291 break;
292 }
293 }
294
295 return (i < anum) ? 0 : -1;
296 }
297
session_remote_log_status(void)298 void session_remote_log_status(void)
299 {
300 bf_log("remote is %s,%s",
301 (state.listed) ? "listed" : "unlisted",
302 (state.protected) ? "protected" : "unprotected");
303 }
304
305 /* ------------------------------------------------------------------------- */
306 /* Set inbound directory, create temporary inbound in it, check permissions */
307 /* If something wrong - return non-zero value */
308 /* ------------------------------------------------------------------------- */
session_set_inbound(void)309 int session_set_inbound(void)
310 {
311 struct stat st;
312 char *p_inb;
313
314 if( (p_inb = conf_string(cf_inbound_directory)) )
315 {
316 state.inbound = (char*)xstrcpy(p_inb);
317 }
318 else
319 {
320 bf_log("no inbound specified, assume \"./\"");
321 state.inbound = (char*)xstrcpy("./");
322 }
323
324 state.tinbound = (char*)xstrcpy(state.inbound);
325 state.tinbound = (char*)xstrcat(state.tinbound, "tmp/");
326
327 /*
328 * Warning, access() make checks using real uid and gid
329 * (not effective), so we can fail, but..
330 */
331 if( stat(state.tinbound, &st) == 0 )
332 {
333 if( (st.st_mode & S_IFDIR) != S_IFDIR )
334 {
335 bf_log("temporary inbound \"%s\" is not directory", state.tinbound);
336 return(1);
337 }
338 else if( access(state.tinbound, R_OK|W_OK|X_OK) )
339 {
340 bf_log("have no r/w permission to temporary inbound \"%s\"", state.tinbound);
341 return(1);
342 }
343 }
344 else if( errno == ENOENT )
345 {
346 /* "tmp" inbound doesn't exist */
347 if( mkdir(state.tinbound, 0700) < 0 )
348 {
349 logerr("can't create temporary inbound \"%s\"", state.tinbound);
350 return(1);
351 }
352 chmod(state.tinbound, 0700);
353 }
354 else
355 {
356 /* Different stat() errors */
357 logerr("can't stat temporary inbound \"%s\"", state.tinbound);
358 return 1;
359 }
360
361 return(0);
362 }
363
364 /* ------------------------------------------------------------------------- */
365 /* Set status of _OUR_ FREQ processor */
366 /* ------------------------------------------------------------------------- */
session_set_freqs_status(void)367 void session_set_freqs_status(void)
368 {
369 int root_ok = 0;
370 int magc_ok = 0;
371 char *p;
372 long options;
373
374 state.reqstat = REQS_DISABLED;
375
376 options = conf_options(cf_options);
377
378 if( (options & OPTIONS_MAILONLY) == OPTIONS_MAILONLY
379 || (options & OPTIONS_NO_FREQS) == OPTIONS_NO_FREQS )
380 { state.reqstat = REQS_NOTALLOW; return; }
381
382 if( state.connspeed > 0
383 && state.connspeed < conf_number(cf_freq_min_speed) )
384 { state.reqstat = REQS_NOTALLOW; return; }
385
386 if( (p = conf_string(cf_freq_srif_command)) && *p )
387 {
388 /*
389 * Can we execute this processor? Disable freqs if we can't!
390 */
391 if( !exec_file_exist(p) )
392 state.reqstat = REQS_ALLOW;
393 else
394 logerr("can't stat SRIF processor \"%s\"", p);
395 }
396 else
397 {
398 /* Check root dir */
399 if( (p = conf_string(cf_freq_dir_list)) && *p )
400 {
401 if( access(p, R_OK) == 0 )
402 root_ok = 1;
403 else
404 logerr("can't stat FREQ dir list \"%s\"", p);
405 }
406
407 /* Check magic dir */
408 if( (p = conf_string(cf_freq_alias_list)) && *p )
409 {
410 if( access(p, R_OK) == 0 )
411 magc_ok = 1;
412 else
413 logerr("can't stat FREQ alias list \"%s\"", p);
414 }
415
416 /* Set FREQ processor status */
417 if( root_ok || magc_ok )
418 state.reqstat = REQS_ALLOW;
419 }
420 }
421
422 /* ------------------------------------------------------------------------- */
423 /* Set our "send options" (common part, based on our local settings) */
424 /* ------------------------------------------------------------------------- */
session_set_send_options(void)425 void session_set_send_options(void)
426 {
427 const long options = conf_options(cf_options);
428
429 if( state.caller == FALSE )
430 state.sopts.holdreq = 1;
431
432 if( (options & OPTIONS_MAILONLY) == OPTIONS_MAILONLY )
433 state.sopts.holdxt = 1;
434 if( (options & OPTIONS_HOLDXT) == OPTIONS_HOLDXT )
435 state.sopts.holdxt = 1;
436 if( (options & OPTIONS_HOLDREQ) == OPTIONS_HOLDREQ )
437 state.sopts.holdreq = 1;
438 if( (options & OPTIONS_HOLDALL) == OPTIONS_HOLDALL )
439 state.sopts.holdall = 1;
440 if( (options & OPTIONS_HOLDHOLD) == OPTIONS_HOLDHOLD )
441 state.sopts.holdhold = 1;
442 }
443
444 /* ------------------------------------------------------------------------- */
445 /* Return (non-zero) if we _CAN'T_ send this file NOW! */
446 /* ------------------------------------------------------------------------- */
holdfile(s_filelist * fi,const char * delayout)447 static int holdfile(s_filelist *fi, const char *delayout)
448 {
449 if( state.sopts.holdall ) return(1);
450 if( state.sopts.holdxt && !(fi->type & TYPE_NETMAIL) ) return(1);
451 if( state.sopts.holdreq && (fi->type & TYPE_REQUEST) ) return(1);
452 if( state.sopts.holdhold && fi->flavor == FLAVOR_HOLD ) return(1);
453 if( fi->status != STATUS_WILLSEND ) return(1);
454 if( delayout && !checkmasks(delayout, fi->fname) ) return(2);
455
456 return 0;
457 }
458
459 /* ------------------------------------------------------------------------- */
460 /* Set SKIP flag for files we can't send NOW */
461 /* ------------------------------------------------------------------------- */
session_set_send_files(void)462 void session_set_send_files(void)
463 {
464 int holdmsg = 0, rc = 0;
465 s_filelist *ptrl = NULL;
466
467 const char *delayout = conf_string(cf_delay_files_send);
468
469 for( ptrl = state.queue.fslist; ptrl; ptrl = ptrl->next )
470 if( (rc = holdfile(ptrl, delayout)) )
471 {
472 if( rc == 2 && !holdmsg )
473 {
474 bf_log("delaying files \"%s\"", delayout);
475 ++holdmsg;
476 }
477 ptrl->status = STATUS_SKIP;
478 }
479 }
480
session_create_files_queue(s_sysaddr * addrs,int anum)481 int session_create_files_queue(s_sysaddr *addrs, int anum)
482 {
483 s_falist *mailfor = NULL;
484 s_outbound_callback_data ocb;
485
486 /* Set addresses for which we will send files */
487 (void)session_addrs_to_falist(addrs, anum, &mailfor);
488
489 /* Scan outbound directory */
490 if( mailfor )
491 {
492 memset(&ocb, '\0', sizeof(s_outbound_callback_data));
493 ocb.callback = out_handle_fsqueue;
494 ocb.dest = (void *)&state.queue;
495 (void)out_scan(&ocb, mailfor);
496 (void)session_set_send_files();
497 (void)session_traffic_set_outgoing(&state.traff_send);
498 }
499
500 return 0;
501 }
502
session_traffic_set_incoming(s_traffic * dest)503 int session_traffic_set_incoming(s_traffic *dest)
504 {
505 memset(dest, '\0', sizeof(s_traffic));
506
507 if( state.handshake && state.handshake->remote_traffic )
508 return state.handshake->remote_traffic(state.handshake, dest);
509
510 return -1;
511 }
512
session_traffic_set_outgoing(s_traffic * dest)513 int session_traffic_set_outgoing(s_traffic *dest)
514 {
515 s_filelist *ptrl;
516
517 memset(dest, '\0', sizeof(s_traffic));
518
519 for( ptrl = state.queue.fslist; ptrl; ptrl = ptrl->next )
520 {
521 if( ptrl->type & TYPE_NETMAIL )
522 {
523 dest->netmail_size += ptrl->size;
524 dest->netmail_num++;
525 }
526 else if( ptrl->type & TYPE_ARCMAIL )
527 {
528 dest->arcmail_size += ptrl->size;
529 dest->arcmail_num++;
530 }
531 else
532 {
533 dest->files_size += ptrl->size;
534 dest->files_num++;
535 }
536 }
537
538 return 0;
539 }
540
session_traffic_bf_log(bool incoming,s_traffic * traff)541 void session_traffic_bf_log(bool incoming, s_traffic *traff)
542 {
543 char buf[32];
544 char msg[128] = "";
545
546 if( traff == NULL )
547 strcpy(msg, "unknown");
548 else if( traff->netmail_size == 0
549 && traff->arcmail_size == 0 && traff->files_size == 0 )
550 strcpy(msg, "none");
551 else
552 {
553 if( traff->netmail_size > 0 )
554 {
555 string_humansize(buf, traff->netmail_size);
556 strcat(msg, buf);
557 strcat(msg, " netmail, ");
558 }
559 if( traff->arcmail_size > 0 )
560 {
561 string_humansize(buf, traff->arcmail_size);
562 strcat(msg, buf);
563 strcat(msg, " arcmail, ");
564 }
565 if( traff->files_size > 0 )
566 {
567 string_humansize(buf, traff->files_size);
568 strcat(msg, buf);
569 strcat(msg, " files, ");
570 }
571 if( *msg )
572 msg[strlen(msg)-2] = '\0';
573 }
574
575 bf_log("%s traffic: %s", incoming ? "incoming" : "outgoing", msg);
576 }
577
session_traffic(void)578 void session_traffic(void)
579 {
580 int rc;
581
582 rc = session_traffic_set_incoming(&state.traff_recv);
583 session_traffic_bf_log(TRUE, rc ? NULL : &state.traff_recv);
584
585 /* Outgoing traffic must be allread calculated */
586 session_traffic_bf_log(FALSE, &state.traff_send);
587 }
588
589 /*
590 * History file line format:
591 * line verbal name,
592 * remote address,
593 * session start time (Unix),
594 * session_length (seconds),
595 * session status flags (L - listed, P - protected),
596 * session result code (one of mailer return codes),
597 * size of sent netmail,
598 * size of sent arcmail,
599 * size of sent files,
600 * size of received netmail,
601 * size of received arcmail,
602 * size of received files
603 */
session_update_history(s_traffic * send,s_traffic * recv,int rc)604 void session_update_history(s_traffic *send, s_traffic *recv, int rc)
605 {
606 FILE *hist_fp;
607 char *hist_file = conf_string(cf_history_file);
608 char abuf[BFORCE_MAX_ADDRSTR+1];
609 char session_status[32] = "";
610
611 if( !hist_file )
612 return;
613
614 hist_fp = file_open(hist_file, "a");
615 if( !hist_fp )
616 {
617 logerr("cannot open history file \"%s\"", hist_file);
618 return;
619 }
620
621
622 if( state.listed )
623 strcat(session_status, "L");
624 if( state.protected )
625 strcat(session_status, "P");
626 if( state.caller )
627 strcat(session_status, "O");
628 else
629 strcat(session_status, "I");
630
631 fprintf(hist_fp, "%s,%s,%lu,%u,%s,%d,%lu,%lu,%lu,%lu,%lu,%lu\n",
632 state.linename ? state.linename : "",
633 state.node.addr.zone ? ftn_addrstr(abuf, state.node.addr) : "",
634 (unsigned long) state.start_time,
635 (unsigned int) time_elapsed(state.start_time),
636 session_status,
637 rc,
638 (unsigned long) send->netmail_size,
639 (unsigned long) send->arcmail_size,
640 (unsigned long) (send->files_size + send->freqed_size),
641 (unsigned long) recv->netmail_size,
642 (unsigned long) recv->arcmail_size,
643 (unsigned long) (recv->files_size + recv->freqed_size));
644
645
646 (void)file_close(hist_fp);
647 }
648
649 /* ------------------------------------------------------------------------- */
650 /* Start session with another FTN mailer */
651 /* ------------------------------------------------------------------------- */
session(void)652 int session(void)
653 {
654 s_protinfo pi;
655 int rc = BFERR_NOERROR;
656 s_traffic traff_send;
657 s_traffic traff_recv;
658 char *p;
659
660 memset(&traff_send, '\0', sizeof(s_traffic));
661 memset(&traff_recv, '\0', sizeof(s_traffic));
662
663 /* Store session start time */
664 state.start_time = time(NULL);
665
666 if( state.session == SESSION_UNKNOWN )
667 {
668 rc = state.caller ? session_init_outgoing()
669 : session_init_incoming();
670
671 if( rc )
672 gotoexit(BFERR_HANDSHAKE_ERROR);
673 }
674
675 /* -------------------------------------------------------------- */
676 /* Handshake part */
677 /* -------------------------------------------------------------- */
678 switch( state.session ) {
679 case SESSION_EMSI:
680 state.handshake = &handshake_protocol_emsi;
681 break;
682 case SESSION_BINKP:
683 state.handshake = &handshake_protocol_binkp;
684 break;
685 case SESSION_YOOHOO:
686 state.handshake = &handshake_protocol_yoohoo;
687 break;
688 case SESSION_FTSC:
689 bf_log("%sbound FTS-1 session", state.caller?"out":"in");
690 bf_log("FTS-1 session not availabe");
691 gotoexit(BFERR_HANDSHAKE_ERROR);
692 case SESSION_UNKNOWN:
693 ASSERT_MSG();
694 gotoexit(BFERR_HANDSHAKE_ERROR);
695 default:
696 ASSERT_MSG();
697 gotoexit(BFERR_HANDSHAKE_ERROR);
698 }
699
700 state.handshake->init(state.handshake);
701
702 bf_log("%sbound %s session",
703 state.caller ? "out" : "in", state.handshake->verbal_name);
704
705 rc = state.caller ? state.handshake->outgoing_session(state.handshake)
706 : state.handshake->incoming_session(state.handshake);
707
708 DEB((D_PROT, "session: handshake rc = %d", rc));
709
710 if( rc != HRC_OK )
711 {
712 const char *errmsg = NULL;
713
714 switch(rc) {
715 case HRC_LOW_SPEED:
716 errmsg = "connect speed too low";
717 rc = BFERR_CONNECT_TOOLOW;
718 break;
719 case HRC_BAD_PASSWD:
720 errmsg = "security violation";
721 rc = BFERR_HANDSHAKE_ERROR;
722 break;
723 case HRC_NO_ADDRESS:
724 errmsg = "no expected address was presented";
725 rc = BFERR_HANDSHAKE_ERROR;
726 break;
727 case HRC_NO_PROTOS:
728 errmsg = "no common protocols";
729 rc = BFERR_HANDSHAKE_ERROR;
730 break;
731 case HRC_BUSY:
732 errmsg = "all remote addresses are busy";
733 rc = BFERR_HANDSHAKE_ERROR;
734 break;
735 case HRC_FATAL_ERR:
736 case HRC_TEMP_ERR:
737 case HRC_OTHER_ERR:
738 errmsg = NULL;
739 rc = BFERR_HANDSHAKE_ERROR;
740 break;
741 default:
742 errmsg = "unexpected error number";
743 rc = BFERR_HANDSHAKE_ERROR;
744 break;
745 }
746
747 if( errmsg )
748 bf_log("abort session due to: %s", errmsg);
749 }
750 else
751 {
752 /*
753 * Execute 'run_after_handshake' command
754 */
755 if( (p = conf_string(cf_run_after_handshake)) )
756 session_run_command(p);
757
758 /*
759 * Files transfer part
760 */
761 DEB((D_FREQ, "setreqstat: Our FREQ processor status: \"%s\"",
762 ( state.reqstat == REQS_ALLOW ) ? "Allowed":
763 ( state.reqstat == REQS_NOTALLOW ) ? "Not allowed now":
764 ( state.reqstat == REQS_DISABLED ) ? "No FREQs available":"Error"));
765 DEB((D_HSHAKE, "session: decided to use %s protocol",
766 Protocols[state.handshake->protocol]));
767
768 /*
769 * Log expected traffic
770 */
771 session_traffic();
772
773 init_protinfo(&pi, state.caller);
774
775 switch(state.handshake->protocol) {
776 case PROT_BINKP:
777 rc = binkp_transfer(&pi);
778 break;
779 case PROT_ZMODEM:
780 case PROT_ZEDZAP:
781 case PROT_DIRZAP:
782 rc = state.caller ? tx_zmodem(&pi, state.caller)
783 : rx_zmodem(&pi, state.caller);
784 if( rc == PRC_NOERROR )
785 {
786 rc = state.caller ? rx_zmodem(&pi, state.caller)
787 : tx_zmodem(&pi, state.caller);
788 }
789 break;
790 case PROT_JANUS:
791 bf_log("Janus is not available in current version");
792 break;
793 case PROT_HYDRA:
794 rc = hydra(&pi, state.sopts.hydraRH1);
795 break;
796 case PROT_NOPROT:
797 bf_log("no common protocols available");
798 break;
799 default:
800 ASSERT_MSG();
801 break;
802 }
803
804 /*
805 * Convert value returned by protocol to the BForce return code
806 */
807 switch(rc) {
808 case PRC_NOERROR: rc = BFERR_NOERROR; break;
809 case PRC_ERROR:
810 case PRC_REMOTEABORTED:
811 case PRC_LOCALABORTED: rc = BFERR_XMITERROR; break;
812 case PRC_CPSTOOLOW: rc = BFERR_CPSTOOLOW; break;
813 case PRC_STOPTIME: rc = BFERR_STOPTIME; break;
814 default: ASSERT_MSG();
815 }
816 state.session_rc = rc;
817
818 /*
819 * Do session clenup (remove temp. files, etc.)
820 */
821 (void)p_session_cleanup(&pi, (rc == BFERR_NOERROR));
822
823 if( rc == BFERR_NOERROR )
824 {
825 /*
826 * Flush our 'stdout' buffer
827 */
828 FLUSHOUT();
829
830 /*
831 * Remove empty .?lo files
832 */
833 (void)out_flo_unlinkempty(state.queue.flotab, state.queue.flonum);
834
835 /*
836 * Wait a little if we are answering on incoming call
837 * (to be sure that all data will be sent) (?)
838 */
839 if( !state.caller ) sleep(1);
840 }
841
842 /*
843 * Remove all .bsy locks
844 */
845 out_bsy_unlockall();
846
847 /*
848 * Write total amount of received/sent bytes, files, etc.
849 */
850 p_log_txrxstat(&pi);
851
852 /*
853 * Save session traffic before deiniting
854 */
855 traff_send = pi.traffic_sent;
856 traff_recv = pi.traffic_rcvd;
857
858 deinit_protinfo(&pi);
859
860 /*
861 * Execute 'run_after_session' command
862 */
863 if( (p = conf_string(cf_run_after_session)) )
864 session_run_command(p);
865 }
866
867 exit:
868 state.session_rc = rc;
869 session_update_history(&traff_send, &traff_recv, rc);
870
871 return rc;
872 }
873