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

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

More missing #includes exposed when compiling on easterly.

Line 
1/*
2 * bbftpd/bbftpd_socket.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 bbftpd_socket.c    v 2.0.0 2000/12/19  - Routines creation
26                    v 2.0.1 2001/04/23  - Correct indentation
27                                        - Port to IRIX
28               
29*****************************************************************************/
30#include <bbftpd.h>
31
32#include <stdio.h>
33
34#include <errno.h>
35#include <fcntl.h>
36
37#include <netinet/tcp.h>
38#include <bbftpd_private_log.h>
39#include <sys/socket.h>
40#include <sys/types.h>
41#include <unistd.h>
42#include <utime.h>
43#if HAVE_STRING_H
44# include <string.h>
45#endif
46
47#include <netinet/in.h>
48#include <common.h>
49#include <daemon.h>
50#include <daemon_proto.h>
51#include <structures.h>
52
53extern int  sendwinsize ;       
54extern int  recvwinsize ;       
55extern struct sockaddr_in his_addr;        /* Remote adresse */
56extern struct sockaddr_in ctrl_addr;    /* Local adresse */
57extern int  fixeddataport ;
58extern int     *myports ;
59extern int     *mysockets ;
60extern int  transferoption ;
61extern int  pasvport_min ;
62extern int  pasvport_max ;
63
64/*******************************************************************************
65** bbftpd_createreceivesocket :                                                       *
66**                                                                             *
67**      Routine to create a receive socket                                     *
68**      This routine may send MSG_INFO                                         *
69**                                                                             *
70**      INPUT variable :                                                       *
71**           portnumber   :  portnumber to connect    NOT MODIFIED             *
72**                                                                             *
73**      OUPUT variable :                                                       *
74**          logmessage :  to write the error message in case of error          *
75**                                                                             *
76**      RETURN:                                                                *
77**          -1   Creation failed unrecoverable error                           *
78**           0   OK                                                            *
79**           >0  Creation failed recoverable error                             *
80**                                                                             *
81*******************************************************************************/
82int bbftpd_createreceivesocket(int portnumber,char *logmessage) 
83{
84    int    sock ;
85    struct sockaddr_in data_source ;
86    int    on = 1 ;
87    int tcpwinsize ;
88#if defined(HAVE_SOCKLEN_T)
89    socklen_t addrlen;
90#else
91#if defined(SUNOS) || defined(_HPUX_SOURCE) || defined(IRIX)
92    int        addrlen ;
93#else
94#if defined(AIX)
95/* Porting AIX 5.2 X64 */
96    socklen_t        addrlen ;
97#else
98    size_t        addrlen ;
99#endif
100#endif
101#endif
102    int    retcode ;
103
104        /*bbftpd_log(BBFTPD_INFO,"New socket to: %s:%d\n",inet_ntoa(his_addr.sin_addr), portnumber);*/
105    sock = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ;
106    if ( sock < 0 ) {
107        bbftpd_log(BBFTPD_ERR, "Cannot create receive socket on port %d : %s",portnumber,strerror(errno));
108        sprintf(logmessage,"Cannot create receive socket on port %d : %s",portnumber,strerror(errno)) ;
109        return (-1) ;
110    }
111    if ( setsockopt(sock,SOL_SOCKET, SO_REUSEADDR,(char *)&on,sizeof(on)) < 0 ) {
112        close(sock) ;
113        bbftpd_log(BBFTPD_ERR,"Cannot set SO_REUSEADDR on receive socket port %d : %s",portnumber,strerror(errno)) ;
114        sprintf(logmessage,"Cannot set SO_REUSEADDR on receive socket port %d : %s",portnumber,strerror(errno)) ;
115        return (-1) ;
116    }
117    tcpwinsize = 1024 * recvwinsize ;
118    if ( setsockopt(sock,SOL_SOCKET, SO_RCVBUF,(char *)&tcpwinsize,sizeof(tcpwinsize)) < 0 ) {
119        /*
120        ** In this case we are going to log a message
121        */
122        bbftpd_log(BBFTPD_ERR,"Cannot set SO_RCVBUF on receive socket port %d : %s",portnumber,strerror(errno)) ;
123    }
124    addrlen = sizeof(tcpwinsize) ;
125    if ( getsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char *)&tcpwinsize,&addrlen) < 0 ) {
126         bbftpd_log(BBFTPD_ERR,"Cannot get SO_RCVBUF on receive socket port %d : %s",portnumber,strerror(errno)) ;
127        close(sock) ;
128        sprintf(logmessage,"Cannot get SO_RCVBUF on receive socket port %d : %s",portnumber,strerror(errno)) ;
129        return (-1) ;
130    }
131    if ( tcpwinsize < 1024 * recvwinsize ) {
132        sprintf(logmessage,"Receive buffer on port %d cannot be set to %d Bytes, Value is %d Bytes",portnumber,1024*recvwinsize,tcpwinsize) ;
133        reply(MSG_INFO,logmessage) ;
134    }
135    tcpwinsize = 1024 * sendwinsize ;
136    if ( setsockopt(sock,SOL_SOCKET, SO_SNDBUF,(char *)&tcpwinsize,sizeof(tcpwinsize)) < 0 ) {
137        /*
138        ** In this case we just log an error
139        */
140        bbftpd_log(BBFTPD_ERR,"Cannot set SO_SNDBUF  on receive socket port %d : %s",portnumber,strerror(errno)) ;
141    }
142    addrlen = sizeof(tcpwinsize) ;
143    if ( getsockopt(sock,SOL_SOCKET, SO_SNDBUF,(char *)&tcpwinsize,&addrlen) < 0 ) {
144        bbftpd_log(BBFTPD_ERR,"Cannot get SO_SNDBUF on receive socket port %d : %s",portnumber,strerror(errno)) ;
145        close(sock) ;
146        sprintf(logmessage,"Cannot get SO_SNDBUF on receive socket port %d : %s",portnumber,strerror(errno)) ;
147        return (-1) ;
148    }
149    if ( tcpwinsize < 1024 * sendwinsize ) {
150        sprintf(logmessage,"Send buffer on port %d cannot be set to %d Bytes, Value is %d Bytes",portnumber,1024*sendwinsize,tcpwinsize) ;
151        reply(MSG_INFO,logmessage) ;
152    }
153    if ( setsockopt(sock,IPPROTO_TCP, TCP_NODELAY,(char *)&on,sizeof(on)) < 0 ) {
154        close(sock) ;
155        bbftpd_log(BBFTPD_ERR,"Cannot set TCP_NODELAY on receive socket port %d : %s",portnumber,strerror(errno)) ;
156        sprintf(logmessage,"Cannot set TCP_NODELAY on receive socket port %d : %s",portnumber,strerror(errno)) ;
157        return (-1) ;
158    }
159    data_source.sin_family = AF_INET;
160#ifdef SUNOS
161    data_source.sin_addr = ctrl_addr.sin_addr;
162#else
163    data_source.sin_addr.s_addr = INADDR_ANY;
164#endif
165    if ( fixeddataport == 1 ) {
166        data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
167    } else {
168        data_source.sin_port = 0;
169    }
170    if ( bind(sock, (struct sockaddr *) &data_source,sizeof(data_source)) < 0) {
171        close(sock) ;
172        bbftpd_log(BBFTPD_ERR,"Cannot bind on receive socket port %d : %s",portnumber,strerror(errno)) ;
173        sprintf(logmessage,"Cannot bind on receive socket port %d : %s",portnumber,strerror(errno)) ;
174        return (-1) ;
175    }
176    data_source.sin_addr = his_addr.sin_addr;
177    data_source.sin_port = htons(portnumber);
178    addrlen = sizeof(data_source) ;
179    retcode = connect(sock,(struct sockaddr *) &data_source,addrlen) ;
180    if ( retcode < 0 ) {
181        if ( errno == EINTR ) {
182            /*
183            ** In this case we are going to tell the calling program
184            ** to retry so we close the socket and set the return code
185            ** to zero
186            */
187            close(sock) ;
188            bbftpd_log(BBFTPD_ERR,"Cannot connect receive socket port %d : %s, telling calling to retry ",portnumber,strerror(errno)) ;
189            return 0 ;
190        } else {
191            sprintf(logmessage,"Cannot connect receive socket port %s:%d : %s",inet_ntoa(his_addr.sin_addr),portnumber,strerror(errno)) ;
192            bbftpd_log(BBFTPD_ERR,"Cannot connect receive socket port %s:%d : %s",inet_ntoa(his_addr.sin_addr),portnumber,strerror(errno)) ;
193            close(sock) ;
194            return (-1) ;
195        }
196    }
197        bbftpd_log(BBFTPD_DEBUG,"Connected on port: %s:%d\n",inet_ntoa(his_addr.sin_addr),portnumber);
198    return sock ;
199}
200
201/*******************************************************************************
202** bbftpd_getdatasockk :                                                       *
203**                                                                             *
204**      Routine to create all the needed sockets to send data                  *
205**                                                                             *
206**      INPUT variable :                                                       *
207**           nbsock   :  number of sockets to create    NOT MODIFIED           *
208**                                                                             *
209**      RETURN:                                                                *
210**          -1   Creation failed unrecoverable error                           *
211**           0   OK                                                            *
212**                                                                             *
213*******************************************************************************/
214int bbftpd_getdatasock(int nbsock) 
215{
216    int     i ;
217    int     tcpwinsize ;
218    int     on = 1 ;
219#if defined(HAVE_SOCKLEN_T)
220    socklen_t addrlen;
221#else
222#if defined(SUNOS) || defined(_HPUX_SOURCE) || defined(IRIX)
223    int     addrlen ;
224#else
225#if defined(AIX)
226/* Porting AIX 5.2 X64 */
227    socklen_t        addrlen ;
228#else
229    size_t  addrlen ;
230#endif
231#endif
232#endif
233    struct  linger li ;
234    struct  sockaddr_in sck ;
235    int     *mysockfree ;
236    int     *myportfree;
237    int     port ;
238   
239    /* Declaring the variables need to change the value of the TOS */
240    int tos_value, tos_len;
241    int qbss_value = 0x20;
242    tos_len = sizeof(tos_value);
243
244
245    mysockfree = mysockets ;
246    myportfree = myports ;
247    sck = ctrl_addr ;
248    for (i=0 ; i<nbsock ; i++) {
249        sck.sin_port = 0;
250        *mysockfree = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ;
251        if ( *mysockfree < 0 ) {
252            bbftpd_log(BBFTPD_ERR, "Cannot create data socket : %s",strerror(errno));
253                        /*            sprintf(logmessage,"Cannot create data socket : %s",strerror(errno)) ;*/
254            return -1 ;
255        }
256        if ( setsockopt(*mysockfree,SOL_SOCKET, SO_REUSEADDR,(char *)&on,sizeof(on)) < 0 ) {
257            bbftpd_log(BBFTPD_ERR, "Cannot set SO_REUSEADDR on data socket : %s",strerror(errno));
258                        /*            sprintf(logmessage,"Cannot set SO_REUSEADDR on data socket : %s",strerror(errno)) ;*/
259            return -1 ;
260        }
261        if ( setsockopt(*mysockfree,IPPROTO_TCP, TCP_NODELAY,(char *)&on,sizeof(on)) < 0 ) {
262            bbftpd_log(BBFTPD_ERR, "Cannot set TCP_NODELAY on data socket : %s",strerror(errno));
263                        /*            sprintf(logmessage,"Cannot set TCP_NODELAY on data socket : %s",strerror(errno)) ;*/
264            return -1 ;
265        }
266
267                /* Printing out the default value for the TOS
268                        if( getsockopt(*mysockfree,IPPROTO_IP,IP_TOS,
269                       &tos_value,
270                       &tos_len) == 0){
271                           }
272                */
273                if ( (transferoption & TROPT_QBSS ) == TROPT_QBSS ) {
274                        /* Setting the value for IP_TOS to be 0x20 */
275                        if ( setsockopt(*mysockfree,IPPROTO_IP, IP_TOS, (char *)&qbss_value, sizeof(qbss_value)) < 0 ) {
276                bbftpd_log(BBFTPD_WARNING, "Cannot set IP_TOS on data socket : %s",strerror(errno));
277                        }
278                }
279
280        /*
281        ** Send and receive are inversed because they are supposed
282        ** to be the daemon char
283        */
284        tcpwinsize = 1024 * recvwinsize ;
285        if ( setsockopt(*mysockfree,SOL_SOCKET, SO_SNDBUF,(char *)&tcpwinsize,sizeof(tcpwinsize)) < 0 ) {
286            addrlen = sizeof(tcpwinsize) ;
287            if ( getsockopt(*mysockfree,SOL_SOCKET,SO_SNDBUF,(char *)&tcpwinsize,&addrlen) < 0 ) {
288                bbftpd_log(BBFTPD_WARNING, "Unable to get send buffer size : %s\n",tcpwinsize,strerror(errno));
289            } else {
290                bbftpd_log(BBFTPD_WARNING, "Send buffer cannot be set to %d Bytes, Value is %d Bytes\n",1024*recvwinsize,tcpwinsize);
291            }
292        }
293        tcpwinsize = 1024 * sendwinsize ;
294        if ( setsockopt(*mysockfree,SOL_SOCKET, SO_RCVBUF,(char *)&tcpwinsize,sizeof(tcpwinsize)) < 0 ) {
295            addrlen = sizeof(tcpwinsize) ;
296            if ( getsockopt(*mysockfree,SOL_SOCKET,SO_RCVBUF,(char *)&tcpwinsize,&addrlen) < 0 ) {
297                bbftpd_log(BBFTPD_WARNING, "Unable to get receive buffer size : %s\n",tcpwinsize,strerror(errno));
298            } else {
299                bbftpd_log(BBFTPD_WARNING, "Receive buffer cannot be set to %d Bytes, Value is %d Bytes\n",1024*recvwinsize,tcpwinsize);
300            }
301        }   
302        li.l_onoff = 1 ;
303        li.l_linger = 1 ;
304        if ( setsockopt(*mysockfree,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(li)) < 0 ) {
305            bbftpd_log(BBFTPD_ERR, "Cannot set SO_LINGER on data socket : %s",strerror(errno));
306                        /*            sprintf(logmessage,"Cannot set SO_LINGER on data socket : %s",strerror(errno)) ;*/
307            return -1 ;
308        }
309        if (pasvport_min) { /* Try to bind within a range */
310                for (port=pasvport_min; port<=pasvport_max; port++) {
311                sck.sin_port = htons(port);
312                    if (bind(*mysockfree, (struct sockaddr *) &sck, sizeof(sck)) >= 0) break;
313                }
314                if (port>pasvport_max) {
315                bbftpd_log(BBFTPD_ERR, "Cannot bind on data socket : %s",strerror(errno));
316                return -1 ;
317                }
318        } else {
319            if (bind(*mysockfree, (struct sockaddr *) &sck, sizeof(sck)) < 0) {
320                bbftpd_log(BBFTPD_ERR, "Cannot bind on data socket : %s",strerror(errno));
321                return -1 ;
322                }
323                }
324        addrlen = sizeof(sck) ;
325        if (getsockname(*mysockfree,(struct sockaddr *)&sck, &addrlen) < 0) {
326            bbftpd_log(BBFTPD_ERR, "Cannot getsockname on data socket : %s",strerror(errno));
327            /*sprintf(logmessage,"Cannot getsockname on data socket : %s",strerror(errno)) ;*/
328            return -1 ;
329           }
330        if (listen(*mysockfree, 1) < 0) {
331            bbftpd_log(BBFTPD_ERR, "Cannot listen on data socket : %s",strerror(errno));
332            /*sprintf(logmessage,"Cannot listen on data socket : %s",strerror(errno)) ;*/
333            return -1 ;
334        }
335        *myportfree++ =  sck.sin_port ;
336        bbftpd_log(BBFTPD_DEBUG,"Listen on port %d\n", ntohs(sck.sin_port)) ; 
337        mysockfree++ ;
338    }
339    return 0 ;
340}
Note: See TracBrowser for help on using the repository browser.