int eventhandler(rudp_socket_t rsocket, rudp_event_t event, struct sockaddr_in *remote) { struct rxfile *rx; switch (event) { case RUDP_EVENT_TIMEOUT: if (remote) { fprintf(stderr, "vs_recv: time out in communication with %s:%d\n", inet_ntoa(remote->sin_addr), ntohs(remote->sin_port)); if ((rx = rxfind(remote))) { if (rx->fileopen) { close(rx->fd); } rxdel(rx); } } else { fprintf(stderr, "vs_recv: time out\n"); } break; case RUDP_EVENT_CLOSED: if (remote && (rx = rxfind(remote))) { if (rx->fileopen) { fprintf(stderr, "vs_recv: prematurely closed communication with %s:%d\n", inet_ntoa(remote->sin_addr), ntohs(remote->sin_port)); close(rx->fd); } rxdel(rx); }else { fprintf(stderr, "vs_recv: closing socket\n"); } break; default: fprintf(stderr, "vs_recv: unknown event %d\n", event); break; } return 0; }
int rudp_receiver(rudp_socket_t rsocket, struct sockaddr_in *remote, char *buf, int len) { struct rxfile *rx; int namelen; int i; struct vsftp *vs = (struct vsftp *) buf; if (len < VS_MINLEN) { fprintf(stderr, "vs_recv: Too short VSFTP packet (%d bytes)\n", len); return 0; } rx = rxfind(remote); switch (ntohl(vs->vs_type)) { case VS_TYPE_BEGIN: namelen = len - sizeof (vs->vs_type); if (namelen > VS_FILENAMELENGTH) namelen = VS_FILENAMELENGTH; strncpy(rx->name, vs->vs_info.vs_filename, namelen); rx->name[namelen] = '\0'; /* Null terminated */ /* Verify that file name is valid * Only alpha-numerical, period, dash and * underscore are allowed */ for (i = 0; i < namelen; i++) { char c = rx->name[i]; if (!(isalnum(c) || c == '.' || c == '_' || c == '-')) { fprintf(stderr, "vs_recv: Illegal file name \"%s\"\n", rx->name); rudp_close(rsocket); return 0; } } if (debug) { fprintf(stderr, "vs_recv: BEGIN \"%s\" (%d bytes) from %s:%d\n", rx->name, len, inet_ntoa(remote->sin_addr), ntohs(remote->sin_port)); } if ((rx->fd = creat(rx->name, 0644)) < 0) { perror("vs_recv: create"); rudp_close(rsocket); } else { rx->fileopen = 1; } break; case VS_TYPE_DATA: if (debug) { fprintf(stderr, "vs_recv: DATA (%d bytes) from %s:%d\n", len, inet_ntoa(remote->sin_addr), ntohs(remote->sin_port)); } len -= sizeof (vs->vs_type); /* len now is length of payload (data or file name) */ if (rx->fileopen) { if ((write(rx->fd, vs->vs_info.vs_filename, len)) < 0) { perror("vs_recv: write"); } } else { fprintf(stderr, "vs_recv: DATA ignored (file not open)\n"); } break; case VS_TYPE_END: if (debug) { fprintf(stderr, "vs_recv: END (%d bytes) from %s:%d\n", len, inet_ntoa(remote->sin_addr), ntohs(remote->sin_port)); } printf("vs_recv: received end of file \"%s\"\n", rx->name); if (rx->fileopen) { close(rx->fd); rxdel(rx); } /* else ignore */ break; default: fprintf(stderr, "vs_recv: bad vsftp type %d from %s:%d\n", vs->vs_type, inet_ntoa(remote->sin_addr), ntohs(remote->sin_port)); } return 0; }