source: TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd.c @ 1100

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd.c@1100
Revision 1100, 43.7 KB checked in by spascoe, 14 years ago (diff)

Python code on the server will now receive the private string from the
client. This is the basic requirement for doing bbftp authentication
within python.

Slightly higher level message passing functions ndg_message_send/recv are now
bound to python callbacks bbftpd.send and bbftpd.recv.

Line 
1/*
2 * bbftpd/bbftpd.c
3 * Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS
4 * bbftp@in2p3.fr
5 * http://doc.in2p3.fr/bbftp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */ 
21
22/****************************************************************************
23
24 
25 
26 bbftpd.c v 0.0.0  1999/11/24
27          v 1.3.0  2000/03/16   - Version in openlog
28          v 1.4.0  2000/03/22   - Modify the connection protocole
29                                  in order to send the crypt type
30                                  after the connection.
31          v 1.5.0  2000/03/24   - Change the wait timer in default
32          v 1.6.0  2000/03/24   - Change the main loop to make it more
33                                    modular
34          v 1.6.1  2000/03/24   - Portage on OSF1
35                                - Make the control socket non blocking
36          v 1.8.0  2000/04/14   - Introduce RSA Cryptage
37          v 1.8.6  2000/05/21   - Allow to run with inetd
38          v 1.8.7  2000/05/24   - Introduce version.h and config.h
39          v 1.8.10 2000/08/11   - Portage to Linux
40          v 1.9.0  2000/08/18   - Use configure to help portage
41                                - default time out set to 900 s
42          v 1.9.3  2000/10/12   - Add -b and -w option in order to overwrite
43                                  the fixed values
44          v 1.9.4  2000/10/16   - Make all sockets blocking in order
45                                  to prevent the error in case of lack
46                                  of memory
47                                - Supress %m
48          v 2.0.0  2001/03/26   - Protocol V2 implementation
49          v 2.0.1  2001/04/23   - Correct indentation
50                                - Port to IRIX
51          v 2.0.2  2001/05/07   - Add debug option for RFIO
52          v 2.1.0  2001/05/28   - Add private authentication
53                                - Correct syslog level
54                                - Add -l option
55                  v 2.2.0  2001/10/03   - Add the certificate authentication process
56
57*****************************************************************************/
58
59
60#include <bbftpd.h>
61
62#include <errno.h>
63#include <fcntl.h>
64#include <limits.h>
65#include <netdb.h>
66#include <netinet/in.h>
67#include <arpa/inet.h>
68#include <netinet/tcp.h>
69#include <pwd.h>
70#include <signal.h>
71#include <stdio.h>
72#include <syslog.h>
73#include <sys/socket.h>
74#include <sys/wait.h>
75#if TIME_WITH_SYS_TIME
76# include <sys/time.h>
77# include <time.h>
78#else
79# if HAVE_SYS_TIME_H
80#  include <sys/time.h>
81# else
82#  include <time.h>
83# endif
84#endif
85#include <sys/stat.h>
86#include <unistd.h>
87#include <utime.h>
88#if HAVE_STRING_H
89# include <string.h>
90#endif
91
92#include <common.h>
93#include <config.h>
94#include <daemon.h>
95#include <daemon_proto.h>
96#include <status.h>
97#include <structures.h>
98#include <version.h>
99#ifdef CERTIFICATE_AUTH
100#include <gssapi.h>
101#include <gfw.h>
102#endif
103#ifdef HAVE_BYTESWAP_H
104#include <byteswap.h>
105#endif
106
107#include <openssl/rsa.h>
108
109#ifdef WITH_GZIP
110#include <zlib.h>
111#endif
112
113#ifdef CERTIFICATE_AUTH
114#define OPTIONS    "bcd:fl:m:pR:suvw:"
115#else
116#define OPTIONS    "bd:e:fl:m:R:suvw:"
117#endif
118
119/*
120** Common variables for BBFTP protocole version 1 and 2
121*/
122/*
123** be_daemon :
124**      That is the way the daemon is going to be run.
125**      0 means run by inetd (that can be done trought
126**      a wrapper)                                      (run as bbftpd)
127**      1 means that the control socket are stdin and
128**      stdout                                          (run as bbftpd -s)
129**      2 means running in background                   (run as bbftpd -b)
130**      Default 0
131*/
132int        be_daemon = 0 ;
133/*
134** daemonchar:
135**      String used to initialize openlog
136*/
137char        daemonchar[50] ;
138/*
139** fixeddataport :
140**      If set to 1 then the server will use CONTROLPORT-1
141**      to use as local port number for the data socket.
142**      It is useful to set it to 1 if the server is
143**      running behing a firewall.                      (run as bbftpd)
144**      If set to 0 then the server will not fixe the
145**      local data port                                 (run as bbftpd -f)
146**      Default 1
147*/
148int     fixeddataport = 1 ;
149/*
150** state :
151**      Define the state of the server. values differ depending
152**      of the BBFTP protocol version
153*/
154int        state ;                         
155/*
156** newcontrolport :
157**      Define the control port to listen on
158*/
159int        newcontrolport ; 
160/*
161** currentusername :
162**      Define the local username
163*/
164char currentusername[MAXLEN] ;
165/*
166** myrsa :
167**      Define the local location where is store the key pair
168*/
169RSA        *myrsa ;
170/*
171** his_addr :
172**      Remote address (the client)
173*/
174struct sockaddr_in his_addr;
175/*
176** ctrl_addr :
177**      Local adresse (the server)
178*/
179struct sockaddr_in ctrl_addr;
180/*
181** bbftpdrc:
182**      Where to store the bbftpdrc file
183*/
184char    *bbftpdrc = NULL ;
185/*
186** protocolversion :
187**      Set to 0 before any PROT message exchange, that also means
188**      that no children have been started
189*/
190int     protocolversion ;
191int     protocolmin = 1  ;
192int     protocolmax = 3  ;
193/*
194** fatherpid :
195**      The pid of the process keepng the control connection
196*/
197pid_t    fatherpid ;
198/*
199** flagsighup:
200**      Set to one when a SIGHUP is received
201**/
202int    flagsighup = 0 ;
203/*
204** killdone:
205**      Set to one when the father has send a kill to all chidren
206*/
207int    killdone= 0 ;
208/*
209** childendinerror:
210**      Set to one when one child has been detected in error in order
211**      to prevent father to send multiple answer
212*/
213int    childendinerror = 0 ;
214/*
215** unlinkfile:
216**      Set to one when father has to unlink the file to store. Used
217**      in case of child ended incorrectly (kill -9 for example)
218*/
219int    unlinkfile = 0  ;
220/*
221** debug:
222**      Set to one for RFIO debug. Valid only with the -b option
223**      set to the value needed for RFIO_TRACE
224*/
225int     debug = 0 ;
226/*
227** castfd:
228**      CASTOR file descriptor use with RFIO and CASTOR
229*/
230int     castfd ;
231/*
232** castfilename:
233**      CASTOR/SHIFT real file name
234*/
235char    *castfilename = NULL ;
236/*
237** End Common variables for BBFTP protocole version 1 and 2 ********************
238*/
239/*
240** Variables for BBFTP protocole version 1
241*/
242/*
243** msgsock :
244**      Define control socket for the server
245*/
246int     msgsock ;
247/*
248** currentfilename :
249**      Define the file we are working on
250*/
251char    currentfilename[MAXLENFILE];
252/*
253** pid_child :
254**      Array to store the children pid
255*/
256pid_t pid_child[MAXPORT] ;
257/*
258** End Variables for BBFTP protocole version 1 *********************************
259*/
260/*
261** Variables for BBFTP protocole version 2
262*/
263/*
264** incontrolsock :
265**      Define the control socket for reading
266** outcontrolsock :
267**      Define the control socket for writing
268**
269**      For be_daemon equal to 0 or 2 incontrolsock = outcontrolsock
270*/
271int     incontrolsock ;
272int     outcontrolsock ;
273/*
274** curfilename :
275**      Define the pointer to the current file
276*/
277char    *curfilename = NULL ;
278/*
279** curfilenamelen :
280**      Define the length of the memory used by curfilename
281*/
282int     curfilenamelen ;
283/*
284** realfilename :
285**      Define the pointer to the real file (= curfilename if TROPT_TMP not
286**      set)
287*/
288char    *realfilename = NULL ;
289/*
290** mychildren :
291**      Pointer to the first pid of children
292*/
293int     *mychildren = NULL ;
294/*
295** nbpidchid :
296**      Number of pid pointed by mychildren
297*/
298int     nbpidchild ;
299/*
300** myports :
301**      Pointer to the first port
302*/
303int     *myports = NULL ;
304/*
305** mysockets :
306**      Pointer to the first socket
307*/
308int     *mysockets = NULL ;
309/*
310** readbuffer :
311**      Pointer to the readbuffer
312*/
313int     *readbuffer = NULL ;
314/*
315** compbuffer :
316**      Pointer to the compression buffer
317*/
318int     *compbuffer = NULL ;
319/*
320** myumask :
321**      Umask for the bbftpd process, the default will be 022 which
322**      means that group and other write permissions are denied
323**      This can be changed by the bbftp umask command
324**/
325int     myumask = 022 ;
326/*
327**      Parameters describing the connection
328*/
329int         ackto           = ACKTO;
330int         recvcontrolto   = CONTROLSOCKTO;
331int         sendcontrolto   = SENDCONTROLTO;
332int         datato          = DATASOCKTO;
333int         checkstdinto    = CHECKSTDINTO;
334int     force_encoding  = 1;
335#ifdef CERTIFICATE_AUTH
336int     accept_certs_only = 0;
337int     accept_pass_only = 0;
338#endif
339/*
340** Parameters describing the transfer
341*/
342int     transferoption ;
343int     filemode ;
344char    lastaccess[9] ;
345char    lastmodif[9] ;
346int     sendwinsize ;       
347int     recvwinsize ;       
348int     buffersizeperstream ;
349int     requestedstreamnumber ;
350my64_t  filesize ;
351int     mycos = 0 ;
352/*
353** maxstreams :
354**      That is to fix the maximum number of stream the deamon will accept.
355**      (run as bbftpd -m 25)
356**      Default 25
357*/
358int     maxstreams = 25 ;
359/*
360** End Variables for BBFTP protocole version 2 *********************************
361*/
362/*
363 * Variables for protocol version 3 (PASV mode) ******************************
364*/
365/*
366 * Range for the ephemeral ports for data connections
367 */
368int     pasvport_min ;
369int     pasvport_max ;
370/*
371** End Variables for BBFTP protocole version 3 *********************************
372*/
373/*
374**  credentials for certificate authentication
375*/
376#ifdef CERTIFICATE_AUTH
377gss_cred_id_t   server_creds;
378#endif
379
380
381/*
382 * Stats
383*/
384struct  timeval  tstart;
385
386#ifdef NDG_PYTHON_EMBED
387int bbftpd_main (argc, argv, envp)
388#else
389main (argc,argv,envp)
390#endif //NDG_PYTHON_EMBED
391    int     argc ;
392    char    **argv ;
393    char    **envp ;
394{
395    extern char *optarg;
396    extern int optind, opterr, optopt;
397/*
398#if defined(SUNOS) || defined(_HPUX_SOURCE) || defined(IRIX)
399    int        addrlen ;
400#else
401    size_t        addrlen ;
402#endif
403*/
404#ifdef HAVE_SOCKLEN_T
405    socklen_t     addrlen ;
406#else
407    int           addrlen ;
408#endif
409    struct  timeval    wait_timer;
410    fd_set  selectmask ; 
411    int        nfds ; 
412    int        retcode ;
413    int        i, j, k ;
414    struct  message *msg ;
415    char    buffer[MINMESSLEN] ;
416    char    logmessage[1024] ;
417    char    rfio_trace[20] ;
418    struct  passwd  *mypasswd ;
419    char    *bbftpdrcfile = NULL ;
420    int     fd ;
421    char    *carret ;
422    char    *startcmd ;
423    int     nooption ;
424    struct  stat    statbuf ;
425    int     alluse ;
426   
427    sprintf(daemonchar,"bbftpd v%s",VERSION) ;
428    openlog(daemonchar, LOG_PID | LOG_NDELAY, BBFTPD_FACILITY);
429    /*
430    ** Set the log mask to BBFTPD_EMERG (0)
431    */
432    setlogmask(LOG_UPTO(BBFTPD_DEFAULT));
433    /*
434    ** Initialize variables
435    */
436    protocolversion = 0 ;
437#ifdef PORT_RANGE
438    sscanf(PORT_RANGE,"%d:%d",&pasvport_min, &pasvport_max) ;
439#endif
440
441    newcontrolport = CONTROLPORT ;
442    opterr = 0 ;
443    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
444        switch (j) {
445            case 'v' :{
446                printf("bbftpd version %s\n",VERSION) ;
447                printf("Compiled with  :   default port %d\n",CONTROLPORT) ;
448                printf("                   default maximum streams = %d \n",maxstreams) ;
449#ifdef PORT_RANGE
450                printf("                   data ports range = %s \n", PORT_RANGE) ;
451#endif
452#ifdef WITH_GZIP
453                printf("                   compression with Zlib-%s\n", zlibVersion()) ;
454#endif
455                printf("                   encryption with %s \n",SSLeay_version(SSLEAY_VERSION)) ;
456#ifdef WITH_RFIO
457# ifdef CASTOR
458                printf("                   CASTOR support (RFIO)\n") ;
459# else
460                printf("                   HPSS support (RFIO)\n") ;
461# endif
462#endif
463#ifdef WITH_RFIO64
464# ifdef CASTOR
465                printf("                   CASTOR support (RFIO64)\n") ;
466# else
467                printf("                   HPSS support (RFIO64)\n") ;
468# endif
469#endif
470#ifdef AFS
471                printf("                   AFS authentication \n") ;
472#endif
473#ifdef CERTIFICATE_AUTH
474                printf("                   GSI authentication \n") ;
475#endif
476#ifdef PRIVATE_AUTH
477                printf("                   private authentication \n") ;
478#endif
479                exit(0) ;
480            }
481        }
482    }
483/* Check zlib version */
484#ifdef WITH_GZIP
485    {
486        int z0, z1;
487        if (0 != strcmp(zlibVersion(), ZLIB_VERSION)) {
488                printf ("WARNING zlib version changed since last compile.\n");
489                printf ("Compiled Version is %s\n", ZLIB_VERSION);
490                printf ("Linked   Version is %s\n", zlibVersion());
491        }
492        z0 = atoi (ZLIB_VERSION);
493        z1 = atoi (zlibVersion());
494        if (z0 != z1) {
495                printf ("ERROR: zlib is not compatible!\n");
496                printf ("zlib source can found at http://www.gzip.org/zlib/\n");
497                exit (0);
498        }
499
500    }
501#endif
502    /*
503    ** Look at the loglevel option
504    */
505    i = 0 ;
506    opterr = 0 ;
507    optind = 1 ;
508    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
509        switch (j) {
510            case 'l' :{
511                for ( i=0 ; i< strlen(optarg) ; i++ ) {
512                    optarg[i] = toupper(optarg[i]) ;
513                }
514                i = 0 ;
515                if ( !strcmp(optarg,"EMERGENCY") ) {
516                    i = BBFTPD_EMERG;
517                } else if ( !strcmp(optarg,"ALERT") ) {
518                    i = BBFTPD_ALERT;
519                } else if ( !strcmp(optarg,"CRITICAL") ) {
520                    i = BBFTPD_CRIT;
521                } else if ( !strcmp(optarg,"ERROR") ) {
522                    i = BBFTPD_ERR;
523                } else if ( !strcmp(optarg,"WARNING") ) {
524                    i = BBFTPD_WARNING;
525                } else if ( !strcmp(optarg,"NOTICE") ) {
526                    i = BBFTPD_NOTICE;
527                } else if ( !strcmp(optarg,"INFORMATION") ) {
528                    i = BBFTPD_INFO;
529                } else if ( !strcmp(optarg,"DEBUG") ) {
530                    i = BBFTPD_DEBUG;
531                }
532                if ( i > 0 ) {
533                    setlogmask(LOG_UPTO(i));
534                }
535                break ;
536            }
537        }
538    }
539    syslog(BBFTPD_DEBUG,"Starting bbftpd") ;
540    opterr = 0 ;
541    optind = 1 ;
542    while ((j = getopt(argc, argv, OPTIONS)) != -1) {
543        switch (j) {
544            case 'b' :{
545                if ( be_daemon != 0 ) {
546                    syslog(BBFTPD_ERR,"-b and -s options are incompatibles") ;
547                    exit(1) ;
548                }
549                be_daemon = 2 ;
550                break ;
551            }
552            case 'd' :{
553                sscanf(optarg,"%d",&i) ;
554                if ( i > 0 ) debug = i ;
555                break ;
556            }
557            case 'e' :{
558                if ((sscanf(optarg,"%d:%d",&i, &k) == 2) && (i < k)) {
559                  pasvport_min = i; pasvport_max = k;
560                } else {
561                  syslog(BBFTPD_ERR,"Invalid port range : %s",optarg) ;
562                  fprintf(stderr,"Invalid port range : %s\n",optarg) ;
563                  exit(1) ;
564                }
565                break ;
566            }
567            case 'f' :{
568                fixeddataport = 0 ;
569                break ;
570            }
571            case 'm' :{
572                sscanf(optarg,"%d",&i) ;
573                if ( i > 0 ) maxstreams = i ;
574                break ;
575            }
576            case 'R' :{
577                bbftpdrcfile = optarg ;
578                break ;
579            }
580            case 's' :{
581                if ( be_daemon != 0 ) {
582                    syslog(BBFTPD_ERR,"-b and -s options are incompatibles") ;
583                    exit(1) ;
584                }
585#ifdef PRIVATE_AUTH
586                syslog(BBFTPD_ERR,"-s option cannot be used with private authentication") ;
587                exit(1) ;               
588#endif
589                be_daemon = 1 ;
590                break ;
591            }
592            case 'u' :{
593                force_encoding = 0 ;
594                break ;
595            }
596            case 'w' :{
597                sscanf(optarg,"%d",&newcontrolport) ;
598                break ;
599            }
600#ifdef CERTIFICATE_AUTH
601            case 'c' :{
602                accept_certs_only = 1 ;
603                break ;
604            }
605            case 'p' :{
606                accept_pass_only = 1 ;
607                break ;
608            }
609#endif
610            default : {
611                break ;
612            }
613        }
614    }
615
616/*
617** Check for the local user in order to find the .bbftpdrc file
618*/
619    if ( bbftpdrcfile == NULL ) {
620        /*
621        ** look for the local user in order to find the .bbftpdrc file
622        ** use /etc/bbftpd.conf if root
623        */
624        if ( getuid() == 0) {
625            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1 )) == NULL ) {
626                syslog(BBFTPD_ERR, "Error allocationg space for config file name.\n") ;
627            } else {
628                strcpy(bbftpdrcfile,BBFTPD_CONF);
629            }
630        } else if ( (mypasswd = getpwuid(getuid())) == NULL ) {
631            syslog(BBFTPD_WARNING, "Unable to get passwd entry, using %s\n", BBFTPD_CONF) ;
632            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
633              strcpy(bbftpdrcfile,BBFTPD_CONF);
634            }
635        } else if ( mypasswd->pw_dir == NULL ) {
636            syslog(BBFTPD_WARNING, "No home directory, using %s\n", BBFTPD_CONF) ;
637            if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
638              strcpy(bbftpdrcfile,BBFTPD_CONF);
639            }
640        } else if ( (bbftpdrcfile = (char *) malloc (strlen(mypasswd->pw_dir)+11) ) == NULL ) {
641            syslog(BBFTPD_ERR, "Error allocationg space for bbftpdrc file name, .bbftpdrc will not be used\n") ;
642        } else {
643            strcpy(bbftpdrcfile,mypasswd->pw_dir) ;
644            strcat(bbftpdrcfile,"/.bbftpdrc") ;
645            if ( stat(bbftpdrcfile,&statbuf) < 0  ) {
646                bbftpdrcfile == NULL;
647                if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) {
648                  strcpy(bbftpdrcfile,BBFTPD_CONF);
649                }
650            }
651        }
652    }
653    if ( bbftpdrcfile != NULL ) {
654        if ( strncmp(bbftpdrcfile,"none",4) != 0 ) {
655            /*
656            ** Stat the file in order to get the length
657            */
658            if ( stat(bbftpdrcfile,&statbuf) < 0  ) {
659                /*
660                  syslog(BBFTPD_WARNING, "Error stating bbftpdrc file (%s)\n",bbftpdrcfile) ;
661                 */
662            } else if ( statbuf.st_size == 0 ) {
663                /*
664                ** do nothing
665                */
666            } else if ( (bbftpdrc = (char *) malloc (statbuf.st_size + 1 ) ) == NULL ) {
667                syslog(BBFTPD_ERR, "Error allocation memory for bbftpdrc, .bbftpdrc will not be used\n") ;
668            } else if ( ( fd  = open (bbftpdrcfile,O_RDONLY) )  < 0 ) {
669                syslog(BBFTPD_ERR, "Error openning .bbftpdrc file (%s) : %s \n",bbftpdrcfile,strerror(errno)) ;
670            } else if ( ( j = read( fd, bbftpdrc , statbuf.st_size )) != statbuf.st_size ) {
671                syslog(BBFTPD_ERR, "Error reading .bbftpdrc file (%s)\n",bbftpdrcfile) ;
672            } else {
673                bbftpdrc[j] = '\0' ;
674            }
675        }
676    }
677/*
678** Analyse the bbftpdrc command in order to supress forbiden command
679** Allowed commands are :
680**          setackto %d
681**          setrecvcontrolto %d
682**          setsendcontrolto %d
683**          setdatato %d
684**          setcheckstdinto %d
685**          setoption fixeddataport
686*/
687    if ( bbftpdrc != NULL ) {
688        carret = bbftpdrc ;
689        startcmd = bbftpdrc ;
690        /*
691        ** Strip starting CR
692        */
693        while (1) {
694            while ( *carret == 10 || *carret == ' ' ) carret++ ;
695            startcmd = carret ;
696            carret = (char *) strchr (carret, 10);
697            if ( carret == NULL ) break ;
698            *carret = '\0' ;
699            if (!strncmp(startcmd,"setackto",8)) {
700                retcode = sscanf(startcmd,"setackto %d",&alluse) ;
701                if ( retcode != 1  || alluse <= 0 ) {
702                    syslog(BBFTPD_WARNING, "Acknowledge timeout must be numeric and > 0\n") ;
703                } else {
704                    ackto = alluse ;
705                }
706            } else if (!strncmp(startcmd,"setrecvcontrolto",16)) {
707                retcode = sscanf(startcmd,"setrecvcontrolto %d",&alluse) ;
708                if ( retcode != 1  || alluse <= 0 ) {
709                    syslog(BBFTPD_WARNING, "Input control timeout must be numeric and > 0\n") ;
710                } else {
711                    recvcontrolto = alluse ;
712                }
713            } else if (!strncmp(startcmd,"setsendcontrolto",16)) {
714                retcode = sscanf(startcmd,"setsendcontrolto %d",&alluse) ;
715                if ( retcode != 1  || alluse <= 0 ) {
716                    syslog(BBFTPD_WARNING, "Output control timeout must be numeric and > 0\n") ;
717                } else {
718                    sendcontrolto = alluse ;
719                }
720            } else if (!strncmp(startcmd,"setdatato",9)) {
721                retcode = sscanf(startcmd,"setdatato %d",&alluse) ;
722                if ( retcode != 1  || alluse <= 0 ) {
723                    syslog(BBFTPD_WARNING, "Data timeout must be numeric and > 0\n") ;
724                } else {
725                    datato = alluse ;
726                }
727            } else if (!strncmp(startcmd,"setcheckstdinto",15)) {
728                retcode = sscanf(startcmd,"setcheckstdinto %d",&alluse) ;
729                if ( retcode != 1  || alluse <= 0 ) {
730                    syslog(BBFTPD_WARNING, "Check input timeout must be numeric and > 0\n") ;
731                } else {
732                    checkstdinto = alluse ;
733                }
734            } else if (!strncmp(startcmd,"setoption",9)) {
735                /*
736                ** look for the option
737                */
738                startcmd = startcmd + 9 ;
739                while (*startcmd == ' ' && *startcmd != '\0' ) startcmd++ ;
740                if ( !strncmp(startcmd,"no",2) ) {
741                    nooption = 1 ;
742                    startcmd = startcmd+2 ;
743                } else {
744                    nooption = 0 ;
745                }
746                if ( !strncmp(startcmd,"fixeddataport",9) ) {
747                    if ( nooption ) {
748                        if (fixeddataport == 1) { /* default value */
749                            fixeddataport = 0;
750                        }
751                    }
752                }
753            } else {
754                syslog(BBFTPD_WARNING, "Unkown command in .bbftpdrc file (%s)\n",startcmd) ;
755            }
756            carret++ ;
757        }
758    }
759    /*
760    ** Get 5K for castfilename in order to work with CASTOR
761    ** software (even if we are not using it)
762    */
763    if ( (castfilename = (char *) malloc (5000)) == NULL ) {
764        /*
765        ** Starting badly if we are unable to malloc 5K
766        */
767        syslog(BBFTPD_ERR,"No memory for CASTOR : %s",strerror(errno)) ;
768        fprintf(stderr,"No memory for CASTOR : %s\n",strerror(errno)) ;
769        exit(1) ;
770    }
771    /*
772    ** Reset debug to zero if -b option is not present
773    */
774    if ( (be_daemon != 2) ) debug = 0 ;
775    /*
776    ** Check if be_daemon = 0 and in this case reset the
777    ** control port to CONTROLPORT
778    */
779    if ( be_daemon == 0 ) newcontrolport = CONTROLPORT ;
780
781#ifdef CERTIFICATE_AUTH               
782    if (be_daemon != 1 && !accept_pass_only) {
783        OM_uint32 min_stat, maj_stat;
784        maj_stat = gfw_acquire_cred(&min_stat, NULL, &server_creds);
785        if (maj_stat != GSS_S_COMPLETE) {
786            gfw_msgs_list *messages = NULL;
787            gfw_status_to_strings(maj_stat, min_stat, &messages) ;
788            while (messages != NULL) {
789                syslog(BBFTPD_ERR,"gfw_acquire_cred: %s", messages->msg) ;
790                if (be_daemon == 2) fprintf(stderr,"Acquire credentials: %s\n", messages->msg) ;
791                messages = messages->next;
792            }
793            exit(1);
794        }
795    }
796#endif
797    if ( be_daemon == 2 ) {
798        /*
799        ** Run as a daemon
800        */
801#ifdef NDG_PYTHON_EMBED
802      if ((fatherpid = do_daemon(argc, argv, envp)) > 0) return fatherpid;
803#else
804        do_daemon(argc, argv, envp);
805#endif
806        /*
807        ** Check for debug
808        */
809        if ( debug != 0 ) {
810#if defined(WITH_RFIO) || defined(WITH_RFIO64)
811            sprintf(rfio_trace,"RFIO_TRACE=%d",debug) ;
812            retcode = putenv(rfio_trace) ;
813#endif
814            if ( retcode == 0 ) {
815                /*
816                ** reopen stdout to a file like /tmp/bbftpd.rfio.trace.pid
817                */
818                close(STDOUT_FILENO) ;
819                sprintf(logmessage,"/tmp/bbftp.rfio.trace.level.%d.%d",debug,getpid()) ;
820                (void) freopen(logmessage,"w",stdout) ;
821            }
822        }
823    } else if ( be_daemon == 1 ) {
824        /*
825        ** Run by a remote user
826        */
827        /*
828        ** Get the username
829        */
830        struct passwd *result ;
831        if ( (result = getpwuid(getuid())) == NULL ) {
832            syslog(BBFTPD_WARNING,"Error getting username") ;
833            sprintf(currentusername,"UID %d",getuid()) ;
834        } else {
835            strcpy(currentusername,result->pw_name) ;
836        }
837        /*
838        ** Set the control sock to stdin and stdout
839        */
840        incontrolsock = 0  ;
841        outcontrolsock = 1 ;
842        /*
843        ** As we cannot rely on the env variables to know the
844        ** remote host, we are going to wait on an undefined
845        ** port, send the MSG_LOGGED_STDIN and the port number
846        ** and wait for a connection...
847        */
848        checkfromwhere() ;
849        syslog(BBFTPD_INFO,"bbftpd started by : %s from %s",currentusername,inet_ntoa(his_addr.sin_addr)) ;
850    } else {
851        char    buffrand[NBITSINKEY] ;
852        struct timeval tp ;
853        unsigned int seed ;
854        /*
855        ** Load the error message from the crypto lib
856        */
857        ERR_load_crypto_strings() ;
858        /*
859        ** Initialize the buffrand buffer which is giong to be used to initialize the
860        ** random generator
861        */
862        /*
863        ** Take the usec to initialize the random session
864        */
865        gettimeofday(&tp,NULL) ;
866        seed = tp.tv_usec ;
867        srandom(seed) ;
868        for (i=0; i < sizeof(buffrand) ; i++) {
869            buffrand[i] = random() ;
870        }
871        /*
872        ** Initialize the random generator
873        */
874        RAND_seed(buffrand,NBITSINKEY) ;
875        incontrolsock = 0  ;
876        outcontrolsock = incontrolsock ;
877        msgsock = incontrolsock ;
878        /*
879        ** set the state
880        */
881        state = S_PROTWAIT ;
882    }
883    fatherpid = getpid() ;
884    if ( be_daemon == 2 || be_daemon == 0 ) {
885        /* Get the remote address */
886        addrlen = sizeof(his_addr);
887        if (getpeername(incontrolsock, (struct sockaddr *) &his_addr, &addrlen) < 0) {
888            syslog(BBFTPD_ERR, "getpeername (%s): %s", argv[0],strerror(errno));
889            exit(1);
890        }
891        addrlen = sizeof(ctrl_addr);
892        if (getsockname(incontrolsock, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) {
893            syslog(BBFTPD_ERR, "getsockname (%s): %s", argv[0],strerror(errno));
894            exit(1);
895        }
896        syslog(BBFTPD_INFO,"Getting new bbftp connexion from : %s",inet_ntoa(his_addr.sin_addr)) ;
897        /*
898        ** Send the encryption supported
899        */
900        sendcrypt() ;
901        /*
902        ** set the state
903        */
904login:
905        state = S_CONN ;
906        nfds = sysconf(_SC_OPEN_MAX) ;
907        FD_ZERO(&selectmask) ;
908        FD_SET(incontrolsock,&selectmask) ;
909        wait_timer.tv_sec  = 10 ;
910        wait_timer.tv_usec = 0 ;
911        if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) {
912            syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
913            exit(1) ;
914        } else if ( retcode == 0 ) {
915            syslog(BBFTPD_ERR,"Time OUT ") ;
916            exit(1) ;
917        } else {
918            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
919                syslog(BBFTPD_ERR,"Error reading MSG_LOG ") ;
920                exit(1) ;
921            }
922            msg = (struct message *) buffer ;
923            if ( msg->code == MSG_SERVER_STATUS ) {
924                sprintf(logmessage, "bbftpd version %s\n",VERSION) ;
925                sprintf(logmessage,"%sCompiled with  :   default port %d\n",logmessage,CONTROLPORT) ;
926#ifdef WITH_GZIP
927                sprintf(logmessage,"%s                   compression with Zlib-%s\n", logmessage,zlibVersion()) ;
928#endif
929                sprintf(logmessage,"%s                   encryption with %s \n",logmessage,SSLeay_version(SSLEAY_VERSION)) ;
930#ifdef WITH_RFIO
931# ifdef CASTOR
932                sprintf(logmessage,"%s                   CASTOR support (RFIO)\n",logmessage) ;
933# else
934                sprintf(logmessage,"%s                   HPSS support (RFIO)\n",logmessage) ;
935# endif
936#endif
937#ifdef WITH_RFIO64
938# ifdef CASTOR
939                sprintf(logmessage,"%s                   CASTOR support (RFIO64)\n",logmessage) ;
940# else
941                sprintf(logmessage,"%s                   HPSS support (RFIO64)\n",logmessage) ;
942# endif
943#endif
944#ifdef AFS
945                sprintf(logmessage,"%s                   AFS authentication \n",logmessage) ;
946#endif
947#ifdef CERTIFICATE_AUTH
948                sprintf(logmessage,"%s                   GSI authentication \n",logmessage) ;
949#endif
950#ifdef PRIVATE_AUTH
951                sprintf(logmessage,"%s                   private authentication \n",logmessage) ;
952#ifdef NDG_AUTH
953                sprintf(logmessage,"%s                   NDG private autentication/authorisation extensions \n", logmessage);
954#endif // NDG_AUTH
955#endif
956#ifdef NDG_PYTHON_EMBED
957                sprintf(logmessage,"%s                   NDG server embedded in Python \n", logmessage);
958                sprintf(logmessage,"%sRunning options:\n",logmessage) ;
959                sprintf(logmessage,"%s                   Maximum number of streams = %d \n",logmessage,maxstreams) ;
960                if (pasvport_min) {
961                    sprintf(logmessage,"%s                   data ports range = [%d-%d] \n", logmessage,pasvport_min, pasvport_max) ;
962                }
963#endif // NDG_PYTHON_EMBED
964#ifdef CERTIFICATE_AUTH
965                if (accept_pass_only) {
966                    sprintf(logmessage, "%s                   The server only accepts USER/PASS\n",logmessage);
967                }
968                if (accept_certs_only) {
969                    sprintf(logmessage, "%s                   The server only accepts certificates\n",logmessage);
970                }
971#endif
972#ifndef PRIVATE_AUTH
973                if (force_encoding) {
974                    sprintf(logmessage, "%s                   The server requires encrypted login\n",logmessage);
975                } else {
976                    sprintf(logmessage, "%s                   The server allows non-encrypted login\n",logmessage);
977                }
978#endif
979
980               
981                    reply(MSG_OK,logmessage);
982                    exit(0);
983            }
984#ifdef CERTIFICATE_AUTH
985            if ( msg->code == MSG_CERT_LOG ) {
986                int retval;
987                if (accept_pass_only) {
988                    sprintf(logmessage, "The server only accepts USER/PASS");
989                    syslog(BBFTPD_ERR,"%s",logmessage) ;
990                    reply(MSG_BAD_NO_RETRY,logmessage);
991                    exit(1);
992                }
993                retval=bbftpd_cert_receive_connection(msg->msglen);
994                if ( retval < 0 ) {
995                    /*
996                    ** The login failed, do not wait for a new one
997                    */
998                                        exit(1) ;
999                }
1000                /*
1001                ** If retval >0, means an MSG_WARN has been sent already
1002                */
1003                    state = S_PROTWAIT ;
1004                if (retval == 0) {
1005                    sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1006                    reply(MSG_OK,logmessage) ;
1007                }
1008            } else if ( msg->code == MSG_LOG ) {
1009                if (accept_certs_only) {
1010                    sprintf(logmessage, "The server only accepts certificates");
1011                    syslog(BBFTPD_ERR,"%s",logmessage) ;
1012                    reply(MSG_BAD_NO_RETRY,logmessage);
1013                } else {
1014                    /*
1015                    ** It seems that it is the message we were waiting
1016                    ** so lets decrypt
1017                    */
1018                    if ( loginsequence() < 0 ) {
1019                        /*
1020                        ** The login failed, do not wait for a new one
1021                        */
1022                        exit(1) ;
1023                    }
1024                    state = S_PROTWAIT ;
1025                    sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1026                    reply(MSG_OK,logmessage) ;
1027                }
1028            } else if (msg->code == MSG_CRYPT) { 
1029                if (accept_certs_only) {
1030                    sprintf(logmessage, "The server only accepts certificates");
1031                    reply(MSG_BAD_NO_RETRY,logmessage);
1032                } else if (force_encoding) {
1033                    /*
1034                    **  The client can't encode and ask if it can send uncrypted
1035                    **  login information
1036                    */
1037                    sprintf(logmessage, "The server requires encrypted login");
1038                    reply(MSG_BAD_NO_RETRY,logmessage);
1039                } else {
1040                    sprintf(logmessage, "Uncrypted login dialog accepted");
1041                    reply(MSG_OK,logmessage);
1042                    goto login;
1043                }
1044            } else {
1045                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1046                reply(MSG_BAD,"Unkown message in connected state") ;
1047                exit(1) ;
1048            }
1049#else
1050#ifndef PRIVATE_AUTH
1051            if ( msg->code == MSG_LOG ) {
1052                /*
1053                ** It seems that it is the message we were waiting
1054                ** so lets decrypt
1055                */
1056                if ( loginsequence() < 0 ) {
1057                    /*
1058                    ** The login failed, do not wait for a new one
1059                    */
1060                    exit(1) ;
1061                }
1062                state = S_PROTWAIT ;
1063                sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1064                reply(MSG_OK,logmessage) ;
1065            } else if (msg->code == MSG_CRYPT) { 
1066                /*
1067                **  The client can't encode and ask if it can send uncrypted
1068                **  login information
1069                */
1070                if (force_encoding) {
1071                    sprintf(logmessage, "The server requires encrypted login");
1072                    reply(MSG_BAD_NO_RETRY,logmessage);
1073                    exit(1);
1074                }
1075                sprintf(logmessage, "Uncrypted login dialog accepted");
1076                reply(MSG_OK,logmessage);
1077                goto login;
1078            } else {
1079                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1080                reply(MSG_BAD,"Unkown message in connected state") ;
1081                exit(1) ;
1082            }
1083#else
1084            if ( msg->code == MSG_PRIV_LOG ) {
1085                if ( bbftpd_private_receive_connection(msg->msglen) < 0 ) {
1086                    /*
1087                    ** The login failed, do not wait for a new one
1088                    */
1089                    exit(1) ;
1090                }
1091                state = S_PROTWAIT ;
1092                sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1093                reply(MSG_OK,logmessage) ;
1094            } else {
1095                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1096                reply(MSG_BAD,"Unkown message in connected state") ;
1097                exit(1) ;
1098            }
1099#endif
1100#endif
1101        }
1102    }
1103
1104    /*
1105    ** At this stage we are in the S_PROTWAIT state
1106    */
1107    nfds = sysconf(_SC_OPEN_MAX) ;
1108    FD_ZERO(&selectmask) ;
1109    FD_SET(incontrolsock,&selectmask) ;
1110    wait_timer.tv_sec  = 10 ;
1111    wait_timer.tv_usec = 0 ;
1112    if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) {
1113        syslog(BBFTPD_ERR,"Select error in S_PROTWAIT state : %s",strerror(errno)) ;
1114        exit(1) ;
1115    } else if ( retcode == 0 ) {
1116        syslog(BBFTPD_ERR,"Time OUT in S_PROTWAIT state") ;
1117        exit(1) ;
1118    } else {
1119        if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1120            syslog(BBFTPD_ERR,"Error reading in S_PROTWAIT state") ;
1121            exit(1) ;
1122        }
1123        msg = (struct message *) buffer ;
1124        if ( msg->code == MSG_PROT ) {
1125            /*
1126            ** The client is using bbftp v2 protocol or higher
1127            */
1128            if ( checkprotocol() < 0 ) {
1129                exit_clean() ;
1130                exit(1) ;
1131            }
1132            syslog(BBFTPD_INFO,"Using bbftp protocol version %d",protocolversion) ;
1133            state = S_LOGGED ;
1134            /*
1135            ** Initialize the variables
1136            */
1137            mychildren = NULL ;
1138            nbpidchild = 0 ;
1139            curfilename = NULL ;
1140            curfilenamelen = 0 ;
1141        } else {
1142            /*
1143            ** This is a bbftp v1 client
1144            */
1145            protocolversion = 1 ;
1146            syslog(BBFTPD_INFO,"Using bbftp protocol version 1") ;
1147            state = S_LOGGED ;
1148            /*
1149            ** So set up the v1 handlers
1150            */
1151            if ( set_signals_v1() < 0 ) {
1152                exit(1) ;
1153            }
1154            /*
1155            ** Initialize the pid array
1156            */
1157            for ( i=0 ; i< MAXPORT ; i++) {
1158                pid_child[i] = 0 ;
1159            }
1160            /*
1161            ** As we have already read the message
1162            */
1163            if ( readcontrol(msg->code,msg->msglen) < 0 ) { 
1164                clean_child() ;
1165                exit_clean() ;
1166                exit(0) ;
1167            }
1168        }
1169    }
1170    if ( protocolversion == 1 ) goto loopv1 ;
1171    if ( protocolversion == 2 || protocolversion == 3) goto loopv2 ;
1172    syslog(BBFTPD_ERR,"Unknown protocol version %d",protocolversion) ;
1173    exit(1) ;
1174/*
1175** Loop for the v2 protocol (also available for v3)
1176*/
1177loopv2:
1178    /*
1179    ** Set up v2 handlers
1180    */
1181    if ( bbftpd_setsignals() < 0 ) {
1182        exit(1) ;
1183    }
1184    /*
1185    ** Set the umask ; first unset it and then reset to the default value
1186    */
1187    umask(0) ;
1188    umask(myumask) ;
1189    for (;;) {
1190        /*
1191        ** Initialize the selectmask
1192        */
1193        nfds = sysconf(_SC_OPEN_MAX) ;
1194        FD_ZERO(&selectmask) ;
1195        FD_SET(incontrolsock,&selectmask) ;
1196        /*
1197        ** Depending on the state set a timer or not
1198        */
1199        switch (state) {
1200            case S_WAITING_STORE_START :
1201            case S_WAITING_FILENAME_STORE :
1202            case S_WAITING_FILENAME_RETR : {
1203                /*
1204                ** Timer of 10s between XX_V2 and FILENAME_XX
1205                */
1206                wait_timer.tv_sec  = 10 ;
1207                wait_timer.tv_usec = 0 ;
1208                break ;
1209            }
1210           
1211            case S_SENDING :
1212            case S_RECEIVING : {
1213                /*
1214                ** No timer while receiving or sending
1215                */
1216                wait_timer.tv_sec  = 0 ;
1217                wait_timer.tv_usec = 0 ;
1218                break ;
1219            }
1220            default : {
1221                /*
1222                ** Timer of 900s between commands
1223                */
1224                wait_timer.tv_sec  = 900 ;
1225                wait_timer.tv_usec = 0 ;
1226                break ;
1227            }
1228        }
1229        if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) {
1230            if ( errno != EINTR ) {
1231                syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
1232            }
1233        } else if ( retcode == 0 ) {
1234            syslog(BBFTPD_ERR,"Time OUT ") ;
1235            if ( state == S_WAITING_STORE_START ) {
1236                bbftpd_storeunlink(realfilename) ;
1237            }
1238            clean_child() ;
1239            exit_clean() ;
1240            exit(0) ;
1241        } else {
1242            /*
1243            ** At this stage we can only receive a command
1244            */
1245            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1246                if ( state == S_WAITING_STORE_START  || state == S_RECEIVING) {
1247                    bbftpd_storeunlink(realfilename) ;
1248                    sleep(5) ;
1249                }
1250                clean_child() ;
1251                exit_clean() ;
1252                exit(0) ;
1253            }
1254            if ( bbftpd_readcontrol(msg->code,msg->msglen) < 0 ) { 
1255                clean_child() ;
1256                exit_clean() ;
1257                exit(0) ;
1258            } else {
1259            }
1260        }
1261    }
1262/*
1263** Loop for the v1 protocol
1264*/
1265loopv1:
1266    for (;;) {
1267        /*
1268        ** Initialize the selectmask
1269        */
1270        nfds = sysconf(_SC_OPEN_MAX) ;
1271        FD_ZERO(&selectmask) ;
1272        FD_SET(incontrolsock,&selectmask) ;
1273        /*
1274        ** Depending on the state set a timer or not
1275        */
1276        switch (state) {
1277            case S_SENDING :
1278            case S_RECEIVING : {
1279                /*
1280                ** No timer while receiving or sending
1281                */
1282                wait_timer.tv_sec  = 0 ;
1283                wait_timer.tv_usec = 0 ;
1284                break ;
1285            }
1286            default : {
1287                /*
1288                ** Timer of 900s between commands
1289                */
1290                wait_timer.tv_sec  = 900 ;
1291                wait_timer.tv_usec = 0 ;
1292                break ;
1293            }
1294        }
1295        if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) {
1296            if ( errno != EINTR ) {
1297                syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
1298            }
1299        } else if ( retcode == 0 ) {
1300            syslog(BBFTPD_ERR,"Time OUT ") ;
1301            clean_child() ;
1302            exit_clean() ;
1303            exit(0) ;
1304        } else {
1305            /*
1306            ** At this stage we can only receive a command
1307            */
1308            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1309                clean_child() ;
1310                exit_clean() ;
1311                exit(0) ;
1312            }
1313            if ( readcontrol(msg->code,msg->msglen) < 0 ) { 
1314                clean_child() ;
1315                exit_clean() ;
1316                exit(0) ;
1317            } else {
1318            }
1319        }
1320    }
1321}
1322
1323void clean_child() 
1324{
1325    int    *pidfree ;
1326    int    i ;
1327   
1328    if ( protocolversion == 0 ) return ;
1329    if ( protocolversion == 1 ) {
1330        if ( killdone == 0 ) {
1331            killdone = 1 ;
1332            for ( i=0 ; i<MAXPORT ; i++) {
1333                if ( pid_child[i] != 0 ) {
1334                    syslog(BBFTPD_DEBUG,"Killing child %d",pid_child[i]) ;
1335                    kill(pid_child[i],SIGKILL) ;
1336                }
1337            }
1338        }
1339        return ;
1340    }
1341    if ( protocolversion >= 2 ) {
1342        if ( killdone == 0 ) {
1343            killdone = 1 ;
1344            pidfree = mychildren ;
1345            for ( i=0 ; i<nbpidchild ; i++) {
1346                if ( *pidfree != 0 ) {
1347                    syslog(BBFTPD_DEBUG,"Killing child %d",*pidfree) ;
1348                    kill(*pidfree,SIGKILL) ;
1349                }
1350                pidfree++ ;
1351            }
1352        }
1353        return ;
1354    }
1355}
1356
1357void exit_clean() 
1358{
1359   
1360    switch (state) {
1361        case S_CONN : {
1362            return ;
1363        }
1364        case S_LOGGED :
1365        case S_PROTWAIT :
1366        case S_WAITING_FILENAME_STORE :
1367        case S_WAITING_STORE_START :
1368        case S_SENDING:
1369        case S_RECEIVING : {
1370            syslog(BBFTPD_INFO,"User %s disconnected",currentusername) ;
1371            return ;
1372        }
1373        default :{
1374            return ;
1375        }
1376    }
1377}
1378
1379my64_t convertlong(my64_t v) {
1380    struct bb {
1381        int    fb ;
1382        int sb ;
1383    } ;
1384    struct bb *bbpt ;
1385    int     tmp ;
1386    my64_t    tmp64 ;
1387   
1388    tmp64 = v ;
1389    bbpt = (struct bb *) &tmp64 ;
1390    tmp = bbpt->fb ;
1391    bbpt->fb = ntohl(bbpt->sb) ;
1392    bbpt->sb = ntohl(tmp) ;   
1393    return tmp64 ;
1394}
1395
1396#ifndef HAVE_NTOHLL
1397my64_t ntohll(my64_t v) {
1398# ifdef HAVE_BYTESWAP_H
1399    return bswap_64(v);
1400# else
1401    long lo = v & 0xffffffff;
1402    long hi = v >> 32U;
1403    lo = ntohl(lo);
1404    hi = ntohl(hi);
1405    return ((my64_t) lo) << 32U | hi;
1406# endif
1407}
1408#define htonll ntohll
1409#endif
1410
Note: See TracBrowser for help on using the repository browser.