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

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

Eliminated all "implicit declaration" warnings from "python setup.py
build"

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