Browse files

master/fd_max sind global, epsv_command hinzugefügt, Problem mit pass…

…ive mode eingegrnzt, paar Einrückungen und umbenennungen
  • Loading branch information...
1 parent f9d866e commit adf92679702ff78e7bec0b239baa3733a361c662 @grobie committed Jun 11, 2009
Showing with 150 additions and 51 deletions.
  1. +150 −51 duoit.c
View
201 duoit.c
@@ -38,6 +38,28 @@ typedef struct usr {
struct usr *next;
} usr;
+// global, I want this!!! ;)
+fd_set master; // master file descriptor list
+int fdmax = 0; // maximum file descriptor number
+
+int add_fd(int socket) {
+ printf("add new socket %d to master\n", socket);
+ FD_SET(socket, &master);
+ // keep track of the biggest file descriptor
+ if (socket > fdmax) {
+ fdmax = socket;
+ }
+
+ return 0;
+}
+
+int remove_fd(int socket) {
+ close(socket);
+ FD_CLR(socket, &master);
+
+ return 0;
+}
+
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa){
if (sa->sa_family == AF_INET){
@@ -207,7 +229,7 @@ int find_pre_user(int socket, usr *head, usr **result) {
*
* accepts new connections and adds them to the file discriptors
*/
-void handle_new_connection(int *listener, fd_set *master, int *fdmax, usr **user) {
+void handle_new_connection(int *listener, usr **user) {
socklen_t addrlen;
struct sockaddr_storage remoteaddr;
int newfd; // newly accept()ed socket descriptor
@@ -219,10 +241,10 @@ void handle_new_connection(int *listener, fd_set *master, int *fdmax, usr **user
if (newfd == -1) {
perror("accept");
} else {
- FD_SET(newfd, master); // add to master set
- if (newfd > *fdmax) { // keep track of the max
- *fdmax = newfd;
- }
+
+ // new socket to the fds
+ add_fd(newfd);
+
//adapt the user list
if (!(*user)) {
//initialize head of user-list
@@ -240,7 +262,7 @@ void handle_new_connection(int *listener, fd_set *master, int *fdmax, usr **user
/*
* handle new data connection
*/
-int handle_data_connection(int lsocket, fd_set *master, int *fdmax, usr *head) {
+int handle_data_connection(int lsocket, usr *head) {
struct sockaddr_storage remoteaddr;
socklen_t addrlen = sizeof remoteaddr;
int newfd; // newly accept()ed socket descriptor
@@ -257,13 +279,9 @@ int handle_data_connection(int lsocket, fd_set *master, int *fdmax, usr *head) {
newfd = accept(lsocket, (struct sockaddr *)&remoteaddr, &addrlen);
if (newfd == -1) {
perror("accept");
- } else {
- FD_SET(newfd, master); // add to master set
- if (newfd > *fdmax) { // keep track of the max
- *fdmax = newfd;
- }
- close(lsocket);
- FD_CLR(lsocket, master);
+ } else {
+ add_fd(newfd);
+ remove_fd(lsocket);
}
user->d_socket = newfd;
@@ -276,7 +294,7 @@ int handle_data_connection(int lsocket, fd_set *master, int *fdmax, usr *head) {
/*
* close connection and remove it from the file discriptors list
*/
-void close_connection(int socket, fd_set *master, usr **head) {
+void close_connection(int socket, usr **head) {
usr *user;
usr *save;
@@ -297,8 +315,7 @@ void close_connection(int socket, fd_set *master, usr **head) {
free(user);
}
- close(socket);
- FD_CLR(socket, master);
+ remove_fd(socket);
}
/*
@@ -470,9 +487,11 @@ int list_command(instruc *instruction, usr *user) {
int yes=1, rv;
if (user->passv == 1) {
+ send_message(user->c_socket, "125 Data connection already open.");
sock_fd = user->d_socket;
- send_message(user->c_socket, "125 Data connection already open; transfer starting.");
} else {
+ send_message(user->c_socket, "150 Opening ASCII mode data connection for file list.");
+
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
@@ -498,7 +517,6 @@ int list_command(instruc *instruction, usr *user) {
//got one
user->d_socket = sock_fd;
- send_message(user->c_socket, "150 Opening ASCII mode data connection for file list");
break;
}
@@ -509,15 +527,17 @@ int list_command(instruc *instruction, usr *user) {
}
send_message(sock_fd, "total 0\r\ndrwx------+ 24 Grobie staff 816 10 Jun 00:46 Desktop");
- close(sock_fd);
send_message(user->c_socket, "226 Transfer complete.");
+
+ user->d_socket = 0;
+ remove_fd(sock_fd);
return 0;
}
/*
* sets mode to passive and prepares d_socket for listening
*/
-int passv_command(instruc *instruction, usr *user) {
+int pasv_command(instruc *instruction, usr *user) {
char reply[30 + 18 + 7]; //#chars of standard reply + ip + #,
char ipstr[INET6_ADDRSTRLEN] = LISTENIP;
char port1[4];
@@ -531,7 +551,7 @@ int passv_command(instruc *instruction, usr *user) {
memset(port1, '\0', sizeof port1);
memset(port2, '\0', sizeof port2);
- memset(possible_port, '\0', sizeof port1);
+ memset(possible_port, '\0', sizeof possible_port);
memset(reply, '\0', sizeof reply);
//Create new d_socket we will listen on
@@ -560,23 +580,16 @@ int passv_command(instruc *instruction, usr *user) {
return 1;
}
- if (bind(sock_fd, p->ai_addr, p->ai_addrlen) == -1){
+ if (bind(sock_fd, p->ai_addr, p->ai_addrlen) == -1) {
close(sock_fd);
perror("server: bind");
continue;
}
break;
}
- if (p == NULL) {
- close(sock_fd);
- continue;
- }
-
break;
}
- //save our IP-Address
- //inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), ipstr, sizeof ipstr);
freeaddrinfo(servinfo); //all done with this structure
@@ -585,12 +598,15 @@ int passv_command(instruc *instruction, usr *user) {
perror("listen");
return 1;
}
+
+ // saving fd
+ user->d_socket = sock_fd;
+ add_fd(sock_fd);
printf("server: waiting for data-connections (port %s) ...\n", possible_port);
//generating reply for client
- strcpy(reply, "227 Entering Passive Mode ");
- strcat(reply, "(");
+ strcpy(reply, "227 Entering Passive Mode (");
//format IP-Adress - e.g. 127,0,0,1
ptr = strtok(ipstr, ".");
while(ptr != NULL) {
@@ -619,13 +635,91 @@ int passv_command(instruc *instruction, usr *user) {
send_message(user->c_socket, reply);
return 0;
}
+
/*
- * quits the connection with client
+ * sets mode to passive and prepares d_socket for listening | extended version
*/
-int quit_command(instruc *instruction, usr *user, fd_set *master, usr **head) {
+int epsv_command(instruc *instruction, usr *user) {
+ char reply[43 + 5]; // chars of standard reply + port
+ char ipstr[INET6_ADDRSTRLEN] = LISTENIP;
+ char possible_port[5];
+ char *ptr;
+ int mod, div, i, h;
+ int sock_fd;
+ struct addrinfo hints, *servinfo, *p;
+ int yes=1, rv;
+ memset(possible_port, '\0', sizeof possible_port);
+ memset(reply, '\0', sizeof reply);
+
+ //Create new d_socket we will listen on
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET; //PASV command only definded for IPv4
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE; //use own IP
+
+ for(h = 3022; h < 65535; h++) {
+ sprintf(possible_port, "%d", h);
+ if ((rv = getaddrinfo(NULL, possible_port, &hints, &servinfo)) != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
+ return 1;
+ }
+
+ // loop through all the results and bind to the first we can
+ for(p = servinfo; p != NULL; p = p->ai_next) {
+ if ((sock_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
+ perror("server: socket");
+ continue;
+ }
+
+ // reuse sockets
+ if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
+ perror("setsockopt");
+ return 1;
+ }
+
+ if (bind(sock_fd, p->ai_addr, p->ai_addrlen) == -1) {
+ close(sock_fd);
+ perror("server: bind");
+ continue;
+ }
+ break;
+ }
+
+ break;
+ }
+
+ freeaddrinfo(servinfo); //all done with this structure
+
+ //listen
+ if (listen(sock_fd, BACKLOG) == -1){
+ perror("listen");
+ return 1;
+ }
+
+ // saving fd
+ user->d_socket = sock_fd;
+ add_fd(user->d_socket);
+
+ printf("server: waiting for data-connections (port %s) ...\n", possible_port);
+
+ //generating reply for client
+ strcpy(reply, "229 Entering Extended Passive Mode (|||");
+
+ //append port
+ strcat(reply, possible_port);
+ strcat(reply, "|).");
+
+ send_message(user->c_socket, reply);
+ return 0;
+}
+
+/*
+ * quits the connection with client
+ */
+int quit_command(instruc *instruction, usr *user, usr **head) {
send_message(user->c_socket, "221 Goodbye.");
- close_connection(user->c_socket, master, head);
+ close_connection(user->c_socket, head);
return 0;
}
@@ -700,7 +794,7 @@ int log_action(usr *user, char *message) {
*
* TODO
*/
-int dispatch(usr *user, char *received, int received_len, fd_set *master, usr **head) {
+int dispatch(usr *user, char *received, int received_len, usr **head) {
instruc instruction;
if (parse_command(received, received_len, &instruction)) {
@@ -725,11 +819,17 @@ int dispatch(usr *user, char *received, int received_len, fd_set *master, usr **
return 1;
}
} else if (!strcmp(instruction.command, "PASV")) {
- if (passv_command(&instruction, user)) {
+ if (pasv_command(&instruction, user)) {
+ return 1;
+ }
+ } else if (!strcmp(instruction.command, "EPSV")) {
+ if (epsv_command(&instruction, user)) {
return 1;
}
} else if (!strcmp(instruction.command, "QUIT")) {
- quit_command(&instruction, user, master, head);
+ if (quit_command(&instruction, user, head)) {
+ return 1;
+ }
} else {
send_message(user->c_socket, "502 Command not implemented.");
}
@@ -789,9 +889,7 @@ int parse_command(char *received, int received_len, instruc *instruction) {
int main(int argc, char *argv[]) {
struct sockaddr_storage client_addr; //client's address information
socklen_t sin_size;
- fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()
- int fdmax; // maximum file descriptor number
int listener; // listening socket descriptor
usr *head = NULL;
usr *current_user = NULL;
@@ -805,9 +903,7 @@ int main(int argc, char *argv[]) {
FD_ZERO(&read_fds);
FD_ZERO(&master);
// add the listener to the master set
- FD_SET(listener, &master);
- // keep track of the biggest file descriptor
- fdmax = listener;
+ add_fd(listener);
// main loop
while(1) {
@@ -820,29 +916,32 @@ int main(int argc, char *argv[]) {
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) {
+ printf("es zappelt\n");
if (i == listener) {
- handle_new_connection(&listener, &master, &fdmax, &head);
+ printf("neue Connection\n");
+ handle_new_connection(&listener, &head);
} else {
-
- if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
+ printf("ohoh\n");
+ if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
if (nbytes == 0) {
// connection closed
printf("socket %d hung up\n", i);
- } else {
- perror("recv");
- }
- close_connection(i, &master, &head);
+ } else {
+ printf("aber wirklich %d\n", i);
+ perror("recv");
+ }
+ close_connection(i, &head);
} else {
if (find_user_by_dsocket(i, head, &current_user)) {
// client sends message
if (find_user_by_csocket(i, head, &current_user)) {
printf("*ERR* corresponding user to socket %d not found!\n", i);
continue;
}
- dispatch(current_user, buf, nbytes, &master, &head);
+ dispatch(current_user, buf, nbytes, &head);
} else {
- handle_data_connection(i, &master, &fdmax, head);
+ handle_data_connection(i, head);
}
}

0 comments on commit adf9267

Please sign in to comment.