/*
* bbftpd/bbftpd_readcontrol.c
* Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS
* bbftp@in2p3.fr
* http://doc.in2p3.fr/bbftp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/****************************************************************************
RETURN:
0 calling program return to main loop
-1 calling program exit
bbftpd_readcontrol.c v 2.0.0 2000/12/19 - Routine creation
v 2.0.1 2001/04/23 - Correct indentation
v 2.0.2 2001/05/04 - Correct return code treatment
- Correct case of file size 0
v 2.1.0 2001/05/30 - Correct syslog level
- Change routines name
v 2.2.0 2001/11/21 - Remote COS received can be -1
*****************************************************************************/
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <syslog.h>
#include <utime.h>
#include <sys/types.h>
#include <unistd.h>
#include <bbftpd.h>
#include <common.h>
#include <daemon.h>
#include <daemon_proto.h>
#include <status.h>
#include <structures.h>
#include <version.h>
extern int state ;
extern int incontrolsock ;
extern int outcontrolsock ;
extern int recvcontrolto ;
extern int sendcontrolto ;
extern char *curfilename ;
extern char *realfilename ;
extern int curfilenamelen ;
extern int transferoption ;
extern int filemode ;
extern char lastaccess[9] ;
extern char lastmodif[9] ;
extern int sendwinsize ;
extern int recvwinsize ;
extern int buffersizeperstream ;
extern int requestedstreamnumber ;
extern my64_t filesize ;
extern int *myports ;
extern int *mychildren ;
extern int *mysockets ;
extern int myumask ;
extern int mycos ;
extern char *readbuffer ;
extern char *compbuffer ;
extern int protocolversion ;
extern char currentusername[MAXLEN] ;
#ifndef WORDS_BIGENDIAN
#ifndef HAVE_NTOHLL
my64_t ntohll(my64_t v) ;
#endif
#endif
int bbftpd_readcontrol(int msgcode,int msglen)
{
int retcode ;
int i ;
char *receive_buffer ;
int oldumask, newumask ;
struct message *msg ;
struct mess_store_v2 *msg_store_v2 ;
struct mess_integer *msg_integer ;
struct mess_dir *msg_dir ;
char logmessage[1024] ;
int *portfree ;
struct utimbuf ftime ;
int *porttosend ;
/*
** Depending on the state the accepted message may be different
*/
#ifndef WORDS_BIGENDIAN
msglen = ntohl(msglen) ;
#endif
switch (state) {
/*
** Case S_LOGGED :
** Nothing is going on, so message accepted are :
**
** MSG_CHCOS
** MSG_CHDIR_V2
** MSG_CHUMASK
** MSG_CLOSE_CONN
** MSG_LIST_V2
** MSG_MKDIR_V2
** MSG_RETR_V2
** MSG_STORE_V2
**
*/
case S_LOGGED : {
switch (msgcode) {
case MSG_CHCOS : {
syslog(BBFTPD_DEBUG,"Receiving MSG_CHCOS, msglen = %d",msglen) ;
if ( (receive_buffer = (char *) malloc (msglen)) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating memory for MSG_CHCOS : %s",strerror(errno)) ;
reply(MSG_BAD,"Error allocating memory for MSG_CHCOS") ;
return 0 ;
}
if ( readmessage(incontrolsock,receive_buffer,msglen,recvcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error reading MSG_CHCOS") ;
FREE(receive_buffer) ;
return -1 ;
}
msg_integer = (struct mess_integer *) receive_buffer ;
#ifndef WORDS_BIGENDIAN
mycos = ntohl(msg_integer->myint) ;
#else
mycos = msg_integer->myint ;
#endif
if (mycos>=0) {
syslog(BBFTPD_DEBUG,"Cos set to %d",mycos) ;
reply(MSG_OK,"COS set") ;
} else {
syslog(BBFTPD_DEBUG,"Cos received : %d",mycos) ;
reply(MSG_OK,"COS not set") ;
}
FREE(receive_buffer) ;
return 0 ;
}
case MSG_CHDIR_V2 : {
syslog(BBFTPD_DEBUG,"Receiving MSG_CHDIR_V2, msglen = %d",msglen) ;
retcode = bbftpd_cd(incontrolsock,msglen) ;
return retcode ;
}
case MSG_CHUMASK : {
syslog(BBFTPD_DEBUG,"Receiving MSG_UMASK ") ;
if ( (receive_buffer = (char *) malloc (msglen)) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating memory for MSG_UMASK : %s",strerror(errno)) ;
reply(MSG_BAD,"Error allocating memory for MSG_UMASK") ;
return 0 ;
}
if ( readmessage(incontrolsock,receive_buffer,msglen,recvcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error reading MSG_UMASK") ;
FREE(receive_buffer) ;
return -1 ;
}
msg_integer = (struct mess_integer *) receive_buffer ;
#ifndef WORDS_BIGENDIAN
myumask = ntohl(msg_integer->myint) ;
#else
myumask = msg_integer->myint ;
#endif
/*
** We reset the umask first then call twice the umask
** in order to see the real umask set
*/
oldumask = umask(0) ;
umask(myumask) ;
newumask = umask(myumask) ;
sprintf(logmessage,"umask changed from %04o to %04o",oldumask,newumask) ;
reply(MSG_OK,logmessage) ;
FREE(receive_buffer) ;
return 0 ;
}
case MSG_CLOSE_CONN : {
syslog(BBFTPD_DEBUG,"Receiving MSG_CLOSE_CONN, msglen = %d",msglen) ;
return -1 ;
}
case MSG_LIST_V2 :{
syslog(BBFTPD_DEBUG,"Receiving MSG_LIST_V2 ") ;
if ( (receive_buffer = (char *) malloc (msglen+1) ) == NULL ) {
syslog(BBFTPD_ERR,"Unable to malloc space for directory name (%d)",msglen) ;
reply(MSG_BAD,"Unable to malloc space for directory name") ;
return 0 ;
}
/*
** Read the characteristics of the directory
*/
if ( readmessage(incontrolsock,receive_buffer,msglen,recvcontrolto) < 0 ) {
/*
** Error ...
*/
syslog(BBFTPD_ERR,"Error reading directory name") ;
FREE(receive_buffer) ;
return -1 ;
}
/*
** buffer contains the directory to create
*/
receive_buffer[msglen] = '\0' ;
msg_dir = (struct mess_dir *) receive_buffer ;
transferoption = msg_dir->transferoption ;
syslog(BBFTPD_DEBUG,"Pattern = %s",msg_dir->dirname) ;
retcode = bbftpd_list(msg_dir->dirname,logmessage) ;
FREE(receive_buffer) ;
return retcode ;
}
case MSG_MKDIR_V2 : {
syslog(BBFTPD_DEBUG,"Receiving MSG_MKDIR_V2 ") ;
retcode = bbftpd_mkdir(incontrolsock,msglen) ;
return retcode ;
}
case MSG_RETR_V2 : {
syslog(BBFTPD_DEBUG,"Receiving MSG_RETR_V2") ;
if ( (receive_buffer = (char *) malloc (msglen)) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating memory for MSG_RETR_V2 : %s",strerror(errno)) ;
return -1 ;
}
if ( readmessage(incontrolsock,receive_buffer,msglen,recvcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error reading MSG_RETR_V2") ;
FREE(receive_buffer) ;
return -1 ;
}
msg_store_v2 = (struct mess_store_v2 *) receive_buffer ;
/*
** Set up the transfer parameter, we are going only to store
** them
*/
#ifndef WORDS_BIGENDIAN
transferoption = msg_store_v2->transferoption ;
sendwinsize = ntohl(msg_store_v2->sendwinsize) ;
recvwinsize = ntohl(msg_store_v2->recvwinsize) ;
buffersizeperstream = ntohl(msg_store_v2->buffersizeperstream) ;
requestedstreamnumber = ntohl(msg_store_v2->nbstream) ;
#else
transferoption = msg_store_v2->transferoption ;
sendwinsize = msg_store_v2->sendwinsize ;
recvwinsize = msg_store_v2->recvwinsize ;
buffersizeperstream = msg_store_v2->buffersizeperstream ;
requestedstreamnumber = msg_store_v2->nbstream ;
#endif
syslog(BBFTPD_DEBUG,"transferoption = %d ",transferoption) ;
syslog(BBFTPD_DEBUG,"sendwinsize = %d ",sendwinsize) ;
syslog(BBFTPD_DEBUG,"recvwinsize = %d ",recvwinsize) ;
syslog(BBFTPD_DEBUG,"buffersizeperstream = %d ",buffersizeperstream) ;
syslog(BBFTPD_DEBUG,"requestedstreamnumber = %d ",requestedstreamnumber) ;
state = S_WAITING_FILENAME_RETR ;
FREE(receive_buffer) ;
return 0 ;
}
case MSG_STORE_V2 :{
syslog(BBFTPD_DEBUG,"Receiving MSG_STORE_V2") ;
if ( (receive_buffer = (char *) malloc (msglen)) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating memory for MSG_STORE_V2 : %s",strerror(errno)) ;
return -1 ;
}
if ( readmessage(incontrolsock,receive_buffer,msglen,recvcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error reading MSG_STORE_V2") ;
FREE(receive_buffer) ;
return -1 ;
}
msg_store_v2 = (struct mess_store_v2 *) receive_buffer ;
/*
** Set up the transfer parameter, we are going only to store
** them
*/
#ifndef WORDS_BIGENDIAN
transferoption = msg_store_v2->transferoption ;
filemode = ntohl(msg_store_v2->filemode) ;
strncpy(lastaccess,msg_store_v2->lastaccess,8) ;
lastaccess[8] = '\0' ;
strncpy(lastmodif,msg_store_v2->lastmodif,8) ;
lastmodif[8] = '\0' ;
sendwinsize = ntohl(msg_store_v2->sendwinsize) ;
recvwinsize = ntohl(msg_store_v2->recvwinsize) ;
buffersizeperstream = ntohl(msg_store_v2->buffersizeperstream) ;
requestedstreamnumber = ntohl(msg_store_v2->nbstream) ;
filesize = ntohll(msg_store_v2->filesize) ;
#else
transferoption = msg_store_v2->transferoption ;
filemode = msg_store_v2->filemode ;
strncpy(lastaccess,msg_store_v2->lastaccess,8) ;
lastaccess[8] = '\0' ;
strncpy(lastmodif,msg_store_v2->lastmodif,8) ;
lastmodif[8] = '\0' ;
sendwinsize = msg_store_v2->sendwinsize ;
recvwinsize = msg_store_v2->recvwinsize ;
buffersizeperstream = msg_store_v2->buffersizeperstream ;
requestedstreamnumber = msg_store_v2->nbstream ;
filesize = msg_store_v2->filesize ;
#endif
syslog(BBFTPD_DEBUG,"transferoption = %d ",transferoption) ;
syslog(BBFTPD_DEBUG,"filemode = %d ",filemode) ;
syslog(BBFTPD_DEBUG,"lastaccess = %s ",lastaccess) ;
syslog(BBFTPD_DEBUG,"lastmodif = %s ",lastmodif) ;
syslog(BBFTPD_DEBUG,"sendwinsize = %d ",sendwinsize) ;
syslog(BBFTPD_DEBUG,"recvwinsize = %d ",recvwinsize) ;
syslog(BBFTPD_DEBUG,"buffersizeperstream = %d ",buffersizeperstream) ;
syslog(BBFTPD_DEBUG,"requestedstreamnumber = %d ",requestedstreamnumber) ;
syslog(BBFTPD_DEBUG,"filesize = %" LONG_LONG_FORMAT " ",filesize) ;
state = S_WAITING_FILENAME_STORE ;
FREE(receive_buffer) ;
return 0 ;
}
default :{
syslog(BBFTPD_ERR,"Unkown message in logged state %d",msgcode) ;
retcode = discardmessage(incontrolsock,msglen,recvcontrolto) ;
reply(MSG_BAD_NO_RETRY,"Unkown message in S_LOGGED state") ;
return retcode ;
}
}
}
/*
** Case S_WAITING_FILENAME_STORE
**
** MSG_FILENAME
*/
case S_WAITING_FILENAME_STORE : {
switch (msgcode) {
case MSG_FILENAME :{
syslog(BBFTPD_DEBUG,"Receiving MSG_FILENAME in S_WAITING_FILENAME_STORE state") ;
if ( msglen == 0 ) {
syslog(BBFTPD_ERR,"Filename length null") ;
return -1 ;
}
if ( (curfilename = (char *) malloc (msglen+1)) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating memory for filename : %s",strerror(errno)) ;
return -1 ;
}
/* tmp name = <name>.bbftp.tmp.<hostname in 10 chars>.<pid in 5 chars> */
if ( (realfilename = (char *) malloc (msglen+30)) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating memory for realfilename : %s",strerror(errno)) ;
free_all_var() ;
return -1 ;
}
if ( readmessage(incontrolsock,curfilename,msglen,recvcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error reading filename") ;
free_all_var() ;
return -1 ;
}
curfilename[msglen] = '\0' ;
curfilenamelen = msglen ;
syslog(BBFTPD_DEBUG,"Request to store file %s",curfilename) ;
if ( (retcode = bbftpd_storecheckoptions(logmessage)) < 0 ) {
syslog(BBFTPD_ERR,logmessage) ;
reply(MSG_BAD_NO_RETRY,logmessage) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
}
/*
** Options are corrects
*/
if ( (transferoption & TROPT_TMP ) == TROPT_TMP ) {
/*
** Caculate tempfile name if TROPT_TMP is set
** To avoid multiple access to temp file in HPSS
** file is called .bbftp.tmp.$host.$pid
*/
char hostname[10 + 1];
if (gethostname(hostname, sizeof(hostname)) < 0) {
sprintf(realfilename,"%s.bbftp.tmp.%d",curfilename,getpid());
} else {
hostname[sizeof(hostname) - 1] = '\0';
sprintf(realfilename,"%s.bbftp.tmp.%s.%d",curfilename,hostname,getpid()) ;
}
} else {
sprintf(realfilename,"%s",curfilename) ;
}
/*
** Create the file
*/
if ( (retcode = bbftpd_storecreatefile(realfilename,logmessage)) < 0 ) {
syslog(BBFTPD_ERR,logmessage) ;
reply(MSG_BAD_NO_RETRY,logmessage) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
} else if ( retcode > 0 ) {
syslog(BBFTPD_ERR,logmessage) ;
reply(MSG_BAD,logmessage) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
} else {
if ( filesize == 0 ) {
if ((transferoption & TROPT_ACC ) == TROPT_ACC ) {
sscanf(lastaccess,"%08x",&ftime.actime) ;
sscanf(lastmodif,"%08x",&ftime.modtime) ;
if ( bbftpd_storeutime(realfilename,&ftime,logmessage) < 0 ) {
syslog(BBFTPD_ERR,logmessage) ;
bbftpd_storeunlink(realfilename) ;
reply(MSG_BAD,logmessage) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
}
}
if ( (transferoption & TROPT_MODE ) == TROPT_MODE ) {
if ( bbftpd_storechmod(realfilename,filemode,logmessage) < 0 ) {
syslog(BBFTPD_ERR,logmessage) ;
bbftpd_storeunlink(realfilename) ;
reply(MSG_BAD,logmessage) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
}
}
if ( (transferoption & TROPT_TMP ) == TROPT_TMP ) {
if ( bbftpd_storerename(realfilename,curfilename,logmessage) < 0 ) {
syslog(BBFTPD_ERR,logmessage) ;
bbftpd_storeunlink(realfilename) ;
reply(MSG_BAD,logmessage) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
}
}
reply(MSG_OK,"") ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
} else {
/*
** We are reserving the memory for the ports
*/
if ( (myports = (int *) malloc (requestedstreamnumber*sizeof(int))) == NULL ) {
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
syslog(BBFTPD_ERR,"Unable to allocate memory for myports") ;
sprintf(logmessage,"Unable to allocate memory for myports") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
/*
** We are reserving the memory for the children pid
*/
if ( (mychildren = (int *) malloc (requestedstreamnumber*sizeof(int))) == NULL) {
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
syslog(BBFTPD_ERR,"Unable to allocate memory for mychildren") ;
sprintf(logmessage,"Unable to allocate memory for mychildren") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
/*
** We are reserving the memory for the readbuffer
*/
if ( (readbuffer = (char *) malloc (buffersizeperstream*1024)) == NULL) {
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
syslog(BBFTPD_ERR,"Unable to allocate memory for readbuffer") ;
sprintf(logmessage,"Unable to allocate memory for readbuffer") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
/*
** We are reserving the memory for the compression buffer
** if needed
*/
if ( (transferoption & TROPT_GZIP ) == TROPT_GZIP ) {
if ( (compbuffer = (char *) malloc (buffersizeperstream*1024)) == NULL) {
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
syslog(BBFTPD_ERR,"Unable to allocate memory for compbuffer") ;
sprintf(logmessage,"Unable to allocate memory for compbuffer") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
}
if ( (receive_buffer = (char *) malloc (STORMESSLEN_V2)) == NULL ) {
bbftpd_storeunlink(realfilename) ;
syslog(BBFTPD_ERR,"Error allocating memory for MSG_TRANS_OK_V2 : %s",strerror(errno)) ;
free_all_var() ;
sprintf(logmessage,"Unable to allocate memory for message MSG_TRANS_OK_V2") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
msg = (struct message *) receive_buffer ;
if ( protocolversion == 2) { /* ACTIVE MODE */
msg->code = MSG_TRANS_OK_V2 ;
} else { /* PASSIVE MODE */
msg->code = MSG_TRANS_OK_V3 ;
}
#ifndef WORDS_BIGENDIAN
msg->msglen = ntohl(STORMESSLEN_V2) ;
#else
msg->msglen = STORMESSLEN_V2 ;
#endif
if ( writemessage(outcontrolsock,receive_buffer,MINMESSLEN,sendcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error wtiting MSG_TRANS_OK_V2 first part") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
msg_store_v2 = (struct mess_store_v2 *) receive_buffer ;
/*
** Set up the transfer parameter
*/
#ifndef WORDS_BIGENDIAN
msg_store_v2->transferoption = transferoption ;
msg_store_v2->filemode = ntohl(filemode) ;
strncpy(msg_store_v2->lastaccess,lastaccess,8) ;
msg_store_v2->lastaccess[8] = '0' ;
strncpy(msg_store_v2->lastmodif,lastmodif,8) ;
msg_store_v2->lastmodif[8] = '0' ;
msg_store_v2->sendwinsize = ntohl(sendwinsize) ;
msg_store_v2->recvwinsize = ntohl(recvwinsize) ;
msg_store_v2->buffersizeperstream = ntohl(buffersizeperstream) ;
msg_store_v2->nbstream = ntohl(requestedstreamnumber) ;
msg_store_v2->filesize = ntohll(filesize) ;
#else
msg_store_v2->transferoption = transferoption ;
msg_store_v2->filemode = filemode;
strncpy(msg_store_v2->lastaccess,lastaccess,8) ;
msg_store_v2->lastaccess[8] = '0' ;
strncpy(msg_store_v2->lastmodif,lastmodif,8) ;
msg_store_v2->lastmodif[8] = '0' ;
msg_store_v2->sendwinsize = sendwinsize ;
msg_store_v2->recvwinsize = recvwinsize ;
msg_store_v2->buffersizeperstream = buffersizeperstream ;
msg_store_v2->nbstream = requestedstreamnumber;
msg_store_v2->filesize = filesize ;
#endif
if ( writemessage(outcontrolsock,receive_buffer,STORMESSLEN_V2,sendcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error wtiting MSG_TRANS_OK_V2 second part") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
/* PASSIVE MODE: send ports */
if ( protocolversion >= 3 ) {
/*
** We are reserving the memory for the ports
*/
if ( (mysockets = (int *) malloc (requestedstreamnumber*sizeof(int))) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating space for sockets") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
if ( bbftpd_getdatasock(requestedstreamnumber) < 0 ) {
syslog(BBFTPD_ERR,"Error creating data sockets") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
portfree = (int *)receive_buffer ;
porttosend = myports ;
for (i=0 ; i<requestedstreamnumber ; i++) {
#ifndef WORDS_BIGENDIAN
*portfree++ = ntohl(ntohs(*porttosend++)) ;
#else
*portfree++ = *porttosend++ ;
#endif
}
/* syslog(BBFTPD_INFO,"Port=%d,socket=%d\n",*myports,*mysockets) ;*/
if ( writemessage(outcontrolsock,receive_buffer,requestedstreamnumber*sizeof(int),sendcontrolto) < 0) {
syslog(BBFTPD_ERR,"Error writing MSG_TRANS_OK_V3 (ports)") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
} /* END PASSIVE MODE */
state = S_WAITING_STORE_START ;
FREE(receive_buffer) ;
return 0 ;
}
}
}
default :{
syslog(BBFTPD_ERR,"Unkown message in S_WAITING_FILENAME_STORE state : %d",msgcode) ;
return -1 ;
}
}
}
/*
** Case S_WAITING_FILENAME_RETR
**
** MSG_FILENAME
*/
case S_WAITING_FILENAME_RETR : {
switch (msgcode) {
case MSG_FILENAME :{
syslog(BBFTPD_DEBUG,"Receiving MSG_FILENAME in S_WAITING_FILENAME_RETR state") ;
if ( msglen == 0 ) {
syslog(BBFTPD_ERR,"Filename length null") ;
return -1 ;
}
if ( (curfilename = (char *) malloc (msglen+1)) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating memory for filename : %s",strerror(errno)) ;
return -1 ;
}
if ( readmessage(incontrolsock,curfilename,msglen,recvcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error reading filename") ;
free_all_var() ;
return -1 ;
}
curfilename[msglen] = '\0' ;
curfilenamelen = msglen ;
syslog(BBFTPD_DEBUG,"Request to retreive file %s",curfilename) ;
/*
** Create the file
*/
if ( (retcode = bbftpd_retrcheckfile(curfilename,logmessage)) < 0 ) {
syslog(BBFTPD_ERR,logmessage) ;
reply(MSG_BAD_NO_RETRY,logmessage) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
} else if ( retcode > 0 ) {
syslog(BBFTPD_ERR,logmessage) ;
reply(MSG_BAD,logmessage) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
} else {
if ( filesize != 0 ) {
/*
** We are reserving the memory for the ports
*/
if ( (myports = (int *) malloc (requestedstreamnumber*sizeof(int))) == NULL ) {
free_all_var() ;
syslog(BBFTPD_ERR,"Unable to allocate memory for myports") ;
sprintf(logmessage,"Unable to allocate memory for myports") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
/*
** We are reserving the memory for the children pid
*/
if ( (mychildren = (int *) malloc (requestedstreamnumber*sizeof(int))) == NULL) {
free_all_var() ;
syslog(BBFTPD_ERR,"Unable to allocate memory for mychildren") ;
sprintf(logmessage,"Unable to allocate memory for mychildren") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
/*
** We are reserving the memory for the readbuffer
*/
if ( (readbuffer = (char *) malloc (buffersizeperstream*1024)) == NULL) {
free_all_var() ;
syslog(BBFTPD_ERR,"Unable to allocate memory for readbuffer") ;
sprintf(logmessage,"Unable to allocate memory for readbuffer") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
/*
** We are reserving the memory for the compression buffer
** if needed
*/
if ( (transferoption & TROPT_GZIP ) == TROPT_GZIP ) {
#ifdef WITH_GZIP
if ( (compbuffer = (char *) malloc (buffersizeperstream*1024)) == NULL) {
free_all_var() ;
syslog(BBFTPD_ERR,"Unable to allocate memory for compbuffer") ;
sprintf(logmessage,"Unable to allocate memory for compbuffer") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
#else
transferoption = transferoption & ~TROPT_GZIP ;
#endif
}
}
if ( (receive_buffer = (char *) malloc (STORMESSLEN_V2)) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating memory for MSG_TRANS_OK_V2 : %s",strerror(errno)) ;
free_all_var() ;
sprintf(logmessage,"Unable to allocate memory for message MSG_TRANS_OK_V2") ;
reply(MSG_BAD,logmessage) ;
state = S_LOGGED ;
return 0 ;
}
msg = (struct message *) receive_buffer ;
if ( protocolversion == 2) { /* ACTIVE MODE */
msg->code = MSG_TRANS_OK_V2 ;
} else { /* PASSIVE MODE */
msg->code = MSG_TRANS_OK_V3 ;
}
#ifndef WORDS_BIGENDIAN
msg->msglen = ntohl(STORMESSLEN_V2) ;
#else
msg->msglen = STORMESSLEN_V2 ;
#endif
if ( writemessage(outcontrolsock,receive_buffer,MINMESSLEN,sendcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error writing MSG_TRANS_OK_V2 first part") ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
msg_store_v2 = (struct mess_store_v2 *) receive_buffer ;
/*
** Set up the transfer parameter
*/
#ifndef WORDS_BIGENDIAN
msg_store_v2->transferoption = transferoption ;
msg_store_v2->filemode = ntohl(filemode) ;
strncpy(msg_store_v2->lastaccess,lastaccess,8) ;
msg_store_v2->lastaccess[8] = '0' ;
strncpy(msg_store_v2->lastmodif,lastmodif,8) ;
msg_store_v2->lastmodif[8] = '0' ;
msg_store_v2->sendwinsize = ntohl(sendwinsize) ;
msg_store_v2->recvwinsize = ntohl(recvwinsize) ;
msg_store_v2->buffersizeperstream = ntohl(buffersizeperstream) ;
msg_store_v2->nbstream = ntohl(requestedstreamnumber) ;
msg_store_v2->filesize = ntohll(filesize) ;
#else
msg_store_v2->transferoption = transferoption ;
msg_store_v2->filemode = filemode;
strncpy(msg_store_v2->lastaccess,lastaccess,8) ;
msg_store_v2->lastaccess[8] = '0' ;
strncpy(msg_store_v2->lastmodif,lastmodif,8) ;
msg_store_v2->lastmodif[8] = '0' ;
msg_store_v2->sendwinsize = sendwinsize ;
msg_store_v2->recvwinsize = recvwinsize ;
msg_store_v2->buffersizeperstream = buffersizeperstream ;
msg_store_v2->nbstream = requestedstreamnumber;
msg_store_v2->filesize = filesize ;
#endif
if ( writemessage(outcontrolsock,receive_buffer,STORMESSLEN_V2,sendcontrolto) < 0 ) {
syslog(BBFTPD_ERR,"Error writing MSG_TRANS_OK_V2 second part") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
if ( filesize == 0 ) {
char statmessage[1024];
state = S_WAITING_CREATE_ZERO ;
sprintf(statmessage,"GET %s %s 0 0 0.0 0.0", currentusername, curfilename);
syslog(BBFTPD_NOTICE,statmessage);
free_all_var() ;
} else {
/* PASSIVE MODE: send ports */
if ( protocolversion >= 3 ) {
/*
** We are reserving the memory for the ports
*/
if ( (mysockets = (int *) malloc (requestedstreamnumber*sizeof(int))) == NULL ) {
syslog(BBFTPD_ERR,"Error allocating space for sockets") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
if ( bbftpd_getdatasock(requestedstreamnumber) < 0 ) {
syslog(BBFTPD_ERR,"Error creating data sockets") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
portfree = (int *)receive_buffer ;
porttosend = myports ;
for (i=0 ; i<requestedstreamnumber ; i++) {
#ifndef WORDS_BIGENDIAN
*portfree++ = ntohl(ntohs(*porttosend++)) ;
#else
*portfree++ = *porttosend++ ;
#endif
}
/* syslog(BBFTPD_INFO,"Port=%d,socket=%d\n",*myports,*mysockets) ;*/
if ( writemessage(outcontrolsock,receive_buffer,requestedstreamnumber*sizeof(int),sendcontrolto) < 0) {
syslog(BBFTPD_ERR,"Error writing MSG_TRANS_OK_V3 (ports)") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
FREE(receive_buffer) ;
return -1 ;
}
} /* END PASSIVE MODE */
state = S_WAITING_RETR_START ;
}
FREE(receive_buffer) ;
return 0 ;
}
}
default :{
syslog(BBFTPD_ERR,"Unkown message in S_WAITING_FILENAME state : %d",msgcode) ;
return -1 ;
}
}
}
/*
** Case S_WAITING_STORE_START
**
** MSG_TRANS_START_V2
** MSG_TRANS_SIMUL
** MSG_ABORT
*/
case S_WAITING_STORE_START : {
switch (msgcode) {
case MSG_TRANS_START_V2 :
case MSG_TRANS_SIMUL :
case MSG_TRANS_START_V3 :
case MSG_TRANS_SIMUL_V3 :{
int simulation = ((msgcode == MSG_TRANS_SIMUL) || (msgcode == MSG_TRANS_SIMUL_V3)?1:0);
syslog(BBFTPD_DEBUG,"Receiving MSG_TRANS_START_V2") ;
if ( msglen != requestedstreamnumber*sizeof(int)) {
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
reply(MSG_BAD,"Inconsistency between MSG_TRANS_START_V2 and message length") ;
syslog(BBFTPD_ERR,"Inconsistency between MSG_TRANS_START_V2 and message length") ;
return -1 ;
}
if (msgcode == MSG_TRANS_START_V2 || msgcode == MSG_TRANS_SIMUL) { /* ACTIVE MODE */
/*
** Retreive port numbers
*/
if ( readmessage(incontrolsock,(char *) myports,msglen,recvcontrolto) < 0 ) {
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
syslog(BBFTPD_ERR,"Error reading MSG_TRANS_START_V2") ;
return -1 ;
} else {
#ifndef WORDS_BIGENDIAN
portfree = myports ;
for (i=0 ; i < requestedstreamnumber ; i++ ) {
*portfree = ntohl(*portfree) ;
portfree++ ;
}
#endif
portfree = myports ;
for (i=0 ; i < requestedstreamnumber ; i++ ) {
portfree++ ;
}
}
}
if ( (retcode = bbftpd_storetransferfile(realfilename,simulation,logmessage)) == 0 ) {
/*
** Everything seems to work correctly
*/
return 0 ;
}
if ( retcode > 0 ) {
/*
** Something goes wrong
*/
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
}
/*
**
*/
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
state = S_LOGGED ;
return -1 ;
}
case MSG_ABORT : {
syslog(BBFTPD_ERR,"Receive ABORT message") ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
}
default :{
syslog(BBFTPD_ERR,"Unkown message in S_WAITING_STORE_START state : %d",msgcode) ;
bbftpd_storeunlink(realfilename) ;
free_all_var() ;
return -1 ;
}
}
}
/*
** Case S_WAITING_CREATE_ZERO
**
** MSG_CREATE_ZERO
** MSG_ABORT
*/
case S_WAITING_CREATE_ZERO : {
switch (msgcode) {
case MSG_CREATE_ZERO : {
syslog(BBFTPD_ERR,"Receive MSG_CREATE_ZERO message ") ;
state = S_LOGGED ;
return 0 ;
}
case MSG_ABORT : {
syslog(BBFTPD_ERR,"Receive ABORT message") ;
state = S_LOGGED ;
return 0 ;
}
default :{
syslog(BBFTPD_ERR,"Unkown message in S_WAITING_CREATE_ZERO state : %d",msgcode) ;
return -1 ;
}
}
}
/*
** Case S_WAITING_RETR_START
**
** MSG_TRANS_START_V2
** MSG_TRANS_SIMUL
** MSG_ABORT
*/
case S_WAITING_RETR_START : {
switch (msgcode) {
case MSG_TRANS_START_V2 :
case MSG_TRANS_SIMUL :
case MSG_TRANS_START_V3 :
case MSG_TRANS_SIMUL_V3 :{
int simulation = ((msgcode == MSG_TRANS_SIMUL) || (msgcode == MSG_TRANS_SIMUL_V3)?1:0);
syslog(BBFTPD_DEBUG,"Receiving MSG_TRANS_START_V2") ;
if ( msglen != requestedstreamnumber*sizeof(int)) {
free_all_var() ;
reply(MSG_BAD,"Inconsistency between MSG_TRANS_START_V2 and message length") ;
syslog(BBFTPD_ERR,"Inconsistency between MSG_TRANS_START_V2 and message length") ;
return -1 ;
}
if (msgcode == MSG_TRANS_START_V2 || msgcode == MSG_TRANS_SIMUL) { /* ACTIVE MODE */
/*
** Retreive port numbers
*/
if ( readmessage(incontrolsock,(char *) myports,msglen,recvcontrolto) < 0 ) {
free_all_var() ;
syslog(BBFTPD_ERR,"Error reading MSG_TRANS_START_V2") ;
return -1 ;
} else {
#ifndef WORDS_BIGENDIAN
portfree = myports ;
for (i=0 ; i < requestedstreamnumber ; i++ ) {
*portfree = ntohl(*portfree) ;
portfree++ ;
}
#endif
/*portfree = myports ;
for (i=0 ; i < requestedstreamnumber ; i++ ) {
portfree++ ;
}*/
}
}
if ( (retcode = bbftpd_retrtransferfile(curfilename,simulation,logmessage)) == 0 ) {
/*
** Everything seems to work correctly
*/
return 0 ;
}
if ( retcode > 0 ) {
/*
** Something goes wrong
*/
syslog(BBFTPD_ERR,"retrtransferfile retcode > 0") ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
}
/*
**
*/
syslog(BBFTPD_ERR,"retrtransferfile retcode < 0") ;
free_all_var() ;
state = S_LOGGED ;
return -1 ;
}
case MSG_ABORT : {
syslog(BBFTPD_ERR,"Receive ABORT message") ;
free_all_var() ;
state = S_LOGGED ;
return 0 ;
}
default :{
syslog(BBFTPD_ERR,"Unkown message in S_WAITING_RETR_START state : %d",msgcode) ;
return -1 ;
}
}
}
/*
** Case S_SENDING or S_RECEIVING
*/
case S_SENDING : {
switch (msgcode) {
case MSG_ABORT :{
syslog(BBFTPD_ERR,"Receive MSG_ABORT while sending") ;
return -1 ;
}
default :{
syslog(BBFTPD_ERR,"Unkown message in S_SENDING state: %d",msgcode) ;
return -1 ;
}
}
}
case S_RECEIVING : {
switch (msgcode) {
case MSG_ABORT :{
syslog(BBFTPD_ERR,"Receive MSG_ABORT while receiving") ;
bbftpd_storeclosecastfile(realfilename,logmessage) ;
bbftpd_storeunlink(realfilename) ;
return -1 ;
}
default :{
syslog(BBFTPD_ERR,"Unkown message in S_RECEIVING state : %d",msgcode) ;
bbftpd_storeclosecastfile(realfilename,logmessage) ;
bbftpd_storeunlink(realfilename) ;
return -1 ;
}
}
}
/*
** Any other state
*/
default : {
syslog(BBFTPD_ERR,"Receive message in state %d",state) ;
return -1 ;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1