/***************************************************************************/ /***************************************************************************/ /* */ /* (c) 1995-1999. The Regents of the University of California. All */ /* rights reserved. */ /* */ /* This work was produced at the University of California, Lawrence */ /* Livermore National Laboratory (UC LLNL) under contract no. */ /* W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy */ /* (DOE) and The Regents of the University of California (University) */ /* for the operation of UC LLNL. Copyright is reserved to the */ /* University for purposes of controlled dissemination, */ /* commercialization through formal licensing, or other disposition */ /* under terms of Contract 48; DOE policies, regulations and orders; */ /* and U.S. statutes. The rights of the Federal Government are */ /* reserved under Contract 48 subject to the restrictions agreed upon */ /* by the DOE and University. */ /* */ /* */ /* DISCLAIMER */ /* */ /* This software was prepared as an account of work sponsored by an */ /* agency of the United States Government. Neither the United States */ /* Government nor the University of California nor any of their */ /* employees, makes any warranty, express or implied, or assumes any */ /* liability or responsibility for the accuracy, completeness, or */ /* usefulness of any information, apparatus, product, or process */ /* disclosed, or represents that its specific commercial products, */ /* process, or service by trade name, trademark, manufacturer, or */ /* otherwise, does not necessarily constitute or imply its */ /* endorsement, recommendation, or favoring by the United States */ /* Government or the University of California. The views and opinions */ /* of the authors expressed herein do not necessarily state or reflect */ /* those of the United States Government or the University of */ /* California, and shall not be used for advertising or product */ /* endorsement purposes. */ /* */ /* Permission to use, copy, modify and distribute this software and its */ /* documentation for any non-commercial purpose, without fee, is */ /* hereby granted, provided that the above copyright notice and this */ /* permission notice appear in all copies of the software and */ /* supporting documentation, and that all UC LLNL identification in */ /* the user interface remain unchanged. The title to copyright LLNL */ /* XDIR shall at all times remain with The Regents of the University */ /* of California and users agree to preserve same. Users seeking the */ /* right to make derivative works with LLNL XDIR for commercial */ /* purposes may obtain a license from the Lawrence Livermore National */ /* Laboratory's Technology Transfer Office, P.O. Box 808, L-795, */ /* Livermore, CA 94550. */ /* */ /***************************************************************************/ /***************************************************************************/ #include #include #include #include #include #include #include #include "xdir.h" extern struct st_host_info hinfo[]; extern int diagnostics; extern int maxt; /* * init_data_conn - Initialize a data connection between the FTP server and * the client. "host" is the host id. Returns the file * descriptor of the data connection socket if successful, * -3 for broken connection, -6 for stop button pressed, * and -1 for other errors. */ init_data_conn(host) int host; { int sock; struct sockaddr_in data; int addrlen; char buf[32]; unsigned char *h; unsigned char port[2]; int retval; unsigned int hostport; /* Create socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { report_perror("Opening stream socket"); return -1; } /* Bind socket. Use same IP address as for control connection */ addrlen = sizeof(data); #if defined(UNIXWARE) || defined(_AIX) if (getsockname(hinfo[host].ctrl_fd, (struct sockaddr *)&data, (size_t *)&addrlen) < 0) { #else if (getsockname(hinfo[host].ctrl_fd, (struct sockaddr *)&data, &addrlen) < 0) { #endif report_perror("Gettin socket name"); close(sock); return -1; } data.sin_port = 0; if (bind(sock, (struct sockaddr *)&data, (int)sizeof(data)) < 0) { report_perror("Binding stream socket"); close(sock); return -1; } /* Listen for connection */ if (listen(sock, 1) < 0) { report_perror("Listen"); close(sock); return -1; } /* Tell FTP server what host/port to connect to */ #if defined(UNIXWARE) || defined(_AIX) if (getsockname(sock, (struct sockaddr *)&data, (size_t *)&addrlen) < 0) { #else if (getsockname(sock, (struct sockaddr *)&data, &addrlen) < 0) { #endif report_perror("Getting socket name"); close(sock); return -1; } h = (unsigned char *)&data.sin_addr; hostport = ntohs(data.sin_port); port[0] = (hostport&0xff00)>>8; port[1] = hostport&0xff; sprintf(buf, "%d,%d,%d,%d,%d,%d", h[0], h[1], h[2], h[3], port[0], port[1]); if ((retval = ftp_port(host, buf)) < 0) { close(sock); return retval; } return sock; } /* * accept_data_conn - Establish a data connection between the FTP server and * the client. "data_fd" is the data connection socket. * Returns the file descriptor of the data connection * socket if successful, else -1. "data_fd" is closed. */ accept_data_conn(data_fd) int data_fd; { struct sockaddr_in remote; int addrlen; int new_data_fd; /* Accept connection */ if (diagnostics == DEBUG) write_log("*** Will try to accept connection\n"); addrlen = sizeof(remote); new_data_fd = iaccept(data_fd, (struct sockaddr *)&remote, &addrlen); if (new_data_fd < 0) { report_perror("accept"); close(data_fd); return -1; } if (diagnostics == DEBUG) write_log("*** Was able to accept connection\n"); /* Success */ close(data_fd); return new_data_fd; } /* * passive_data_conn - Establish a data connection between the FTP * server and the client, where the FTP server * is in passive mode. "host" is the id of the * server's host. Returns 0 if successful, -3 * for broken control connection, -6 for stop * button pressed, or -1 for other errors. */ passive_data_conn(host) char *host; { struct sockaddr_in remote; char host_addr[16]; char msg[60]; char *hostport; int h[4]; int port[2]; int sock; int retval; /* Put FTP server in passive mode */ if((retval = ftp_passive(host, &hostport)) < 0) return retval; /* Form destination address */ bzero(&remote, (int)sizeof(remote)); remote.sin_family = AF_INET; sscanf(hostport, "%d,%d,%d,%d,%d,%d", &h[0], &h[1], &h[2], &h[3], &port[0], &port[1]); XtFree(hostport); sprintf(host_addr, "%d.%d.%d.%d", h[0], h[1], h[2], h[3]); remote.sin_addr.s_addr = inet_addr(host_addr); remote.sin_port = htons((short)(256*port[0]+port[1])); if (diagnostics == DEBUG) { sprintf(msg, "*** dest_addr of data connection = %lx\n", (unsigned long)remote.sin_addr.s_addr); write_log(msg); } /* Create socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { report_perror("Opening socket stream"); return -1; } /* Make socket nonblocking */ #ifndef SOCKS #ifdef FNDELAY if (fcntl(sock, F_SETFL, FNDELAY) == -1) { #else if (fcntl(sock, F_SETFL, O_NDELAY) == -1) { #endif report_perror("Making socket stream nonblocking"); close(sock); return -1; } #endif /* Connect socket */ if (diagnostics == DEBUG) write_log("*** Will try to connect to remote data\n"); if (iconnect(sock, (struct sockaddr *)&remote,(int)sizeof(remote)) < 0) { if (errno != EINPROGRESS) { report_perror("Connecting socket stream"); close(sock); return -1; } switch (select_on_write(sock, maxt)) { case -6: close(sock); return -6; case 0: write_log("Timed out while trying to establish data connection\n"); case -1: close(sock); return -1; } } return sock; }