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

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

I've created a bbftpd log facility to replace syslog.
At present it allows you to log messages to a file in addition
to syslog. This should help testing on other machines.

Line 
1/*
2 * bbftpd/bbftpd_check.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 Routines : void checkfromwhere()
26            int checkprotocol()
27 
28 bbftpd_check.c v 2.0.0  2000/12/18 - Creation of the routine.
29                v 2.0.1  2001/04/23 - Correct indentation
30                v 2.1.0  2001/06/01 - Change file name
31                                    - Reorganise routines as in bbftp_
32                                     
33 *****************************************************************************/
34#include <bbftpd.h>
35
36#include <errno.h>
37
38#include <bbftpd_log.h>
39
40#if TIME_WITH_SYS_TIME
41# include <sys/time.h>
42# include <time.h>
43#else
44# if HAVE_SYS_TIME_H
45#  include <sys/time.h>
46# else
47#  include <time.h>
48# endif
49#endif
50#include <unistd.h>
51#include <utime.h>
52#if HAVE_STRING_H
53# include <string.h>
54#endif
55
56#include <netinet/in.h>
57#include <sys/socket.h>
58#include <common.h>
59#include <daemon.h>
60#include <daemon_proto.h>
61#include <structures.h>
62#include <version.h>
63
64extern struct   sockaddr_in his_addr;
65extern struct   sockaddr_in ctrl_addr;
66extern  int     incontrolsock ;
67extern  int     outcontrolsock ;
68extern  int     recvcontrolto ;
69extern  int     sendcontrolto ;
70extern  int     checkstdinto ;
71extern  int     protocolversion ;
72extern  int     protocolmin ;
73extern  int     protocolmax ;
74extern  int     newcontrolport ; 
75extern  int     fixeddataport;
76extern  int     pasvport_min;
77extern  int     pasvport_max;
78extern  char    currentusername[MAXLEN] ;
79
80/*******************************************************************************
81** checkfromwhere :                                                            *
82**                                                                             *
83**      This routine get a socket on a port, send a MSG_LOGGED_STDIN and       *
84**      wait for a connection on that port.                                    *
85**                                                                             *
86**      RETURN:                                                                *
87**          No return but the routine exit in case of error.                   *
88*******************************************************************************/
89
90
91void checkfromwhere() 
92{
93    int        sock,ns,addrlen,retcode,nfds ;
94    struct  sockaddr_in server ;
95    char    buffer[MINMESSLEN] ;
96     struct    message *msg ;
97    struct  timeval wait_timer;
98    fd_set    selectmask ;
99    struct linger li ;
100    int     on = 1 ;
101   
102   
103    sock = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ;
104    if ( sock < 0 ) {
105        bbftpd_log(BBFTPD_ERR, "Cannot create checkreceive socket : %s",strerror(errno));
106        reply(MSG_BAD,"Cannot create checkreceive socket") ;
107        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
108        exit(1) ;
109    }
110    if ( setsockopt(sock,SOL_SOCKET, SO_REUSEADDR,(char *)&on,sizeof(on)) < 0 ) {
111        bbftpd_log(BBFTPD_ERR,"Cannot set SO_REUSEADDR on checkreceive socket : %s\n",strerror(errno)) ;
112        reply(MSG_BAD,"Cannot set SO_REUSEADDR on checkreceive socket") ;
113        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
114        close(sock) ;
115        exit(1) ;
116    }
117    li.l_onoff = 1 ;
118    li.l_linger = 1 ;
119    if ( setsockopt(sock,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(li)) < 0 ) {
120        bbftpd_log(BBFTPD_ERR,"Cannot set SO_LINGER on checkreceive socket : %s\n",strerror(errno)) ;
121        reply(MSG_BAD,"Cannot set SO_LINGER on checkreceive socket") ;
122        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
123        close(sock) ;
124        exit(1) ;
125    }
126   
127    server.sin_family = AF_INET;
128    server.sin_addr.s_addr = INADDR_ANY;
129    if ( fixeddataport == 1 ) {
130        server.sin_port = htons(newcontrolport+1)  ;
131    } else {
132         server.sin_port = 0  ;
133    }
134    if (fixeddataport == 0 && pasvport_min) { /* Try to bind within a range */
135        int port;
136        for (port=pasvport_min; port<=pasvport_max; port++) {
137            server.sin_port = htons(port);
138            if (bind(sock,(struct sockaddr *) &server, sizeof(server) ) >= 0) break;
139        }
140        if (port>pasvport_max) {
141            bbftpd_log(BBFTPD_ERR, "Cannot bind on data socket : %s",strerror(errno));
142            reply(MSG_BAD,"Cannot bind checkreceive socket") ;
143            bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
144            close(sock) ;
145            exit(1) ;
146        }
147    } else if ( bind (sock,(struct sockaddr *) &server, sizeof(server) ) < 0 ) {
148        bbftpd_log(BBFTPD_ERR,"Error binding checkreceive socket : %s",strerror(errno)) ;
149        reply(MSG_BAD,"Cannot bind checkreceive socket") ;
150        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
151        close(sock) ;
152        exit(1) ;
153    }
154    addrlen = sizeof(server) ;
155    if (getsockname(sock,(struct sockaddr *)&server, &addrlen) < 0) {
156        bbftpd_log(BBFTPD_ERR,"Error getsockname checkreceive socket : %s",strerror(errno)) ;
157        reply(MSG_BAD,"Cannot getsockname checkreceive socket") ;
158        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
159        close(sock) ;
160        exit(1) ;
161    }
162    if ( listen(sock,1) < 0 ) {
163        bbftpd_log(BBFTPD_ERR,"Error listening checkreceive socket : %s",strerror(errno)) ;
164        reply(MSG_BAD,"Error listening checkreceive socket") ;
165        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
166        close(sock) ;
167        exit(1) ;
168    }
169    bbftpd_log(BBFTPD_INFO, "listen port : %d",ntohs(server.sin_port));
170    /*
171    ** Send the MSG_LOGGED_STDIN message
172    */
173    msg = (struct message *)buffer ;
174    msg->code = MSG_LOGGED_STDIN ;
175#ifndef WORDS_BIGENDIAN
176    msg->msglen = ntohl(4) ;
177#else
178    msg->msglen = 4 ;
179#endif
180    if ( writemessage(outcontrolsock,buffer,MINMESSLEN,sendcontrolto) < 0 ) {
181        bbftpd_log(BBFTPD_ERR,"Error writing checkreceive socket part 1") ;
182        reply(MSG_BAD,"Error writing checkreceive socket") ;
183        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
184        close(sock) ;
185        exit(1) ;
186    }
187    /*
188    ** Send the port number
189    */
190#ifndef WORDS_BIGENDIAN
191    msg->code = ntohl(ntohs(server.sin_port)) ;
192#else
193    msg->code = server.sin_port ;
194#endif
195     if ( writemessage(outcontrolsock,buffer,4,sendcontrolto) < 0 ) {
196        bbftpd_log(BBFTPD_ERR,"Error writing checkreceive socket part 2") ;
197        reply(MSG_BAD,"Error writing checkreceive socket") ;
198        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
199        exit(1) ;
200    }
201    /*
202    ** Now wait on the socket for a connection
203    */
204    nfds = sysconf(_SC_OPEN_MAX) ;
205    FD_ZERO(&selectmask) ;
206    FD_SET(sock,&selectmask) ;
207    /*
208    ** Set the timer for the connection
209    */
210    wait_timer.tv_sec  = checkstdinto ;
211    wait_timer.tv_usec = 0 ;
212    retcode = select(nfds,&selectmask,0,0,&wait_timer) ;
213    if ( retcode < 0 ) {
214        bbftpd_log(BBFTPD_ERR,"Error select checkreceive socket : %s ",strerror(errno)) ;
215        reply(MSG_BAD,"Error select checkreceive socket") ;
216        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
217        close(sock) ;
218        exit(1) ;
219    }
220    if ( retcode == 0 ) {
221        /*
222        ** Time out
223        */
224        bbftpd_log(BBFTPD_ERR,"Time out select checkreceive socket ") ;
225        reply(MSG_BAD,"Time Out select checkreceive socket") ;
226        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
227        close(sock) ;
228        exit(1) ;
229    }
230    if ( (ns = accept(sock,0,0) ) < 0 ) {
231        bbftpd_log(BBFTPD_ERR,"Error accept checkreceive socket ") ;
232        reply(MSG_BAD,"Error accep checkreceive socket") ;
233        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
234        close(sock) ;
235        exit(1) ;
236    }
237    close(sock) ;
238    addrlen = sizeof(his_addr);
239    if (getpeername(ns, (struct sockaddr *) &his_addr, &addrlen) < 0) {
240        bbftpd_log(BBFTPD_ERR, "getpeername : %s",strerror(errno));
241        reply(MSG_BAD,"getpeername error") ;
242        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
243        close(ns) ;
244        exit(1);
245    }
246    addrlen = sizeof(ctrl_addr);
247    if (getsockname(ns, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) {
248        bbftpd_log(BBFTPD_ERR, "getsockname : %s",strerror(errno));
249        reply(MSG_BAD,"getsockname error") ;
250        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
251        close(ns) ;
252        exit(1);
253    }
254    /*
255    ** Now read the message
256    */
257    if ( readmessage(ns,buffer,MINMESSLEN,recvcontrolto) < 0 ) {
258        bbftpd_log(BBFTPD_ERR,"Error reading checkreceive socket") ;
259        reply(MSG_BAD,"Error reading checkreceive socket") ;
260        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
261        close(ns) ;
262        exit(1) ;
263    }
264    if (msg->code != MSG_IPADDR ) {
265        bbftpd_log(BBFTPD_ERR,"Receive unkown message on checkreceive socket") ;
266        reply(MSG_BAD,"Receive unkown message on checkreceive socket") ;
267        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
268        close(ns) ;
269        exit(1);
270    }
271    /*
272    ** Everything seems OK so send a MSG_IPADDR_OK on the
273    ** control socket and close the connection
274    */
275    msg->code = MSG_IPADDR_OK ;
276    msg->msglen = 0 ;
277     if ( writemessage(ns,buffer,MINMESSLEN,sendcontrolto) < 0 ) {
278        bbftpd_log(BBFTPD_ERR,"Error writing checkreceive socket OK message") ;
279        reply(MSG_BAD,"Error writing checkreceive socket OK message") ;
280        bbftpd_log(BBFTPD_INFO,"User %s disconnected",currentusername) ;
281        close(ns) ;
282        exit(1) ;
283    }
284    /*
285    ** set the port of ctrl_addr structure to the control port
286    */
287    ctrl_addr.sin_port = htons(newcontrolport) ;
288    /*
289    ** Wait a while before closing
290    */
291    close(ns) ;
292}
293
294
295/*******************************************************************************
296** checkprotocol :                                                             *
297**                                                                             *
298**      This routine send it protocol version and wait for the client prorocol *
299**      version.                                                               *
300**                                                                             *
301**      RETURN:                                                                *
302**           0 OK                                                              *
303**          -1 calling program exit                                            *
304*******************************************************************************/
305
306int checkprotocol() 
307{
308
309    char    buffer[MINMESSLEN] ;
310    struct  message *msg ;
311    int     msglen ;
312
313    msg = ( struct    message * ) buffer ;
314    msg->code = MSG_PROT_ANS ;
315#ifndef WORDS_BIGENDIAN
316    msg->msglen = ntohl(MINMESSLEN) ;
317#else
318    msg->msglen = MINMESSLEN ;
319#endif
320    if ( writemessage(outcontrolsock,buffer,MINMESSLEN,sendcontrolto) < 0 ) {
321        bbftpd_log(BBFTPD_ERR,"Error writing MSG_PROT_ANS part 1") ;
322        return -1 ;
323    }
324    /*
325    ** Send the min and max protocol version
326    */
327#ifndef WORDS_BIGENDIAN
328    msg->code = ntohl(protocolmin) ;
329    msg->msglen = ntohl(protocolmax) ;
330#else
331    msg->code = protocolmin ;
332    msg->msglen = protocolmax ;
333#endif
334     if ( writemessage(outcontrolsock,buffer,MINMESSLEN,sendcontrolto) < 0 ) {
335        bbftpd_log(BBFTPD_ERR,"Error writing MSG_PROT_ANS part 2") ;
336        return -1 ;
337    }
338    /*
339    ** And wait for the answer
340    */
341    if ( readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto) < 0 ) {
342        bbftpd_log(BBFTPD_ERR,"Error waiting MSG_PROT_ANS") ;
343        return -1 ;
344    }
345    if ( msg->code == MSG_PROT_ANS ) {
346#ifndef WORDS_BIGENDIAN
347        msglen = ntohl(msg->msglen) ;
348#else
349        msglen = msg->msglen ;
350#endif
351        if ( msglen == 4 ) {
352            if ( readmessage(incontrolsock,buffer,4,recvcontrolto) < 0 ) {
353                bbftpd_log(BBFTPD_ERR,"Error waiting MSG_PROT_ANS (protocol version)") ;
354                return -1 ;
355            }
356#ifndef WORDS_BIGENDIAN
357            msglen = ntohl(msg->code) ;
358#else
359            msglen = msg->code ;
360#endif
361            protocolversion = msglen ;
362            return 0 ;
363        } else {
364            bbftpd_log(BBFTPD_ERR,"Unexpected length while MSG_PROT_ANS %d",msglen) ;
365            return -1 ;
366        }
367    } else if ( msg->code == MSG_BAD_NO_RETRY ) {
368        bbftpd_log(BBFTPD_ERR,"Incompatible server and client") ;
369        return -1 ;
370    } else {
371        bbftpd_log(BBFTPD_ERR,"Unexpected message while MSG_PROT_ANS %d",msg->code) ;
372        return -1 ;
373    }
374
375   
376}
Note: See TracBrowser for help on using the repository browser.