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

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

Minor change to server debug output.

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#ifdef CERTIFICATE_AUTH
964                if (accept_pass_only) {
965                    sprintf(logmessage, "%s                   The server only accepts USER/PASS\n",logmessage);
966                }
967                if (accept_certs_only) {
968                    sprintf(logmessage, "%s                   The server only accepts certificates\n",logmessage);
969                }
970#endif
971#ifndef PRIVATE_AUTH
972                if (force_encoding) {
973                    sprintf(logmessage, "%s                   The server requires encrypted login\n",logmessage);
974                } else {
975                    sprintf(logmessage, "%s                   The server allows non-encrypted login\n",logmessage);
976                }
977#endif
978
979               
980                    reply(MSG_OK,logmessage);
981                    exit(0);
982            }
983#ifdef CERTIFICATE_AUTH
984            if ( msg->code == MSG_CERT_LOG ) {
985                int retval;
986                if (accept_pass_only) {
987                    sprintf(logmessage, "The server only accepts USER/PASS");
988                    syslog(BBFTPD_ERR,"%s",logmessage) ;
989                    reply(MSG_BAD_NO_RETRY,logmessage);
990                    exit(1);
991                }
992                retval=bbftpd_cert_receive_connection(msg->msglen);
993                if ( retval < 0 ) {
994                    /*
995                    ** The login failed, do not wait for a new one
996                    */
997                                        exit(1) ;
998                }
999                /*
1000                ** If retval >0, means an MSG_WARN has been sent already
1001                */
1002                    state = S_PROTWAIT ;
1003                if (retval == 0) {
1004                    sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1005                    reply(MSG_OK,logmessage) ;
1006                }
1007            } else if ( msg->code == MSG_LOG ) {
1008                if (accept_certs_only) {
1009                    sprintf(logmessage, "The server only accepts certificates");
1010                    syslog(BBFTPD_ERR,"%s",logmessage) ;
1011                    reply(MSG_BAD_NO_RETRY,logmessage);
1012                } else {
1013                    /*
1014                    ** It seems that it is the message we were waiting
1015                    ** so lets decrypt
1016                    */
1017                    if ( loginsequence() < 0 ) {
1018                        /*
1019                        ** The login failed, do not wait for a new one
1020                        */
1021                        exit(1) ;
1022                    }
1023                    state = S_PROTWAIT ;
1024                    sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1025                    reply(MSG_OK,logmessage) ;
1026                }
1027            } else if (msg->code == MSG_CRYPT) { 
1028                if (accept_certs_only) {
1029                    sprintf(logmessage, "The server only accepts certificates");
1030                    reply(MSG_BAD_NO_RETRY,logmessage);
1031                } else if (force_encoding) {
1032                    /*
1033                    **  The client can't encode and ask if it can send uncrypted
1034                    **  login information
1035                    */
1036                    sprintf(logmessage, "The server requires encrypted login");
1037                    reply(MSG_BAD_NO_RETRY,logmessage);
1038                } else {
1039                    sprintf(logmessage, "Uncrypted login dialog accepted");
1040                    reply(MSG_OK,logmessage);
1041                    goto login;
1042                }
1043            } else {
1044                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1045                reply(MSG_BAD,"Unkown message in connected state") ;
1046                exit(1) ;
1047            }
1048#else
1049#ifndef PRIVATE_AUTH
1050            if ( msg->code == MSG_LOG ) {
1051                /*
1052                ** It seems that it is the message we were waiting
1053                ** so lets decrypt
1054                */
1055                if ( loginsequence() < 0 ) {
1056                    /*
1057                    ** The login failed, do not wait for a new one
1058                    */
1059                    exit(1) ;
1060                }
1061                state = S_PROTWAIT ;
1062                sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1063                reply(MSG_OK,logmessage) ;
1064            } else if (msg->code == MSG_CRYPT) { 
1065                /*
1066                **  The client can't encode and ask if it can send uncrypted
1067                **  login information
1068                */
1069                if (force_encoding) {
1070                    sprintf(logmessage, "The server requires encrypted login");
1071                    reply(MSG_BAD_NO_RETRY,logmessage);
1072                    exit(1);
1073                }
1074                sprintf(logmessage, "Uncrypted login dialog accepted");
1075                reply(MSG_OK,logmessage);
1076                goto login;
1077            } else {
1078                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1079                reply(MSG_BAD,"Unkown message in connected state") ;
1080                exit(1) ;
1081            }
1082#else
1083            if ( msg->code == MSG_PRIV_LOG ) {
1084                if ( bbftpd_private_receive_connection(msg->msglen) < 0 ) {
1085                    /*
1086                    ** The login failed, do not wait for a new one
1087                    */
1088                    exit(1) ;
1089                }
1090                state = S_PROTWAIT ;
1091                sprintf(logmessage,"bbftpd version %s : OK",VERSION) ;
1092                reply(MSG_OK,logmessage) ;
1093            } else {
1094                syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ;
1095                reply(MSG_BAD,"Unkown message in connected state") ;
1096                exit(1) ;
1097            }
1098#endif
1099#endif
1100        }
1101    }
1102
1103    /*
1104    ** At this stage we are in the S_PROTWAIT state
1105    */
1106    nfds = sysconf(_SC_OPEN_MAX) ;
1107    FD_ZERO(&selectmask) ;
1108    FD_SET(incontrolsock,&selectmask) ;
1109    wait_timer.tv_sec  = 10 ;
1110    wait_timer.tv_usec = 0 ;
1111    if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) {
1112        syslog(BBFTPD_ERR,"Select error in S_PROTWAIT state : %s",strerror(errno)) ;
1113        exit(1) ;
1114    } else if ( retcode == 0 ) {
1115        syslog(BBFTPD_ERR,"Time OUT in S_PROTWAIT state") ;
1116        exit(1) ;
1117    } else {
1118        if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1119            syslog(BBFTPD_ERR,"Error reading in S_PROTWAIT state") ;
1120            exit(1) ;
1121        }
1122        msg = (struct message *) buffer ;
1123        if ( msg->code == MSG_PROT ) {
1124            /*
1125            ** The client is using bbftp v2 protocol or higher
1126            */
1127            if ( checkprotocol() < 0 ) {
1128                exit_clean() ;
1129                exit(1) ;
1130            }
1131            syslog(BBFTPD_INFO,"Using bbftp protocol version %d",protocolversion) ;
1132            state = S_LOGGED ;
1133            /*
1134            ** Initialize the variables
1135            */
1136            mychildren = NULL ;
1137            nbpidchild = 0 ;
1138            curfilename = NULL ;
1139            curfilenamelen = 0 ;
1140        } else {
1141            /*
1142            ** This is a bbftp v1 client
1143            */
1144            protocolversion = 1 ;
1145            syslog(BBFTPD_INFO,"Using bbftp protocol version 1") ;
1146            state = S_LOGGED ;
1147            /*
1148            ** So set up the v1 handlers
1149            */
1150            if ( set_signals_v1() < 0 ) {
1151                exit(1) ;
1152            }
1153            /*
1154            ** Initialize the pid array
1155            */
1156            for ( i=0 ; i< MAXPORT ; i++) {
1157                pid_child[i] = 0 ;
1158            }
1159            /*
1160            ** As we have already read the message
1161            */
1162            if ( readcontrol(msg->code,msg->msglen) < 0 ) { 
1163                clean_child() ;
1164                exit_clean() ;
1165                exit(0) ;
1166            }
1167        }
1168    }
1169    if ( protocolversion == 1 ) goto loopv1 ;
1170    if ( protocolversion == 2 || protocolversion == 3) goto loopv2 ;
1171    syslog(BBFTPD_ERR,"Unknown protocol version %d",protocolversion) ;
1172    exit(1) ;
1173/*
1174** Loop for the v2 protocol (also available for v3)
1175*/
1176loopv2:
1177    /*
1178    ** Set up v2 handlers
1179    */
1180    if ( bbftpd_setsignals() < 0 ) {
1181        exit(1) ;
1182    }
1183    /*
1184    ** Set the umask ; first unset it and then reset to the default value
1185    */
1186    umask(0) ;
1187    umask(myumask) ;
1188    for (;;) {
1189        /*
1190        ** Initialize the selectmask
1191        */
1192        nfds = sysconf(_SC_OPEN_MAX) ;
1193        FD_ZERO(&selectmask) ;
1194        FD_SET(incontrolsock,&selectmask) ;
1195        /*
1196        ** Depending on the state set a timer or not
1197        */
1198        switch (state) {
1199            case S_WAITING_STORE_START :
1200            case S_WAITING_FILENAME_STORE :
1201            case S_WAITING_FILENAME_RETR : {
1202                /*
1203                ** Timer of 10s between XX_V2 and FILENAME_XX
1204                */
1205                wait_timer.tv_sec  = 10 ;
1206                wait_timer.tv_usec = 0 ;
1207                break ;
1208            }
1209           
1210            case S_SENDING :
1211            case S_RECEIVING : {
1212                /*
1213                ** No timer while receiving or sending
1214                */
1215                wait_timer.tv_sec  = 0 ;
1216                wait_timer.tv_usec = 0 ;
1217                break ;
1218            }
1219            default : {
1220                /*
1221                ** Timer of 900s between commands
1222                */
1223                wait_timer.tv_sec  = 900 ;
1224                wait_timer.tv_usec = 0 ;
1225                break ;
1226            }
1227        }
1228        if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) {
1229            if ( errno != EINTR ) {
1230                syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
1231            }
1232        } else if ( retcode == 0 ) {
1233            syslog(BBFTPD_ERR,"Time OUT ") ;
1234            if ( state == S_WAITING_STORE_START ) {
1235                bbftpd_storeunlink(realfilename) ;
1236            }
1237            clean_child() ;
1238            exit_clean() ;
1239            exit(0) ;
1240        } else {
1241            /*
1242            ** At this stage we can only receive a command
1243            */
1244            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1245                if ( state == S_WAITING_STORE_START  || state == S_RECEIVING) {
1246                    bbftpd_storeunlink(realfilename) ;
1247                    sleep(5) ;
1248                }
1249                clean_child() ;
1250                exit_clean() ;
1251                exit(0) ;
1252            }
1253            if ( bbftpd_readcontrol(msg->code,msg->msglen) < 0 ) { 
1254                clean_child() ;
1255                exit_clean() ;
1256                exit(0) ;
1257            } else {
1258            }
1259        }
1260    }
1261/*
1262** Loop for the v1 protocol
1263*/
1264loopv1:
1265    for (;;) {
1266        /*
1267        ** Initialize the selectmask
1268        */
1269        nfds = sysconf(_SC_OPEN_MAX) ;
1270        FD_ZERO(&selectmask) ;
1271        FD_SET(incontrolsock,&selectmask) ;
1272        /*
1273        ** Depending on the state set a timer or not
1274        */
1275        switch (state) {
1276            case S_SENDING :
1277            case S_RECEIVING : {
1278                /*
1279                ** No timer while receiving or sending
1280                */
1281                wait_timer.tv_sec  = 0 ;
1282                wait_timer.tv_usec = 0 ;
1283                break ;
1284            }
1285            default : {
1286                /*
1287                ** Timer of 900s between commands
1288                */
1289                wait_timer.tv_sec  = 900 ;
1290                wait_timer.tv_usec = 0 ;
1291                break ;
1292            }
1293        }
1294        if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) {
1295            if ( errno != EINTR ) {
1296                syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ;
1297            }
1298        } else if ( retcode == 0 ) {
1299            syslog(BBFTPD_ERR,"Time OUT ") ;
1300            clean_child() ;
1301            exit_clean() ;
1302            exit(0) ;
1303        } else {
1304            /*
1305            ** At this stage we can only receive a command
1306            */
1307            if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) {
1308                clean_child() ;
1309                exit_clean() ;
1310                exit(0) ;
1311            }
1312            if ( readcontrol(msg->code,msg->msglen) < 0 ) { 
1313                clean_child() ;
1314                exit_clean() ;
1315                exit(0) ;
1316            } else {
1317            }
1318        }
1319    }
1320}
1321
1322void clean_child() 
1323{
1324    int    *pidfree ;
1325    int    i ;
1326   
1327    if ( protocolversion == 0 ) return ;
1328    if ( protocolversion == 1 ) {
1329        if ( killdone == 0 ) {
1330            killdone = 1 ;
1331            for ( i=0 ; i<MAXPORT ; i++) {
1332                if ( pid_child[i] != 0 ) {
1333                    syslog(BBFTPD_DEBUG,"Killing child %d",pid_child[i]) ;
1334                    kill(pid_child[i],SIGKILL) ;
1335                }
1336            }
1337        }
1338        return ;
1339    }
1340    if ( protocolversion >= 2 ) {
1341        if ( killdone == 0 ) {
1342            killdone = 1 ;
1343            pidfree = mychildren ;
1344            for ( i=0 ; i<nbpidchild ; i++) {
1345                if ( *pidfree != 0 ) {
1346                    syslog(BBFTPD_DEBUG,"Killing child %d",*pidfree) ;
1347                    kill(*pidfree,SIGKILL) ;
1348                }
1349                pidfree++ ;
1350            }
1351        }
1352        return ;
1353    }
1354}
1355
1356void exit_clean() 
1357{
1358   
1359    switch (state) {
1360        case S_CONN : {
1361            return ;
1362        }
1363        case S_LOGGED :
1364        case S_PROTWAIT :
1365        case S_WAITING_FILENAME_STORE :
1366        case S_WAITING_STORE_START :
1367        case S_SENDING:
1368        case S_RECEIVING : {
1369            syslog(BBFTPD_INFO,"User %s disconnected",currentusername) ;
1370            return ;
1371        }
1372        default :{
1373            return ;
1374        }
1375    }
1376}
1377
1378my64_t convertlong(my64_t v) {
1379    struct bb {
1380        int    fb ;
1381        int sb ;
1382    } ;
1383    struct bb *bbpt ;
1384    int     tmp ;
1385    my64_t    tmp64 ;
1386   
1387    tmp64 = v ;
1388    bbpt = (struct bb *) &tmp64 ;
1389    tmp = bbpt->fb ;
1390    bbpt->fb = ntohl(bbpt->sb) ;
1391    bbpt->sb = ntohl(tmp) ;   
1392    return tmp64 ;
1393}
1394
1395#ifndef HAVE_NTOHLL
1396my64_t ntohll(my64_t v) {
1397# ifdef HAVE_BYTESWAP_H
1398    return bswap_64(v);
1399# else
1400    long lo = v & 0xffffffff;
1401    long hi = v >> 32U;
1402    lo = ntohl(lo);
1403    hi = ntohl(hi);
1404    return ((my64_t) lo) << 32U | hi;
1405# endif
1406}
1407#define htonll ntohll
1408#endif
1409
Note: See TracBrowser for help on using the repository browser.