FTP服务器,客户端使用PASV无法连接上
头文件rdwr.h
#include <unistd.h>#include <errno.h>#include <stdio.h>ssize_t readline(int fd, void *vptr, size_t maxlen){ ssize_t n, rc; char c; char *ptr; ptr = vptr; for (n = 0; n < maxlen; n++) { again: if ((rc = read(fd, &c, 1)) == 1) { *ptr++ = c; if (c == '\n') break; } else if (rc == 0) { *ptr = 0; return -1; } else { if (errno == EINTR) goto again; return -1; } } *ptr = 0; return n;}ssize_t readn(int fd, void *vptr, size_t n){ size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ((nread = read(fd, ptr, nleft)) < 0) { if (errno == EINTR) nread = 0; else return -1; } else if (nread == 0) { break; } nleft -= nread; ptr += nread; } return(n - nleft);}ssize_t writen(int fd, void *vptr, size_t n){ size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ((nwritten = write(fd, ptr, nleft)) <= 0) { if (nwritten < 0 && errno == EINTR) nwritten = 0; else return -1; } nleft -= nwritten; ptr += nwritten; } return(n - nleft);}ssize_t wr_and_rd(int fd, void *buf, size_t bufsize){ size_t nleft; ssize_t n; if (writen(fd, buf, bufsize) < 0) return -1; n = read(fd, buf, bufsize); return n;}
#include <sys/socket.h>#include <sys/types.h>#include <strings.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <stdio.h>#define SA struct sockaddrint create_client_fd(const char *hostname, int port){ int clientfd; struct hostent *hostinfo; struct sockaddr_in srv; struct sockaddr_in cli; if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; if ((hostinfo = gethostbyname(hostname)) == NULL) return -2; bzero(&srv, sizeof(srv)); srv.sin_family = AF_INET; srv.sin_port = htons(port); srv.sin_addr = *(struct in_addr *)*hostinfo->h_addr_list; if (connect(clientfd, (SA *)&srv, sizeof(srv)) < 0) { close(clientfd); return -1; } return clientfd;}int create_listen_fd(int port, int listen_queue){ int listenfd, optval = 1; struct sockaddr_in srv; if ((listenfd = socket(AF_INET, SOCK_STREAM ,0)) < 0) return -1; if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof(int)) < 0) return -1; bzero(&srv, sizeof(srv)); srv.sin_family = AF_INET; srv.sin_addr.s_addr = htonl(INADDR_ANY); srv.sin_port = htons((unsigned short)port); if (bind(listenfd, (SA *)&srv, sizeof(srv)) < 0) return -1; if (listen(listenfd, listen_queue) < 0) return -1; return listenfd;}int create_connection(struct sockaddr *srv, size_t srv_len, int port){ int fd; if ((fd = socket(AF_INET, SOCK_STREAM ,0)) < 0) return -1; if (connect(fd, (SA *)&srv, srv_len) < 0) return -1; return fd;}
int do_login(int fd);int do_current_dir(int fd, int data_fd);int do_show_srv(int fd);int do_show_files(int fd, int data_fd);int do_port_connect(int fd);int do_pasv_connect(int fd);int do_sent_file(int fd, int data_fd);int do_close(int fd);
#include <string.h>#include <unistd.h>#include <fcntl.h>#include "server.h"#include "sock.h"#include "rdwr.h"char cmd_buf[128] = "\0";char cmd_name[128] = "\0";char cmd_arg[128] = "\0";typedef struct { char *ftp_cmd_name; int (* ftp_cmd_handler)(int sockfd);} ftpcmd1_s;typedef struct { char *ftp_cmd_name; int (* ftp_cmd_handler)(int sockfd, int data_fd);} ftpcmd2_s;ftpcmd1_s ftpcmd1[] = { {"USER", do_login},// {"TYPE", NULL}, {"SYST", do_show_srv},// {"PORT", do_port_connect}, {"PASV", do_pasv_connect},// {"QUIT", do_close}, {NULL, NULL},};ftpcmd2_s ftpcmd2[] = {// {"PWD", do_current_dir},// {"LIST", do_show_files},// {"STOR", NULL}, {"RETR", do_sent_file},// {"DELE", NULL}, {NULL, NULL},};int check_cmd1(){ int i; for (i = 0; ftpcmd1[i].ftp_cmd_name != NULL; i++) { if (strcmp(cmd_name, ftpcmd1[i].ftp_cmd_name) == 0) { return i; } } return -1;}int check_cmd2(){ int i; for (i = 0; ftpcmd2[i].ftp_cmd_name != NULL; i++) { if (strcmp(cmd_name, ftpcmd2[i].ftp_cmd_name) == 0) { return i; } } return -1;}int do_show_srv(clifd){ return talk(clifd, "Linux Fedora 13");}int get_cmd(int sockfd){ int nread; char *cptr; bzero(cmd_buf, sizeof(cmd_buf)); bzero(cmd_name, sizeof(cmd_name)); bzero(cmd_arg, sizeof(cmd_arg)); nread = read(sockfd, cmd_buf, sizeof(cmd_buf)); if (nread == -1) return -1; if ((cptr = strchr(cmd_buf, '\n')) != NULL) *cptr = 0; printf("get cmd: %s\n", cmd_buf); sscanf(cmd_buf, "%s %s", cmd_name, cmd_arg); return 0;}int send_cmd(int sockfd, const char *mes){ char buf[1024]; int buflen; printf("send cmd: %s\n", mes); if (sprintf(buf, "%s\r\n", mes) < 0) return -1; buflen = strlen(buf); if (writen(sockfd, buf, buflen) != buflen) return -1; return 0;}int talk(int sockfd, const char *mes){ if (send_cmd(sockfd, mes) < 0) return -1; return get_cmd(sockfd);}int do_login(int clifd){ int nread; printf("in login\n"); if (strcmp(cmd_name, "USER") != 0) { talk(clifd, "530 Please Login"); } else if (strcmp(cmd_arg, "red") != 0) { talk(clifd, "530 username unavailable"); } else { talk(clifd, "331 Please input password"); if (strcmp(cmd_name, "PASS") != 0) { talk(clifd, "530 not password"); } else if (strcmp(cmd_arg, "gospursgo") != 0) { talk(clifd, "530 password error"); } else { talk(clifd, "230 login succeed"); return 0; } } return -1;}void change_ip(char *ip){ while (*ip++) { if (*ip == '.') { *ip = ','; } }}int do_pasv_connect(int clifd){ int listenfd, data_fd, addrlen, res, i; struct sockaddr_in addr; char local_ip[20], mes[128]; int local_port, net_port; struct hostent *hostptr; if ((listenfd = create_listen_fd(8080, 1)) < 0) { return -1; } addrlen = sizeof(struct sockaddr_in); if (getsockname(clifd, (SA *)&addr, &addrlen) < 0) { return -1; } local_port = 8080; net_port = htons(local_port); hostptr = gethostent(); strcpy(local_ip, inet_ntoa(addr.sin_addr)); change_ip(local_ip);// res = snprintf(mes, sizeof(mes), "227 PORT %s,%d,%d",// local_ip, local_port / 256, local_port % 256); res = snprintf(mes, sizeof(mes), "PORT %s,%d,%d", local_ip, net_port / 256, net_port % 256); if (res == sizeof(mes) || res < 0) mes[res] = 0;// talk(clifd, mes); send_cmd(clifd, "227"); send_cmd(clifd, mes); data_fd = accept(listenfd, NULL, NULL); printf("data_fd = %d\n", data_fd);/* if ((i = check_cmd2()) < 0) { talk(clifd, "202 common unavailable"); } else { ftpcmd2[i].ftp_cmd_handler(clifd, data_fd); } close(data_fd); return 0;*/ return data_fd;}int do_sent_file(int clifd, int data_fd){ char filename[128], buf[1024]; char *ptr; int res, fd, nread;printf("here\n"); ptr = cmd_arg; if ((*ptr != '/') && ((*ptr != '.') && (*(ptr + 1) != '/'))) { res = sprintf(filename, "./%s", cmd_arg); filename[res] = 0; } if ((fd = open(filename, O_RDONLY)) < 0) { if (access(filename, F_OK) < 0) { talk(clifd, "450 file not exist"); } else { talk(clifd, "unable to open the file"); } return -1; } else { talk(clifd, "150 file to sent"); while ((nread = read(fd, buf, sizeof(buf))) > 0) { writen(data_fd, buf, nread); writen(STDOUT_FILENO, buf, nread); } } return 0;}int main(){ pid_t listen_pid, clifd, data_fd = -1; struct sockaddr_in cliaddr; int clilen, i; char buf[1024], *cptr; if ((listen_pid = create_listen_fd(21, 5)) < 0) { perror("listen"); exit(1); } while (1) { clilen = sizeof(struct sockaddr_in); clifd = accept(listen_pid, (SA *)&cliaddr, &clilen); if (clifd < 0) { perror("accept"); } talk(clifd, "220 connection succeed, please login"); while (1) { if ((i = check_cmd1()) >= 0) { data_fd = ftpcmd1[i].ftp_cmd_handler(clifd); } if ((i = check_cmd2()) >= 0) { ftpcmd2[i].ftp_cmd_handler(clifd, data_fd); } }// close(clifd); } exit(0);}