#include #include #include #include #include #include #include #include #include #include #include void poll_wait(int fd, int events) { int n; struct pollfd ufds[1]; memset((char *) &ufds, 0, sizeof(ufds)); ufds[0].fd = fd; ufds[0].events = events; n = poll(ufds, 1, -1); if (n < 0) { perror("poll()"); exit(1); } } int main(int argc, char **argv) { int i, s, s2, err; int h1,h2,h3,h4,p1,p2; size_t sz; struct sockaddr_in addr; struct in_addr inaddr; char buf[8192], junk[8192]; /* clear out address structures */ memset((char *) &addr, 0, sizeof(addr)); /* Get the destination IP address */ inet_aton("127.0.0.1", &inaddr); /* Set up the local address to which we will connect */ addr.sin_family = AF_INET; addr.sin_addr = inaddr; addr.sin_port = htons(21); s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) { perror("socket()"); exit(1); } /* Connect to the destination port */ if (connect(s, (struct sockaddr *) &addr, sizeof addr)) { perror("connect()"); exit(1); } printf("Connected!\n"); printf("Sending USER ftp, PASS nobody@\n"); /* Log in */ if (write(s,"USER ftp\r\n" "PASS nobody@\r\n", 10+14) != 10+14) { perror("write login:"); exit(1); } /* Wait for the login to succeed */ sleep(1); do { sz = read(s,buf,8192); if (sz < 0) { perror("read login:"); exit(1); } printf("Got %d bytes\n", sz); if (sz >= 0) { buf[sz]='\0'; printf("%s", buf); } } while (sz > 0 && !strstr(buf,"230 ")); /* Ok. here we should have been logged in (230 reply) * no actual check here as I am lazy and this is not * production code ;-) */ /* Now get the local endpoint. The data channel must be * bound to the same address as the control channel */ sz = sizeof addr; if (getsockname(s, (struct sockaddr *) &addr, &sz)) { perror("getsockname()"); exit(1); } printf("Creating data socket\n"); /* Set up our data channel where the actual test occurs */ s2 = socket(AF_INET, SOCK_STREAM, 0); if (s2 == -1) { perror("socket()"); exit(1); } /* Bind it to the local endpoint IP address */ addr.sin_port = 0; if (bind(s2, (struct sockaddr *) &addr, sizeof(addr))) { perror("bind()"); exit(1); } /* Make the socket non-blocking */ fcntl(s2, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK); printf("Sending PASV\n"); /* Ask the FTP server for a passive connection */ if (write(s, "PASV\r\n", 6) != 6) { perror("write pasv:"); exit(1); } sleep(1); sz=read(s, buf, 8192); if (sz < 0) { perror("read pasv:"); exit(1); } buf[sz]=0; printf("%s",buf); /* Decode the server address */ sz = sscanf(buf, "%d%[^0123456789]%d,%d,%d,%d,%d,%d", &i, junk, &h1, &h2, &h3, &h4, &p1, &p2); if (sz != 8 || i != 227) { fprintf(stderr, "Failed to parse PASV reply\n"); exit(1); } sprintf(junk,"%d.%d.%d.%d",h1,h2,h3,h4); inet_aton(junk, &addr.sin_addr); addr.sin_port = htons((p1<<8)+p2); /* Connect to the destination port */ printf("Connecting to %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); if (connect(s2, (struct sockaddr *) &addr, sizeof addr) && errno != EINPROGRESS) { perror("connect()"); exit(1); } /* Wait for the connection to complete */ poll_wait(s2, POLLOUT | POLLERR); sz = sizeof(err); if (getsockopt(s2, SOL_SOCKET, SO_ERROR, &err, &sz)) { perror("getsockopt( SOL_SOCKET SO_ERROR )"); exit(1); } if (err) { errno = err; perror("non-blocking connect()"); exit(1); } sz = sizeof addr; if (getsockname(s2, (struct sockaddr *) &addr, &sz)) { perror("getsockname()"); exit(1); } printf("Connected. Local endpoint is %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); if (write(s,"LIST\r\n", 6) != 6) { perror("write command:"); exit(1); } poll_wait(s, POLLERR | POLLIN); sz=read(s, buf, 8192); if (sz < 0) { perror("read pasv:"); exit(1); } buf[sz]=0; printf("%s",buf); do { printf("Waiting for data..\n"); poll_wait(s2, POLLERR | POLLIN); printf("Reading data\n"); i = read(s2, &buf, sizeof(buf) - 1); if (i == 0) { printf("read() returned 0 bytes.. is this really true?\n"); i = read(s2, &buf, sizeof(buf) - 1); if (i != 0) printf("nope, it should have returned %d\n", i); else printf("yep, probably so\n"); } if (i < 0) { perror("read()"); if (errno != EAGAIN) exit(1); } else { buf[i] = 0; printf("Got %d bytes ----------\n%s==========================\n", i, buf); } } while (i != 0); /* We are done */ printf("DONE!\n"); close(s2); close(s); return 0; }