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

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

Another missing use of socklen_t.

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