579 lines
17 KiB
C
579 lines
17 KiB
C
/* $Id: eft_server.c,v 1.3 1999/10/06 18:16:22 he Exp $ */
|
|
/*
|
|
Copyright 1998 by Henner Eisen
|
|
|
|
This code is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
#include <sys/stat.h>
|
|
#include <sys/param.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h> /*NEW libc2: realpath*/
|
|
|
|
#include <pwd.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <tdu_user.h>
|
|
#include "sbv.h"
|
|
#include "tdu.h"
|
|
#include <eft.h>
|
|
#include "eft_private.h"
|
|
#include "fileheader.h"
|
|
|
|
/*
|
|
* global variable for eft flat dir. Is tried as default directory when
|
|
* server thinks that the client does not support navigation.
|
|
*/
|
|
const char * eft_flat_dir_name = EFT_METAFILE_PREFIX "_flat";
|
|
/*
|
|
* map unknown users to this if not NULL
|
|
*/
|
|
char * eft_map_to_user = NULL;
|
|
|
|
|
|
static int assoc_ind( struct tdu_user *usr, struct tdu_param *par)
|
|
{
|
|
struct eft * eft = usr->priv;
|
|
unsigned char calling[TDU_PLEN_ADDR+1]="", udata[TDU_PLEN_UDATA+1]="",
|
|
*user="", *pass="";
|
|
struct tdu_assoc_param *respar=par->res.assoc, *inpar=par->par.assoc;
|
|
|
|
par->other_reason[0] = 0;
|
|
par->other_reason[1] = 0;
|
|
|
|
/*
|
|
* the tdu layer checks that the maximum udata len is not exceeded,
|
|
* which should prevent overflow attacks here.
|
|
*/
|
|
tdu_mk_printable(udata, inpar->udata, inpar->udata_len);
|
|
tdu_mk_printable(calling, inpar->calling_addr, inpar->calling_len);
|
|
|
|
tdu_printf(TDU_LOG_TRC," assoc_ind, ident_len=%d\n",inpar->ident_len);
|
|
|
|
eft_set_flags(eft,eft_get_flags(eft)|EFT_FLAG_STRICT_TREE);
|
|
|
|
if( inpar->ident_len > 0 ){
|
|
user = inpar->ident;
|
|
/* Prevent possible buffer overflows by string functions
|
|
* depending on zero termination.
|
|
* The struct tdu_assoc_param contains space for adding
|
|
* an extra delimiting \0 charater.
|
|
* Be also careful with missing pass here
|
|
*/
|
|
user[inpar->ident_len]=0;
|
|
pass = user;
|
|
while( pass-user < inpar->ident_len ){
|
|
if(*pass == '/'){
|
|
*pass = 0;
|
|
pass++;
|
|
break;
|
|
}
|
|
pass++;
|
|
};
|
|
tdu_printf(TDU_LOG_AP1,"IND: ASSOC id=%s calling=%s udata=%s\n",user,calling,udata );
|
|
/*
|
|
* A leading '+' is used to indicate that the server shall
|
|
* apply the case-insensitiveness or other compatibility
|
|
* hacks for transfer names.
|
|
* The '+' is not part of the user id, thus stripping it.
|
|
*/
|
|
if( user[0] == '+' ){
|
|
long flags;
|
|
user++;
|
|
|
|
flags = eft_get_flags(eft);
|
|
eft_set_flags(eft,flags|EFT_FLAG_CASEFIX_TN|
|
|
EFT_FLAG_CASEFIX_FS|EFT_FLAG_SLASHFIX);
|
|
}
|
|
/* 20.11.98, ms@msdatec.de: mapping to user eft_map_to_user, if failed
|
|
*
|
|
* Slightly modified and moved here (1999-01-07) -- HE:
|
|
*
|
|
* Now mapping to default user only if user is not in
|
|
* passwd database.
|
|
*
|
|
* FIXME:
|
|
* This check might be inappropriate if other authentication
|
|
* methods (not based on /etc/passwd) are used.
|
|
*/
|
|
|
|
if (eft_map_to_user) {
|
|
struct passwd *pw;
|
|
/*
|
|
*/
|
|
setpwent();
|
|
while( (pw=getpwent()) ){
|
|
if( strcmp(user,pw->pw_name) == 0) break;
|
|
};
|
|
endpwent();
|
|
|
|
if( ! pw ){
|
|
/* user is unknown (not in /etc/passwd).*/
|
|
tdu_printf(TDU_LOG_LOG, "user %s not known, trying alternate authentication as user \"%s\" instead\n",
|
|
user, eft_map_to_user);
|
|
user = eft_map_to_user;
|
|
pass = "";
|
|
}
|
|
}
|
|
|
|
strcpy(eft->user_name,user);
|
|
par->reason = eft->check_user(eft,user,pass,eft_peer_phone(eft));
|
|
} else {
|
|
strcpy(eft->user_name,"(empty)");
|
|
tdu_printf(TDU_LOG_AP1,"IND: ASSOC with empty id"
|
|
" calling=%s udata=%s\n", calling, udata );
|
|
par->reason = eft->check_user(eft,"","",eft_peer_phone(eft));
|
|
}
|
|
|
|
respar->resp_timeout = 15;
|
|
respar->called_len = LIMIT(strlen(eft->address), TDU_PLEN_ADDR);
|
|
memcpy( respar->called_addr, eft->address, respar->called_len);
|
|
|
|
if(! eft_signature ){
|
|
respar->udata_len = -1;
|
|
} else {
|
|
respar->udata_len = LIMIT(strlen(eft_signature), TDU_PLEN_UDATA);
|
|
memcpy( respar->udata, eft_signature, respar->udata_len);
|
|
}
|
|
|
|
if( par->reason ) {
|
|
tdu_printf(TDU_LOG_AP1,"REJ: ASSOC user=%s from=%s\n",
|
|
user, eft_peer_phone(eft));
|
|
} else {
|
|
tdu_printf(TDU_LOG_AP1,"ACP: ASSOC user=%s from=%s\n",
|
|
user, eft_peer_phone(eft));
|
|
}
|
|
|
|
tdu_printf(TDU_LOG_LOG,"user \"%s\" from %s %s\n",
|
|
user, eft_peer_phone(eft),
|
|
par->reason ? "rejected" : "accepted");
|
|
if( par->reason == TDU_RE_OTHER_REASON )
|
|
par->other_reason[0] = EFT_RE_ID_REJECTED;
|
|
|
|
return par->reason;
|
|
}
|
|
|
|
/*
|
|
* called from the tdu layer when an access indication is received.
|
|
*/
|
|
static int access_ind( struct tdu_user *usr, struct tdu_param *par)
|
|
{
|
|
struct eft * eft = usr->priv;
|
|
|
|
par->other_reason[0] = 0;
|
|
par->other_reason[1] = 0;
|
|
|
|
tdu_printf(TDU_LOG_TRC,"eft_server access_ind()\n");
|
|
|
|
par->res.access->udata_len = 3;
|
|
par->res.access->window = 8;
|
|
#if 1
|
|
/* t_dir applies to group A, application name subset */
|
|
par->res.access->udata[0] = 0x89;
|
|
#else
|
|
par->res.access->udata[0] = 0x99;
|
|
#endif
|
|
par->res.access->udata[1] = 0x24;
|
|
par->res.access->udata[2] = 0x4f; /* navigation supported */
|
|
|
|
par->reason = eft->setup_user(eft);
|
|
eft_set_home(eft);
|
|
tdu_printf(TDU_LOG_LOG,"access_ind: user set up.\n");
|
|
|
|
tdu_printf(TDU_LOG_AP2,"IND: ACCESS features=XXX_log_peer_supported_feastures_here\n");
|
|
|
|
return( par->reason );
|
|
}
|
|
|
|
/*
|
|
* Write a log record about transferred file into to a log file.
|
|
*
|
|
* The format is the same as used by wu-ftpd 2.4.2 although slightly
|
|
* different semantics (because eft != ftp) apply to certain fields.
|
|
* Thus, you should be able to use or modify existing tools for
|
|
* parsing your log file.
|
|
*/
|
|
static void eft_log_xfer(struct eft * eft){
|
|
#define MAX_LOGREC_LEN MAXPATHLEN+400
|
|
char msg[MAX_LOGREC_LEN];
|
|
struct tdu_fsm * fsm = eft->fsm;
|
|
struct transfer_regime *tr = & fsm->transfer;
|
|
int tr_sec = tr->tv_end.tv_sec - tr->tv_begin.tv_sec;
|
|
int bytes = tr->byte_cnt - fsm->stream->hdr.len, g;
|
|
time_t t = time(NULL);
|
|
|
|
if( eft->xferlog <= 0 ) return;
|
|
g='r';
|
|
if( eft->flags & EFT_FLAG_ANONYMOUS ){
|
|
g = (eft->flags & EFT_FLAG_GUEST) ? 'g' : 'a';
|
|
};
|
|
|
|
snprintf(msg, MAX_LOGREC_LEN,
|
|
"%.24s %d %s %d %s %c %s %c %c %s eft %d %s\n",
|
|
ctime(&t),
|
|
tr_sec,
|
|
eft_peer_phone(eft), /* phone number instead of domain name*/
|
|
bytes,
|
|
eft->fn,
|
|
'b', /* we currently support binary transfers only */
|
|
"_", /* for transfer options like on-the-fly tar/gzip, which
|
|
* is currently not supported */
|
|
tr->outbound ? 'o' : 'i',
|
|
g,
|
|
eft->user_name,
|
|
0, /* authenticated e-mail address does not make sense with
|
|
eurofile as we are probably outside internet domain */
|
|
"*" /* dto */
|
|
);
|
|
write(eft->xferlog,msg,strlen(msg));
|
|
}
|
|
|
|
static void eft_write_xfer_log(struct tdu_user * usr, int abnormal)
|
|
{
|
|
usr->transfer_end = NULL;
|
|
eft_log_xfer(usr->priv);
|
|
if(abnormal){
|
|
tdu_printf(TDU_LOG_AP2, "TRF: ABORT \n");
|
|
} else {
|
|
tdu_printf(TDU_LOG_AP3, "TRF: FINISH\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This is called from the tdu protocol layer when a request for a download
|
|
* is indicated. Basically, it provides us the name of the file to be
|
|
* downlowded. This callback functions needs to do the following:
|
|
* - map the transfer name of the file to a POSIX file name
|
|
* - decide whether we want to grant the peer read access permission to
|
|
* file
|
|
* - open the file in question
|
|
* - return a tdu_stream object back to the tdu layer. The tdu layer then
|
|
* will use the tdu_stream object and its methods for reading the file
|
|
*/
|
|
int eft_load_ind( struct tdu_user * usr, struct tdu_param * par )
|
|
{
|
|
unsigned char fnbuf[MAXPATHLEN], *fn="",
|
|
*tn = par->par.transfer->designation;
|
|
/* struct tdu_stream * ts = tdu_user_get_stream(usr); */
|
|
int fd, len=par->par.transfer->designation_len, stat_d=0,size;
|
|
struct stat s[1];
|
|
struct eft * eft = usr->priv;
|
|
|
|
usr->fsm->transfer.outbound = 1;
|
|
par->other_reason[0] = 0;
|
|
par->other_reason[1] = 0;
|
|
/* FIXME: is len limited? */
|
|
/* len has at least been checked to be >=0 by lower layer */
|
|
tn[len]=0;
|
|
#if 0
|
|
/* special hack to support certain rare non-conformaning application */
|
|
{
|
|
int i=0;
|
|
while( tn[i] ){
|
|
if( tn[i] == '\\') tn[i] = '/';
|
|
i++;
|
|
}
|
|
}
|
|
#endif
|
|
if( strcmp(tn, "EUROSFT92/NAVIGATION/S-LIST") == 0 ) {
|
|
tdu_printf(TDU_LOG_AP3,"IND: SLIST \n" );
|
|
fd = eft_store_slist(eft,".",NULL);
|
|
eft_stream_set_names(eft, tn, fn, TDU_FH_CLASS_EFT_LIST);
|
|
stat_d = 1;
|
|
} else if( strcmp(tn, "EUROSFT92/NAVIGATION/S-FILESTORE") == 0 ) {
|
|
tdu_printf(TDU_LOG_AP3,"IND: PWD \n" );
|
|
fd = eft_store_cwd(eft);
|
|
eft_stream_set_names(eft, tn, fn, TDU_FH_CLASS_EFT_STRING);
|
|
} else if( strcmp(tn, "EUROSFT92/NAVIGATION/LIST") == 0 ) {
|
|
tdu_printf(TDU_LOG_AP3,"IND: LIST \n" );
|
|
par->reason = TDU_RE_UNKNOWN_FILE;
|
|
tdu_printf(TDU_LOG_AP3,"REJ: LIST reason=%s\n",
|
|
eft_str_reason(par->reason) );
|
|
return( par->reason );
|
|
} else if( eft_acceptable_tname(tn) ) {
|
|
fn = eft_fn_by_tn(fnbuf,tn,eft_get_flags(eft));
|
|
tdu_printf(TDU_LOG_AP2,"IND: LOAD t_name=%s f_name=%s\n",tn,fn);
|
|
if( realpath(fn,eft->fn) && eft_file_is_tabu(eft->fn) ) {
|
|
par->other_reason[0] = EFT_RE_FILE_ACCESS_IMPOSSIBLE;
|
|
tdu_printf(TDU_LOG_AP2,"REJ: LOAD reason=%s[tabu]\n",
|
|
eft_str_other_reason(par->other_reason[0]));
|
|
return( par->reason = TDU_RE_OTHER_REASON);
|
|
}
|
|
fd = open(fn, O_RDONLY, 0640 );
|
|
if( fd < 0 ){
|
|
switch ( errno ) {
|
|
case ENOENT:
|
|
par->reason = TDU_RE_UNKNOWN_FILE;
|
|
break;
|
|
default:
|
|
par->reason = TDU_RE_OTHER_REASON;
|
|
par->other_reason[0] =
|
|
EFT_RE_FILE_ACCESS_IMPOSSIBLE;
|
|
}
|
|
tdu_printf(TDU_LOG_AP2,"REJ: LOAD reason=%s[%s]\n",
|
|
par->reason == TDU_RE_OTHER_REASON ?
|
|
eft_str_other_reason(par->other_reason[0]) :
|
|
eft_str_reason(par->reason),
|
|
strerror(errno));
|
|
return( par->reason );
|
|
}
|
|
eft_stream_set_names(eft, par->par.transfer->designation, fn,
|
|
TDU_FH_CLASS_EFT_DATA);
|
|
usr->transfer_end = eft_write_xfer_log;
|
|
} else {
|
|
tdu_printf(TDU_LOG_AP2,"IND: LOAD t_name=%s\n",tn);
|
|
par->reason = TDU_RE_ERRON_DESIGN;
|
|
tdu_printf(TDU_LOG_AP2,"REJ: LOAD reason=%s\n",
|
|
eft_str_reason(par->reason));
|
|
return( par->reason);
|
|
}
|
|
|
|
if( fd < 0 ){
|
|
perror("cannot open local file to be transferred");
|
|
par->reason = TDU_RE_UNKNOWN_FILE;
|
|
tdu_printf(TDU_LOG_AP2,"REJ: LOAD reason=%s\n",
|
|
eft_str_reason(par->reason));
|
|
return( par->reason );
|
|
}
|
|
tdu_printf(TDU_LOG_LOG,"File \"%s\" opened for reading, fd=%d\n", fn,fd);
|
|
eft_stream_init_fd(eft,fd,1);
|
|
fstat(fd,s);
|
|
if( stat_d ){
|
|
size = s->st_size;
|
|
stat(".",s);
|
|
s->st_size = size;
|
|
}
|
|
eft_stream_set_stat(eft, s);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* This is called from the tdu protocol layer when a t_directory indication.'
|
|
* is received. Basically, pattern to selcet the requested filenames is
|
|
* provided. This callback function needs to do the following:
|
|
* - Check designatation parameter for validity and decide whether we
|
|
* want to grant the peer read access permission to the directory contents
|
|
* in question.
|
|
* - build a diretory contents file.
|
|
* - return a tdu_stream object attached to the directory contents
|
|
* back to the tdu layer. The tdu layer then will use the tdu_stream
|
|
* object and its methods for reading diretory contents.
|
|
*/
|
|
int eft_dir_ind( struct tdu_user * usr, struct tdu_param * par )
|
|
{
|
|
unsigned char fn[TDU_PLEN_DESIGNATION+1];
|
|
/* struct tdu_stream * ts = tdu_user_get_stream(usr); */
|
|
int i, fd, len=par->par.transfer->designation_len, size, extended
|
|
, class;
|
|
struct eft * eft = usr->priv;
|
|
struct stat s[1];
|
|
|
|
usr->fsm->transfer.outbound = 1;
|
|
par->other_reason[0] = 0;
|
|
par->other_reason[1] = 0;
|
|
extended = (par->par.transfer->udata_len >= 2) &&
|
|
(par->par.transfer->udata[1] == 0x40);
|
|
strncpy(fn,par->par.transfer->designation,len);
|
|
tdu_printf(TDU_LOG_AP3,"IND: DIR extended=%d\n",extended );
|
|
|
|
for( i=0; i< len; i++ ){
|
|
if( fn[i] == '/' ) fn[i] = 0;
|
|
}
|
|
fn[len] = 0;
|
|
/*
|
|
* we currently just show the contents of the working directory
|
|
*/
|
|
if( (fd = eft_store_dir(eft,".",NULL,extended)) < 0 ){
|
|
/* FIXME: wrong error code ??? */
|
|
*par->other_reason = EFT_RE_FILE_ACCESS_IMPOSSIBLE;
|
|
par->reason_len = 1;
|
|
return ( par->reason = TDU_RE_OTHER_REASON );
|
|
}
|
|
|
|
eft_stream_init_fd(eft,fd,1);
|
|
class = extended ? TDU_FH_CLASS_EFT_XDIR : TDU_FH_CLASS_EFT_DIR;
|
|
eft_stream_set_names(eft, "", "", class);
|
|
/*
|
|
* size from generated directory content file, other attributes from
|
|
* directory's stat entries
|
|
*/
|
|
fstat(fd,s);
|
|
size = s->st_size;
|
|
stat(".",s);
|
|
s->st_size = size;
|
|
eft_stream_set_stat(eft, s);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* This is called from the tdu protocol layer when the peer indicates that
|
|
* it wants to upload a file to us.
|
|
* Basically, it provides us the name of the file to be uploaded. This
|
|
* callback function needs to do the following:
|
|
* - decide whether we want to grant the peer write access permission to
|
|
* the file and current directory
|
|
* - open/create the file in question
|
|
* - return a tdu_stream object back to the tdu layer. The tdu layer then
|
|
* will use the tdu_stream object and its methods for writing to the file.
|
|
*/
|
|
int eft_save_ind( struct tdu_user * usr, struct tdu_param * par )
|
|
{
|
|
unsigned char fnbuf[MAXPATHLEN+1],
|
|
*tn = par->par.transfer->designation,
|
|
*fn = fnbuf;
|
|
struct tdu_stream * ts = tdu_user_get_stream(usr);
|
|
int fd, cd=0, len=par->par.transfer->designation_len;
|
|
struct eft * eft = usr->priv;
|
|
|
|
usr->fsm->transfer.outbound = 0;
|
|
par->reason = 0;
|
|
par->other_reason[0] = 0;
|
|
par->other_reason[1] = 0;
|
|
tn[len]=0;
|
|
fn[0]=0;
|
|
|
|
if( strcmp(tn, "EUROSFT92/NAVIGATION/SELECT") == 0 ) {
|
|
tdu_printf(TDU_LOG_AP2,"IND: CHDIR \n" );
|
|
fd = eft_get_tmp(eft);
|
|
cd = 1;
|
|
} else if( eft_acceptable_tname(tn) &&
|
|
(strncmp("EUROSFT92/",tn,10)!=0) ){
|
|
fn = eft_fn_by_tn(fnbuf,tn,eft_get_flags(eft));
|
|
tdu_printf(TDU_LOG_AP2,"IND: SAVE t_name=%s f_name=%s\n",tn,fn);
|
|
if( realpath(fn,eft->fn) && eft_file_is_tabu(eft->fn) ) {
|
|
par->other_reason[0] = EFT_RE_FILE_ACCESS_IMPOSSIBLE;
|
|
tdu_printf(TDU_LOG_AP2,"REJ: SAVE reason=%s[tabu]\n",
|
|
eft_str_other_reason(par->other_reason[0]) );
|
|
return( par->reason = TDU_RE_OTHER_REASON);
|
|
}
|
|
fd = open(fn, O_WRONLY | O_CREAT, 0640 );
|
|
} else {
|
|
tdu_printf(TDU_LOG_AP2,"IND: SAVE t_name=%s\n",tn);
|
|
par->reason = TDU_RE_ERRON_DESIGN;
|
|
tdu_printf(TDU_LOG_AP2,"REJ: SAVE reason=%s\n",
|
|
eft_str_reason(par->reason) );
|
|
|
|
return( par->reason );
|
|
}
|
|
|
|
if( fd < 0 ){
|
|
tdu_printf(TDU_LOG_DBG,"cannot create local file to be transferred\n");
|
|
switch ( errno ) {
|
|
case ENOENT:
|
|
par->reason = TDU_RE_UNKNOWN_FILE;
|
|
break;
|
|
case EEXIST:
|
|
par->reason = TDU_RE_FILE_EXISTS;
|
|
break;
|
|
case ENOSPC:
|
|
par->reason = TDU_RE_OTHER_REASON;
|
|
par->other_reason[0] = EFT_RE_DISK_FULL;
|
|
break;
|
|
default:
|
|
par->reason = TDU_RE_OTHER_REASON;
|
|
par->other_reason[0] =
|
|
EFT_RE_FILE_ACCESS_IMPOSSIBLE;
|
|
}
|
|
tdu_printf(TDU_LOG_AP2,"REJ: SAVE reason=%s[%s]\n",
|
|
par->reason == TDU_RE_OTHER_REASON ?
|
|
eft_str_other_reason(par->other_reason[0]) :
|
|
eft_str_reason(par->reason),
|
|
strerror(errno)
|
|
);
|
|
return( par->reason );
|
|
}
|
|
tdu_printf(TDU_LOG_DBG,"File \"%s\" opened for writing, fd=%d\n", fn,fd);
|
|
|
|
tdu_stream_init_fd(ts,fd,1);
|
|
if( cd ){
|
|
ts->close = eft_cd_close;
|
|
} else {
|
|
usr->transfer_end = eft_write_xfer_log;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int eft_accept_user(struct eft * eft)
|
|
{
|
|
int ret, sk = eft_get_socket(eft);
|
|
struct tdu_user * user = eft_get_user(eft);
|
|
unsigned char isdn_no[21];
|
|
time_t t;
|
|
|
|
eft_get_peer_phone(isdn_no,sk);
|
|
eft_add_peer_phone(eft,isdn_no);
|
|
t = time(NULL);
|
|
tdu_printf(TDU_LOG_LOG,"awaiting SBV connection from %s\n", isdn_no);
|
|
ret = tdu_sbv_accept(sk);
|
|
if( ret ){
|
|
tdu_printf(TDU_LOG_ERR,"SBV connection failed, ret=%d\n",ret);
|
|
return ret;
|
|
}
|
|
tdu_printf(TDU_LOG_LOG,"SBV connection accepted\n");
|
|
|
|
user->t_associate = assoc_ind;
|
|
user->t_access = access_ind;
|
|
user->t_typed_data = eft_msg2stdout;
|
|
user->t_load = eft_load_ind;
|
|
user->t_save = eft_save_ind;
|
|
user->t_dir = eft_dir_ind;
|
|
user->t_rename = NULL;
|
|
user->t_delete = NULL;
|
|
user->transfer_end = NULL;
|
|
|
|
tdu_init_slave(eft->fsm);
|
|
eft->fsm->idle.initiator = 0;
|
|
tdu_initial_set_idle(eft->fsm);
|
|
tdu_assoc_allow_listen(eft->fsm);
|
|
|
|
if (eft_is_up(eft)){
|
|
tdu_printf(TDU_LOG_DBG,
|
|
"eft_accept_user(): waiting for associate request\n");
|
|
ret = tdu_dispatch_packet(eft->fsm);
|
|
}
|
|
tdu_printf(TDU_LOG_DBG,"eft_accept_user: ret=%d\n",ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int eft_server_mainloop( struct eft * eft )
|
|
{
|
|
while(eft_is_up(eft)){
|
|
tdu_dispatch_packet(eft->fsm);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void eft_set_auth(struct eft * eft,
|
|
int (*check_user)(struct eft *, char *, char *,char *),
|
|
int (*setup_user)(struct eft *),
|
|
int (*cleanup_user)(struct eft *)
|
|
)
|
|
{
|
|
eft->check_user = check_user ? *check_user : NULL;
|
|
eft->setup_user = setup_user ? *setup_user : NULL;
|
|
eft->cleanup_user = cleanup_user ? *cleanup_user : NULL;
|
|
}
|