/***************************************************************************/
/***************************************************************************/
/* */
/* (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 <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1