diff options
author | kevlo <kevlo@FreeBSD.org> | 2010-10-11 13:46:21 +0800 |
---|---|---|
committer | kevlo <kevlo@FreeBSD.org> | 2010-10-11 13:46:21 +0800 |
commit | 4d6b849dd2bce8d2c5ff66264f1f114263393127 (patch) | |
tree | 28795a8f236e8d00e5943d140a8091eaad709520 /ftp/atftp | |
parent | 28762757639963da6eda436b0b409595d8105b78 (diff) | |
download | freebsd-ports-graphics-4d6b849dd2bce8d2c5ff66264f1f114263393127.tar.gz freebsd-ports-graphics-4d6b849dd2bce8d2c5ff66264f1f114263393127.tar.zst freebsd-ports-graphics-4d6b849dd2bce8d2c5ff66264f1f114263393127.zip |
Missed multicast fix patches in previous commit
Diffstat (limited to 'ftp/atftp')
-rw-r--r-- | ftp/atftp/Makefile | 1 | ||||
-rw-r--r-- | ftp/atftp/files/patch-options.c | 15 | ||||
-rw-r--r-- | ftp/atftp/files/patch-options.h | 11 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftp.c | 93 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftp_def.c | 17 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftp_file.c | 68 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftp_io.c | 35 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftpd.c | 50 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftpd.h | 14 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftpd_file.c | 353 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftpd_list.c | 45 | ||||
-rw-r--r-- | ftp/atftp/files/patch-tftpd_mtftp.c | 40 |
12 files changed, 624 insertions, 118 deletions
diff --git a/ftp/atftp/Makefile b/ftp/atftp/Makefile index 54c63e43cd5..18c6919b327 100644 --- a/ftp/atftp/Makefile +++ b/ftp/atftp/Makefile @@ -7,6 +7,7 @@ PORTNAME= atftp PORTVERSION= 0.7 +PORTREVISION= 1 CATEGORIES= ftp MASTER_SITES= ${MASTER_SITE_DEBIAN} MASTER_SITE_SUBDIR= pool/main/a/${PORTNAME} diff --git a/ftp/atftp/files/patch-options.c b/ftp/atftp/files/patch-options.c new file mode 100644 index 00000000000..fd96417175f --- /dev/null +++ b/ftp/atftp/files/patch-options.c @@ -0,0 +1,15 @@ +--- options.c.orig 2003-04-25 08:16:18.000000000 +0800 ++++ options.c 2010-10-11 10:23:20.000000000 +0800 +@@ -273,6 +273,12 @@ + return ERR; + } + ++int opt_equal(struct tftp_opt *opt1, struct tftp_opt *opt2) ++{ ++ return ((strncmp(opt1->option, opt2->option, OPT_SIZE) == 0) && ++ (strncmp(opt1->value, opt2->value, OPT_SIZE) == 0)); ++} ++ + void opt_set_tsize(int tsize, struct tftp_opt *options) + { + snprintf(options[OPT_TSIZE].value, VAL_SIZE, "%d", tsize); diff --git a/ftp/atftp/files/patch-options.h b/ftp/atftp/files/patch-options.h new file mode 100644 index 00000000000..09e2acff81a --- /dev/null +++ b/ftp/atftp/files/patch-options.h @@ -0,0 +1,11 @@ +--- options.h.orig 2001-07-07 07:35:18.000000000 +0800 ++++ options.h 2010-10-11 13:11:41.000000000 +0800 +@@ -39,6 +39,8 @@ + int opt_get_timeout(struct tftp_opt *options); + int opt_get_blksize(struct tftp_opt *options); + int opt_get_multicast(struct tftp_opt *options, char *addr, int *port, int *mc); ++int opt_equal(struct tftp_opt *opt1, struct tftp_opt *opt2); ++int opt_same_file(struct tftp_opt *opt1, struct tftp_opt *opt2); + void opt_set_tsize(int tsize, struct tftp_opt *options); + void opt_set_timeout(int timeout, struct tftp_opt *options); + void opt_set_blksize(int blksize, struct tftp_opt *options); diff --git a/ftp/atftp/files/patch-tftp.c b/ftp/atftp/files/patch-tftp.c index 3b1a356e38e..a66573d3d22 100644 --- a/ftp/atftp/files/patch-tftp.c +++ b/ftp/atftp/files/patch-tftp.c @@ -1,5 +1,5 @@ ---- tftp.c.orig 2010-10-05 09:35:38.000000000 +0800 -+++ tftp.c 2010-10-05 09:42:03.000000000 +0800 +--- tftp.c.orig 2010-10-11 11:19:25.000000000 +0800 ++++ tftp.c 2010-10-11 11:19:12.000000000 +0800 @@ -354,7 +354,7 @@ void make_arg(char *string, int *argc, char ***argv) { @@ -9,7 +9,88 @@ /* split the string to an argz vector */ if (argz_create_sep(string, ' ', &tmp, &argz_len) != 0) -@@ -608,9 +608,16 @@ +@@ -408,8 +408,7 @@ + */ + int set_peer(int argc, char **argv) + { +- struct hostent *host; /* for host name lookup */ +- struct servent *sp; /* server entry for tftp service */ ++ int port = -1; + + /* sanity check */ + if ((argc < 2) || (argc > 3)) +@@ -418,13 +417,34 @@ + return ERR; + } + +- /* get the server entry */ +- sp = getservbyname("tftp", "udp"); +- if (sp == 0) { +- fprintf(stderr, "tftp: udp/tftp, unknown service.\n"); +- return ERR; ++ /* get the server port */ ++ if (argc == 3) ++ { ++ port = htons(atoi(argv[2])); ++ if (port < 0) ++ { ++ fprintf(stderr, "%s: bad port number.\n", argv[2]); ++ data.connected = 0; ++ return ERR; ++ } ++ data.sa_peer.sin_port = port; ++ } ++ else ++ { ++ /* get the server entry */ ++ struct servent *sp; ++ sp = getservbyname("tftp", "udp"); ++ if (sp == 0) { ++ fprintf(stderr, "tftp: udp/tftp, unknown service.\n"); ++ return ERR; ++ } ++ else ++ { ++ port = sp->s_port; ++ } + } + ++ struct hostent *host; /* for host name lookup */ + /* look up the host */ + host = gethostbyname(argv[1]); + /* if valid, update s_inn structure */ +@@ -437,7 +457,7 @@ + Strncpy(data.hostname, host->h_name, + sizeof(data.hostname)); + data.hostname[sizeof(data.hostname)-1] = 0; +- data.sa_peer.sin_port = sp->s_port; ++ data.sa_peer.sin_port = port; + } + else + { +@@ -445,20 +465,8 @@ + data.connected = 0; + return ERR; + } +- /* get the server port */ +- if (argc == 3) +- { +- sp->s_port = htons(atoi(argv[2])); +- if (sp->s_port < 0) +- { +- fprintf(stderr, "%s: bad port number.\n", argv[2]); +- data.connected = 0; +- return ERR; +- } +- data.sa_peer.sin_port = sp->s_port; +- } + /* copy port number to data structure */ +- data.port = ntohs(sp->s_port); ++ data.port = ntohs(port); + + data.connected = 1; + return OK; +@@ -608,9 +616,16 @@ exit(ERR); } memset(&data.sa_local, 0, sizeof(data.sa_local)); @@ -29,7 +110,7 @@ /* do the transfer */ gettimeofday(&data.start_time, NULL); -@@ -621,7 +628,7 @@ +@@ -621,7 +636,7 @@ fsync(data.sockfd); close(data.sockfd); @@ -38,7 +119,7 @@ } /* -@@ -712,9 +719,16 @@ +@@ -712,9 +727,16 @@ exit(ERR); } memset(&data.sa_local, 0, sizeof(data.sa_local)); @@ -58,7 +139,7 @@ /* do the transfer */ gettimeofday(&data.start_time, NULL); -@@ -731,7 +745,7 @@ +@@ -731,7 +753,7 @@ fsync(data.sockfd); close(data.sockfd); diff --git a/ftp/atftp/files/patch-tftp_def.c b/ftp/atftp/files/patch-tftp_def.c index a56e5ee8470..f1e0eb61379 100644 --- a/ftp/atftp/files/patch-tftp_def.c +++ b/ftp/atftp/files/patch-tftp_def.c @@ -1,15 +1,20 @@ ---- tftp_def.c.orig 2010-10-05 09:43:06.000000000 +0800 -+++ tftp_def.c 2010-10-05 09:43:53.000000000 +0800 -@@ -140,8 +140,10 @@ +--- tftp_def.c.orig 2010-10-11 11:20:48.000000000 +0800 ++++ tftp_def.c 2010-10-11 11:20:40.000000000 +0800 +@@ -140,11 +140,14 @@ */ inline char *Strncpy(char *to, const char *from, size_t size) { - to[size-1] = '\000'; - return strncpy(to, from, size - 1); -+ strncpy(to, from, size); + if (size > 0) ++ { + to[size-1] = '\000'; -+ return to; ++ return strncpy(to, from, size - 1); ++ } else ++ return to; } - +- + /* + * gethostbyname replacement that is reentrant. This function is copyied + * from the libc manual. diff --git a/ftp/atftp/files/patch-tftp_file.c b/ftp/atftp/files/patch-tftp_file.c index 59b08f46739..8f2e1931393 100644 --- a/ftp/atftp/files/patch-tftp_file.c +++ b/ftp/atftp/files/patch-tftp_file.c @@ -1,5 +1,5 @@ ---- tftp_file.c.orig 2004-02-13 11:16:09.000000000 +0800 -+++ tftp_file.c 2010-10-04 18:46:54.000000000 +0800 +--- tftp_file.c.orig 2010-10-11 11:21:54.000000000 +0800 ++++ tftp_file.c 2010-10-11 11:27:01.000000000 +0800 @@ -59,7 +59,7 @@ unsigned int next_word; @@ -9,17 +9,7 @@ next_word_no = next_hole / 32; next_bit_no = next_hole % 32; next_word = bitmap[next_word_no]; -@@ -150,7 +150,8 @@ - memset(&file_bitmap, 0, sizeof(file_bitmap)); - - /* make sure the socket is not connected */ -- sa.sin_family = AF_UNSPEC; -+ memset(&sa, 0, sizeof(sa)); -+ sa.sin_family = AF_INET; - connect(sockfd, (struct sockaddr *)&sa, sizeof(sa)); - connected = 0; - -@@ -238,9 +239,13 @@ +@@ -238,9 +238,13 @@ tftp_find_bitmap_hole(prev_bitmap_hole, file_bitmap); block_number = prev_bitmap_hole; } @@ -27,40 +17,26 @@ - fprintf(stderr, "sent ACK <block: %d>\n", block_number); - tftp_send_ack(sockfd, &sa, block_number); + result = tftp_send_ack(sockfd, &sa, block_number); -+ if (result == OK) -+ { -+ if (data->trace) -+ fprintf(stderr, "sent ACK <block: %d>\n", -+ block_number); ++ if (result == OK) ++ { ++ if (data->trace) ++ fprintf(stderr, "sent ACK <block: %d>\n", ++ block_number); + } /* if we just ACK the last block we are done */ if (block_number == last_block_number) state = S_END; -@@ -627,7 +632,8 @@ - from.sin_addr.s_addr = 0; - - /* make sure the socket is not connected */ -- sa.sin_family = AF_UNSPEC; -+ memset(&sa, 0, sizeof(sa)); -+ sa.sin_family = AF_INET; - connect(sockfd, (struct sockaddr *)&sa, sizeof(sa)); - connected = 0; - -@@ -761,7 +767,7 @@ - /* if the socket if not connected, connect it */ - if (!connected) - { -- //connect(sockfd, (struct sockaddr *)&sa, sizeof(sa)); -+ connect(sockfd, (struct sockaddr *)&sa, sizeof(sa)); - connected = 1; - } - block_number = ntohs(tftphdr->th_block); -@@ -780,7 +786,7 @@ - /* if the socket if not connected, connect it */ - if (!connected) - { -- //connect(sockfd, (struct sockaddr *)&sa, sizeof(sa)); -+ connect(sockfd, (struct sockaddr *)&sa, sizeof(sa)); - connected = 1; - } - state = S_OACK_RECEIVED; +@@ -484,6 +488,13 @@ + sa_mcast.sin_family = AF_INET; + sa_mcast.sin_addr.s_addr = htonl(INADDR_ANY); + sa_mcast.sin_port = htons(mc_port); ++ int yes = 1; ++ if (setsockopt(mcast_sockfd, SOL_SOCKET, ++ SO_REUSEADDR, &yes, sizeof(yes)) < 0) ++ { ++ perror("setsockopt"); ++ exit(1); ++ } + + if (bind(mcast_sockfd, (struct sockaddr *)&sa_mcast, + sizeof(sa_mcast)) < 0) diff --git a/ftp/atftp/files/patch-tftp_io.c b/ftp/atftp/files/patch-tftp_io.c index 1c2672e978f..28bf686a7af 100644 --- a/ftp/atftp/files/patch-tftp_io.c +++ b/ftp/atftp/files/patch-tftp_io.c @@ -1,39 +1,44 @@ --- tftp_io.c.orig 2004-02-19 09:30:00.000000000 +0800 -+++ tftp_io.c 2010-10-04 18:45:56.000000000 +0800 -@@ -102,8 +102,8 @@ - tftphdr.th_opcode = htons(ACK); ++++ tftp_io.c 2010-10-11 13:01:28.000000000 +0800 +@@ -103,7 +103,8 @@ tftphdr.th_block = htons(block_number); -- result = sendto(socket, &tftphdr, 4, 0, (struct sockaddr *)sa, + result = sendto(socket, &tftphdr, 4, 0, (struct sockaddr *)sa, - sizeof(*sa)); -+ result = write(socket, &tftphdr, 4); ++ sizeof(*sa)); + if (result < 0) return ERR; return OK; -@@ -141,8 +141,8 @@ - } +@@ -142,7 +143,8 @@ } /* send the buffer */ -- result = sendto(socket, buffer, index, 0, (struct sockaddr *)sa, + result = sendto(socket, buffer, index, 0, (struct sockaddr *)sa, - sizeof(*sa)); -+ result = write(socket, buffer, index); ++ sizeof(*sa)); + if (result < 0) return ERR; return OK; -@@ -191,8 +191,8 @@ - tftphdr->th_opcode = htons(DATA); +@@ -171,6 +173,7 @@ + + result = sendto(socket, tftphdr, size, 0, (struct sockaddr *)sa, + sizeof(*sa)); ++ + if (result < 0) + return ERR; + return OK; +@@ -192,7 +195,8 @@ tftphdr->th_block = htons(block_number); -- result = sendto(socket, data, size, 0, (struct sockaddr *)sa, + result = sendto(socket, data, size, 0, (struct sockaddr *)sa, - sizeof(*sa)); -+ result = write(socket, data, size); ++ sizeof(*sa)); + if (result < 0) return ERR; return OK; -@@ -214,7 +214,6 @@ +@@ -214,7 +218,6 @@ struct msghdr msg; /* used to get client's packet info */ struct cmsghdr *cmsg; @@ -41,7 +46,7 @@ struct iovec iov; char cbuf[1024]; -@@ -284,11 +283,12 @@ +@@ -284,11 +287,12 @@ cmsg != NULL && cmsg->cmsg_len >= sizeof(*cmsg); cmsg = CMSG_NXTHDR(&msg, cmsg)) { diff --git a/ftp/atftp/files/patch-tftpd.c b/ftp/atftp/files/patch-tftpd.c index 00d8c2a5768..b9b3f4f8a0c 100644 --- a/ftp/atftp/files/patch-tftpd.c +++ b/ftp/atftp/files/patch-tftpd.c @@ -1,5 +1,5 @@ ---- tftpd.c.orig 2010-10-04 18:26:05.000000000 +0800 -+++ tftpd.c 2010-10-04 18:30:20.000000000 +0800 +--- tftpd.c.orig 2010-10-11 11:30:50.000000000 +0800 ++++ tftpd.c 2010-10-11 11:31:42.000000000 +0800 @@ -60,6 +60,9 @@ char directory[MAXLEN] = "/tftpboot/"; int retry_timeout = S_TIMEOUT; @@ -57,8 +57,13 @@ } #ifdef RATE_CONTROL -@@ -466,7 +478,7 @@ +@@ -463,10 +475,12 @@ + exit(1); + } + new->client_info->done = 0; ++ new->client_info->bytes_sent = 0; new->client_info->next = NULL; ++ new->client_info->last_ack = -1; /* Start a new server thread. */ - if (pthread_create(&new->tid, NULL, tftpd_receive_request, @@ -66,7 +71,7 @@ (void *)new) != 0) { logger(LOG_ERR, "Failed to start new thread"); -@@ -567,7 +579,8 @@ +@@ -567,7 +581,8 @@ /* Detach ourself. That way the main thread does not have to * wait for us with pthread_join. */ @@ -76,7 +81,7 @@ /* Read the first packet from stdin. */ data_size = data->data_buffer_size; -@@ -615,7 +628,25 @@ +@@ -615,7 +630,25 @@ data->sockfd = socket(PF_INET, SOCK_DGRAM, 0); to.sin_family = AF_INET; to.sin_port = 0; @@ -99,11 +104,34 @@ + logger(LOG_INFO, "socket may listen on any address, including broadcast"); + } + -+ if (data->sockfd != -1) ++ if (data->sockfd >= 0) { /* bind the socket to the interface */ if (bind(data->sockfd, (struct sockaddr *)&to, len) == -1) -@@ -732,8 +763,8 @@ +@@ -630,17 +663,14 @@ + logger(LOG_ERR, "getsockname: %s", strerror(errno)); + retval = ABORT; + } +- /* connect the socket, faster for kernel operation */ +- if (connect(data->sockfd, +- (struct sockaddr *)&data->client_info->client, +- sizeof(data->client_info->client)) == -1) +- { +- logger(LOG_ERR, "connect: %s", strerror(errno)); +- retval = ABORT; +- } + logger(LOG_DEBUG, "Creating new socket: %s:%d", + inet_ntoa(to.sin_addr), ntohs(to.sin_port)); + ++ /* save the dest ip address to bind multicast to correct ++ * interface ++ */ ++ data->mcastaddr.imr_interface.s_addr = to.sin_addr.s_addr; ++ + /* read options from request */ + opt_parse_request(data->data_buffer, data_size, + data->tftp_options); +@@ -732,8 +762,8 @@ tftpd_clientlist_free(data); /* free the thread structure */ @@ -114,7 +142,7 @@ logger(LOG_INFO, "Server thread exiting"); pthread_exit(NULL); } -@@ -811,6 +842,7 @@ +@@ -811,6 +841,7 @@ { "no-multicast", 0, NULL, 'M' }, { "logfile", 1, NULL, 'L' }, { "pidfile", 1, NULL, 'I'}, @@ -122,7 +150,7 @@ { "daemon", 0, NULL, 'D' }, { "no-fork", 0, NULL, 'N'}, { "user", 1, NULL, 'U'}, -@@ -888,6 +920,9 @@ +@@ -888,6 +919,9 @@ case 'I': pidfile = strdup(optarg); break; @@ -132,7 +160,7 @@ case 'D': tftpd_daemon = 1; break; -@@ -1015,6 +1050,10 @@ +@@ -1015,6 +1049,10 @@ logger(LOG_INFO, " log file: %s", (log_file==NULL) ? "syslog":log_file); if (pidfile) logger(LOG_INFO, " pid file: %s", pidfile); @@ -143,7 +171,7 @@ if (tftpd_daemon == 1) logger(LOG_INFO, " server timeout: Not used"); else -@@ -1111,11 +1150,12 @@ +@@ -1111,11 +1149,12 @@ " output messages\n" " --trace : log all sent and received packets\n" " --no-timeout : disable 'timeout' from RFC2349\n" diff --git a/ftp/atftp/files/patch-tftpd.h b/ftp/atftp/files/patch-tftpd.h new file mode 100644 index 00000000000..49b9794f301 --- /dev/null +++ b/ftp/atftp/files/patch-tftpd.h @@ -0,0 +1,14 @@ +--- tftpd.h.orig 2010-10-11 11:33:53.000000000 +0800 ++++ tftpd.h 2010-10-11 11:34:33.000000000 +0800 +@@ -71,6 +71,11 @@ + struct client_info { + struct sockaddr_in client; + int done; /* that client as receive it's file */ ++ int bytes_sent; ++ int number_of_timeout; /* number of timeouts while sending to ++ * this client ++ */ ++ int last_ack; /* last ACK received from this client */ + struct client_info *next; + }; + diff --git a/ftp/atftp/files/patch-tftpd_file.c b/ftp/atftp/files/patch-tftpd_file.c index e11ad6aac6b..7f81c6935a4 100644 --- a/ftp/atftp/files/patch-tftpd_file.c +++ b/ftp/atftp/files/patch-tftpd_file.c @@ -1,6 +1,43 @@ ---- tftpd_file.c.orig 2010-10-04 18:33:31.000000000 +0800 -+++ tftpd_file.c 2010-10-04 18:37:08.000000000 +0800 -@@ -240,9 +240,13 @@ +--- tftpd_file.c.orig 2004-02-18 10:21:47.000000000 +0800 ++++ tftpd_file.c 2010-10-11 13:22:54.000000000 +0800 +@@ -89,6 +89,28 @@ + return OK; + } + ++int opt_same_file(struct tftp_opt *opt1, struct tftp_opt *opt2) ++{ ++ if ((strncmp(opt1->option, "filename", OPT_SIZE) == 0) && ++ (strncmp(opt2->option, "filename", OPT_SIZE) == 0)) ++ { ++ char tofilename[MAXLEN]; ++ char fromfilename[MAXLEN]; ++ struct stat tostat; ++ struct stat fromstat; ++ ++ Strncpy(tofilename, opt1->value, MAXLEN); ++ tftpd_rules_check(tofilename); ++ Strncpy(fromfilename, opt2->value, MAXLEN); ++ tftpd_rules_check(fromfilename); ++ if (stat(tofilename, &tostat) || stat(fromfilename, &fromstat)) ++ return 0; ++ ++ return (tostat.st_ino == fromstat.st_ino); ++ } ++ return 0; ++} ++ + /* + * Receive a file. It is implemented as a state machine using a while loop + * and a switch statement. Function flow is as follow: +@@ -117,7 +139,6 @@ + char filename[MAXLEN]; + char string[MAXLEN]; + int timeout = data->timeout; +- int number_of_timeout = 0; + int all_blocks_received = 0; /* temporary kludge */ + int convert = 0; /* if true, do netascii convertion */ + +@@ -240,9 +261,13 @@ break; case S_SEND_ACK: timeout_state = state; @@ -8,30 +45,163 @@ - if (data->trace) - logger(LOG_DEBUG, "sent ACK <block: %d>", block_number); + result = tftp_send_ack(sockfd, sa, block_number); -+ if (result == OK) -+ { ++ if (result == OK) ++ { + if (data->trace) + logger(LOG_DEBUG, "sent ACK <block: %d>", -+ block_number); ++ block_number); + } if (all_blocks_received) state = S_END; else -@@ -660,8 +664,12 @@ - data->mc_port, 1); +@@ -265,8 +290,8 @@ + switch (result) + { + case GET_TIMEOUT: +- number_of_timeout++; +- if (number_of_timeout > NB_OF_RETRY) ++ data->client_info->number_of_timeout++; ++ if (data->client_info->number_of_timeout > NB_OF_RETRY) + { + logger(LOG_INFO, "client (%s) not responding", + inet_ntoa(data->client_info->client.sin_addr)); +@@ -322,7 +347,7 @@ + else + logger(LOG_WARNING, "source port mismatch, check bypassed"); + } +- number_of_timeout = 0; ++ data->client_info->number_of_timeout = 0; + state = S_DATA_RECEIVED; + break; + case GET_DISCARD: +@@ -413,13 +438,13 @@ + char filename[MAXLEN]; + char string[MAXLEN]; + int timeout = data->timeout; +- int number_of_timeout = 0; + int mcast_switch = data->mcast_switch_client; + struct stat file_stat; + int convert = 0; /* if true, do netascii conversion */ + struct thread_data *thread = NULL; /* used when looking for a multicast + thread */ + int multicast = 0; /* set to 1 if multicast */ ++ time_t last_send_time = -1; + + struct client_info *client_info = data->client_info; + struct client_info *client_old = NULL; +@@ -428,6 +453,8 @@ + int prev_block_number = 0; /* needed to support netascii convertion */ + int prev_file_pos = 0; + int temp = 0; ++ int total_bytes_sent = 0; ++ int clients_served = 0; + + /* look for mode option */ + if (strcasecmp(data->tftp_options[OPT_MODE].value, "netascii") == 0) +@@ -535,6 +562,34 @@ + return ERR; + } + ++ /* make sure that the oack packet will fit in the buffer */ ++ int oacklen = 2; ++ int i; ++ for (i = 2; i < OPT_NUMBER; i++) ++ { ++ if (data->tftp_options[i].enabled && ++ data->tftp_options[i].specified) ++ { ++ oacklen += strlen(data->tftp_options[i].option); ++ oacklen++; ++ oacklen += strlen(data->tftp_options[i].value); ++ oacklen++; ++ } ++ } ++ ++ if (oacklen > result) ++ { ++ logger(LOG_NOTICE, "OACK will not fit in buffer of size %d.", ++ " Options rejected.", result); ++ tftp_send_error(sockfd, sa, EOPTNEG, data->data_buffer, ++ data->data_buffer_size); ++ if (data->trace) ++ logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", ++ EOPTNEG, tftp_errmsg[EOPTNEG]); ++ fclose(fp); ++ return ERR; ++ } ++ + data->data_buffer_size = result + 4; + data->data_buffer = realloc(data->data_buffer, data->data_buffer_size); + +@@ -559,11 +614,16 @@ + logger(LOG_INFO, "blksize option -> %d", result); + } + ++ /* multicast option */ ++ if (data->tftp_options[OPT_MULTICAST].specified && ++ data->tftp_options[OPT_MULTICAST].enabled && !convert) ++ { + /* Verify that the file can be sent in 2^16 block of BLKSIZE octets */ + if ((file_stat.st_size / (data->data_buffer_size - 4)) > 65535) + { + tftp_send_error(sockfd, sa, EUNDEF, data->data_buffer, data->data_buffer_size); +- logger(LOG_NOTICE, "Requested file to big, increase BLKSIZE"); ++ logger(LOG_NOTICE, "Requested file too big, increase BLKSIZE, ", ++ "cannot rollover in multicast transfer"); + if (data->trace) + logger(LOG_DEBUG, "sent ERROR <code: %d, msg: %s>", EUNDEF, + tftp_errmsg[EUNDEF]); +@@ -571,10 +631,6 @@ + return ERR; + } + +- /* multicast option */ +- if (data->tftp_options[OPT_MULTICAST].specified && +- data->tftp_options[OPT_MULTICAST].enabled && !convert) +- { + /* + * Find a server with the same options to give up the client. + */ +@@ -649,10 +705,16 @@ + /* initialise multicast address structure */ + data->mcastaddr.imr_multiaddr.s_addr = + data->sa_mcast.sin_addr.s_addr; +- data->mcastaddr.imr_interface.s_addr = htonl(INADDR_ANY); ++ + setsockopt(data->sockfd, IPPROTO_IP, IP_MULTICAST_TTL, + &data->mcast_ttl, sizeof(data->mcast_ttl)); + ++ logger(LOG_DEBUG, "Multicast interface = %s", ++ inet_ntoa(data->mcastaddr.imr_interface)); ++ setsockopt(data->sockfd, IPPROTO_IP, IP_MULTICAST_IF, ++ &(data->mcastaddr.imr_interface.s_addr), ++ sizeof(data->mcastaddr.imr_interface.s_addr)); ++ + /* set options data for OACK */ + opt_set_multicast(data->tftp_options, data->mc_addr, + data->mc_port, 1); +@@ -661,7 +723,7 @@ /* the socket must be unconnected for multicast */ -+#ifdef __linux__ sa->sin_family = AF_UNSPEC; - connect(sockfd, (struct sockaddr *)sa, sizeof(sa)); -+#else -+ sa->sin_family = AF_INET; -+#endif + connect(sockfd, (struct sockaddr *)sa, sizeof(*sa)); /* set multicast flag */ multicast = 1; -@@ -706,10 +714,14 @@ +@@ -669,6 +731,11 @@ + tftpd_clientlist_ready(data); + } + } ++ if ((file_stat.st_size / (data->data_buffer_size - 4)) > 65535) ++ { ++ logger(LOG_NOTICE, "Requested file bigger than tftp is designed to ", ++ "handle, attempting rollover, but not officially in a tftp spec"); ++ } + + /* copy options to local structure, used when falling back a client to slave */ + memcpy(options, data->tftp_options, sizeof(options)); +@@ -706,10 +773,14 @@ case S_SEND_OACK: timeout_state = state; opt_options_to_string(data->tftp_options, string, MAXLEN); @@ -43,14 +213,14 @@ + data->data_buffer, + data->data_buffer_size); + if (result == OK) -+ { ++ { + if (data->trace) -+ logger(LOG_DEBUG, "sent OACK <%s>", string); ++ logger(LOG_DEBUG, "sent OACK <%s>", string); + } state = S_WAIT_PACKET; break; case S_SEND_DATA: -@@ -725,19 +737,25 @@ +@@ -725,18 +796,24 @@ if (multicast) { @@ -60,6 +230,7 @@ + result = tftp_send_data(sockfd, &data->sa_mcast, + block_number + 1, data_size, + data->data_buffer); ++ client_info->bytes_sent += data_size-4; } else { @@ -67,21 +238,149 @@ - data_size, data->data_buffer); + result = tftp_send_data(sockfd, sa, block_number + 1, + data_size, data->data_buffer); -+ } + } +- if (data->trace) +- logger(LOG_DEBUG, "sent DATA <block: %d, size %d>", +- block_number + 1, data_size - 4); + -+ if (result == ERR) -+ state = S_ABORT; -+ else ++ if (result == OK) + { + if (data->trace) + logger(LOG_DEBUG, "sent DATA <block: %d, size %d>", + block_number + 1, data_size - 4); -+ state = S_WAIT_PACKET; - } -- if (data->trace) -- logger(LOG_DEBUG, "sent DATA <block: %d, size %d>", -- block_number + 1, data_size - 4); -- state = S_WAIT_PACKET; ++ } ++ time(&last_send_time); + state = S_WAIT_PACKET; break; case S_WAIT_PACKET: - data_size = data->data_buffer_size; +@@ -746,12 +823,14 @@ + switch (result) + { + case GET_TIMEOUT: +- number_of_timeout++; ++ client_info->number_of_timeout++; + +- if (number_of_timeout > NB_OF_RETRY) ++ if (client_info->number_of_timeout > NB_OF_RETRY) + { +- logger(LOG_INFO, "client (%s) not responding", +- inet_ntoa(client_info->client.sin_addr)); ++ logger(LOG_INFO, "client (%s) not responding.", ++ " state=%d block_number=%d", ++ inet_ntoa(client_info->client.sin_addr), ++ timeout_state,block_number); + state = S_END; + } + else +@@ -779,7 +858,8 @@ + /* Proceed normally with the next client, + going to OACK state */ + logger(LOG_INFO, +- "Serving next client: %s:%d", ++ "Serving next client after timeout: state=%d, block_number=%d: %s:%d", ++ timeout_state,block_number, + inet_ntoa(client_info->client.sin_addr), + ntohs(client_info->client.sin_port)); + sa = &client_info->client; +@@ -796,7 +876,9 @@ + break; + } + } +- logger(LOG_WARNING, "timeout: retrying..."); ++ logger(LOG_WARNING, "timeout: retrying... state=%d,", ++ " block_number=%d", timeout_state, ++ block_number); + state = timeout_state; + } + break; +@@ -811,7 +893,13 @@ + * If this is an ACK for the last block, mark this client as + * done + */ +- if ((last_block != -1) && (block_number > last_block)) ++ logger(LOG_DEBUG, ++ "received ACK <block: %d> from wrong client: %s:%d", ++ ntohs(tftphdr->th_block), ++ inet_ntoa(from.sin_addr), ++ ntohs(from.sin_port)); ++ ++ if ((last_block != -1) && (ntohs(tftphdr->th_block) > last_block)) + { + if (tftpd_clientlist_done(data, NULL, &from) == 1) + logger(LOG_DEBUG, "client done <%s>", +@@ -851,8 +939,33 @@ + } + } + /* The ACK is from the current client */ +- number_of_timeout = 0; +- block_number = ntohs(tftphdr->th_block); ++ client_info->number_of_timeout = 0; ++ int ACK_block_number = ntohs(tftphdr->th_block); ++ if (ACK_block_number == client_info->last_ack) ++ { ++ /* duplicate ACK, ignore */ ++ time_t now; ++ time(&now); ++ /* if a timeout has occurred, resend last block */ ++ if ((now-last_send_time) > timeout) ++ { ++ state = S_SEND_DATA; ++ logger(LOG_DEBUG, "Duplicate ACK packet discarded <%d>, timeout. Resend last block.", ACK_block_number); ++ } ++ else ++ { ++ logger(LOG_DEBUG, "Duplicate ACK packet discarded <%d>.", ACK_block_number); ++ } ++ break; ++ } ++ ++ client_info->last_ack = ACK_block_number; ++ ++ if (block_number < 65534) ++ block_number = ACK_block_number; ++ else ++ block_number++; ++ + if (data->trace) + logger(LOG_DEBUG, "received ACK <block: %d>", + block_number); +@@ -932,10 +1045,16 @@ + } + break; + case S_END: ++ total_bytes_sent += client_info->bytes_sent; + if (multicast) + { + logger(LOG_DEBUG, "End of multicast transfer"); ++ logger(LOG_INFO, ++ "Bytes sent while this client was master: %d", ++ client_info->bytes_sent); ++ + /* mark the current client done */ ++ clients_served++; + tftpd_clientlist_done(data, client_info, NULL); + /* Look if there is another client to serve. We lock list of + client to make sure no other thread try to add clients in +@@ -948,13 +1067,20 @@ + ntohs(client_info->client.sin_port)); + /* client is a new client structure */ + sa = &client_info->client; +- /* nedd to send an oack to that client */ ++ /* send an oack to that client */ + state = S_SEND_OACK; + fseek(fp, 0, SEEK_SET); + } + else + { +- logger(LOG_INFO, "No more client, end of tranfers"); ++ int fs = file_stat.st_size; ++ int blksze = (data->data_buffer_size - 4); ++ int ttlblks = fs / blksze; ++ int blksretry = (total_bytes_sent-file_stat.st_size) / blksze; ++ logger(LOG_INFO, "No more client, end of tranfers. %d clients served", clients_served); ++ logger(LOG_INFO, "Bytes saved over unicast: %ld", (clients_served*file_stat.st_size) - total_bytes_sent); ++ logger(LOG_INFO, "File size: %d, total data bytes sent %d", file_stat.st_size, total_bytes_sent); ++ logger(LOG_INFO, "Block re-sent: %d of %d = %f percent", blksretry, ttlblks, ((float)blksretry/(float)ttlblks) * 100); + fclose(fp); + return OK; + } diff --git a/ftp/atftp/files/patch-tftpd_list.c b/ftp/atftp/files/patch-tftpd_list.c index 1a087d64a2d..42ffd38fe0c 100644 --- a/ftp/atftp/files/patch-tftpd_list.c +++ b/ftp/atftp/files/patch-tftpd_list.c @@ -1,11 +1,42 @@ ---- tftpd_list.c.orig 2010-10-05 13:11:12.000000000 +0800 -+++ tftpd_list.c 2010-10-05 13:18:09.000000000 +0800 -@@ -149,7 +149,7 @@ +--- tftpd_list.c.orig 2010-10-11 12:44:39.000000000 +0800 ++++ tftpd_list.c 2010-10-11 12:44:34.000000000 +0800 +@@ -137,23 +137,17 @@ + struct thread_data *data, + struct client_info *client) + { +- struct thread_data *current = thread_data; /* head of the list */ ++ struct thread_data *current; + struct tftp_opt *tftp_options = data->tftp_options; + struct client_info *tmp; +- char options[MAXLEN]; +- char string[MAXLEN]; +- char *index; +- int len; - opt_request_to_string(tftp_options, options, MAXLEN); - index = strstr(options, "multicast"); -- len = (int)index - (int)options; -+ len = strlen(options) - strlen(index); + *thread = NULL; +- opt_request_to_string(tftp_options, options, MAXLEN); +- index = strstr(options, "multicast"); +- len = (int)index - (int)options; +- /* lock the whole list before walking it */ pthread_mutex_lock(&thread_list_mutex); + ++ current = thread_data; /* head of the list */ ++ + while (current) + { + if (current != data) +@@ -162,9 +156,9 @@ + pthread_mutex_lock(¤t->client_mutex); + if (current->client_ready == 1) + { +- opt_request_to_string(current->tftp_options, string, MAXLEN); +- /* must have exact same option string */ +- if (strncmp(string, options, len) == 0) ++ /* must have exact same mode and refer to the same file */ ++ if (opt_same_file(current->tftp_options,tftp_options) && ++ opt_equal(&(current->tftp_options[OPT_MODE]), &(tftp_options[OPT_MODE]))) + { + *thread = current; + /* insert the new client at the end. If the client is already diff --git a/ftp/atftp/files/patch-tftpd_mtftp.c b/ftp/atftp/files/patch-tftpd_mtftp.c new file mode 100644 index 00000000000..29dc26de7c0 --- /dev/null +++ b/ftp/atftp/files/patch-tftpd_mtftp.c @@ -0,0 +1,40 @@ +--- tftpd_mtftp.c.orig 2010-10-11 12:45:36.000000000 +0800 ++++ tftpd_mtftp.c 2010-10-11 12:46:29.000000000 +0800 +@@ -369,6 +369,13 @@ + logger(LOG_ERR, "mtftp: can't open socket"); + pthread_exit(NULL); + } ++ ++ int one = 1; ++ if (setsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR, &one, sizeof(one)) != 0) ++ { ++ logger(LOG_WARNING, "Failed to set socket option: %s", ++ strerror(errno)); ++ } + /* bind the socket to the tftp port */ + if (bind(sockfd, (struct sockaddr*)&sa, sizeof(sa)) < 0) + { +@@ -389,7 +396,8 @@ + that file name */ + memset(&sa, 0, sizeof(sa)); /* this will hold the client info */ + data_size = data->data_buffer_size; +- retval = tftp_get_packet(sockfd, -1, NULL, &sa, NULL, NULL, ++ struct sockaddr_in toaddr; ++ retval = tftp_get_packet(sockfd, -1, NULL, &sa, NULL, &toaddr, + data->timeout, + &data_size, data->data_buffer); + +@@ -472,8 +480,11 @@ + getsockname(thread->sockfd, (struct sockaddr *)&(sa), &len); + + /* configure multicast socket */ +- thread->mcastaddr.imr_multiaddr.s_addr = thread->sa_mcast.sin_addr.s_addr; +- thread->mcastaddr.imr_interface.s_addr = htonl(INADDR_ANY); ++ thread->mcastaddr.imr_interface.s_addr = toaddr.sin_addr.s_addr; ++ setsockopt(thread->sockfd, IPPROTO_IP, IP_MULTICAST_IF, ++ &(thread->mcastaddr.imr_interface.s_addr), ++ sizeof(thread->mcastaddr.imr_interface.s_addr)); ++ + setsockopt(thread->sockfd, IPPROTO_IP, IP_MULTICAST_TTL, + &data->mcast_ttl, sizeof(data->mcast_ttl)); + |