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

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

More missing #includes exposed when compiling on easterly.

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