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

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

Added the private authentication API extensions needed to implement
NDG security. This API is connected to empty stub functions, no useful
functionality yet. Authorisation will require a further extension later.

The code compiles. Execution yet to be tested.

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