[PATCH] tftp(d): fix wrong logic in get/put feature preprocessor work + some error handling enhancements
Benjamin Cama
benoar at free.fr
Thu Feb 25 20:50:22 UTC 2010
Ping ?
Is no one interested in committing this fix ? Is there any problem in
the patch ?
Regards,
benjamin
Le lundi 15 février 2010 à 05:23 +0100, Benjamin Cama a écrit :
> Hi,
>
> I tried to build tftpd applet with only "get" opcode support, but it
> didn't work (no data is transfered). I also got some accidental file
> overwriting problem which seems to be due to this problem.
>
> Basically, the logic behind the get/put opcode feature macros is
> brain-dead. Furthermore, there is a confusion in the code between the
> actual get/put opcode and the meaning CMD_GET() and CMD_PUT() are
> assigned in tftp_protocol(), which is, get is to receive data (so it's
> get opcode for tftp, but put for tftpd) and put is to send it (same for
> tftp, but means get for tftpd). I think it would be better to name them
> XXX_RECV/XXX_SEND, but I leave that to someone else. It would make the
> code far clearer.
>
> So, I removed almost all the macro conditionnal stuff at the top, and
> also fixed another bug in the middle (the test for the opcode against
> TFTP_RRQ/WRQ was inverted). The previous logic also assumed every opcode
> is what was enabled if there's only one opcode selected (so, a get
> becomes a put if get support has not been enabled ...). I didn't like it
> and find the "general case everywhere" approach better. (yes, you loose
> some optimizations) This "general case" is needed anyway either when you
> select at least the two applets (tftp and tftpd) or when you choose the
> two opcodes.
>
> I also separated one error case (which opcode is supported) and added
> another error message saying we don't handle anything else than octet
> mode (yes, I got caught by that for some time).
>
> Tested working with different features enabled on 1.15.3, patch against
> git master following.
>
> Regards,
> benjamin
>
> Signed-off-by: Benjamin Cama <benoar at free.fr>
> ---
> diff --git a/networking/tftp.c b/networking/tftp.c
> index 0e5b48d..6629995 100644
> --- a/networking/tftp.c
> +++ b/networking/tftp.c
> @@ -60,19 +60,14 @@ enum {
> TFTPD_OPT_u = (1 << 10) * ENABLE_TFTPD,
> };
>
> -#if ENABLE_FEATURE_TFTP_GET && !ENABLE_FEATURE_TFTP_PUT
> -#define IF_GETPUT(...)
> -#define CMD_GET(cmd) 1
> -#define CMD_PUT(cmd) 0
> -#elif !ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
> -#define IF_GETPUT(...)
> -#define CMD_GET(cmd) 0
> -#define CMD_PUT(cmd) 1
> -#else
> +#if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
> #define IF_GETPUT(...) __VA_ARGS__
> +#else
> +#define IF_GETPUT(...)
> +#endif
> +
> #define CMD_GET(cmd) ((cmd) & TFTP_OPT_GET)
> #define CMD_PUT(cmd) ((cmd) & TFTP_OPT_PUT)
> -#endif
> /* NB: in the code below
> * CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive
> */
> @@ -667,7 +662,7 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
> # endif
> int result;
> int port;
> - IF_GETPUT(int opt;)
> + int opt;
>
> INIT_G();
>
> @@ -675,7 +670,7 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
> opt_complementary = "" IF_FEATURE_TFTP_GET("g:") IF_FEATURE_TFTP_PUT("p:")
> IF_GETPUT("g--p:p--g:");
>
> - IF_GETPUT(opt =) getopt32(argv,
> + opt = getopt32(argv,
> IF_FEATURE_TFTP_GET("g") IF_FEATURE_TFTP_PUT("p")
> "l:r:" IF_FEATURE_TFTP_BLOCKSIZE("b:"),
> &local_file, &remote_file
> @@ -774,13 +769,16 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
> opcode = ntohs(*(uint16_t*)block_buf);
> if (result < 4 || result >= sizeof(block_buf)
> || block_buf[result-1] != '\0'
> - || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
> - IF_GETPUT(&&)
> - IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
> - )
> ) {
> goto err;
> }
> + if (IF_FEATURE_TFTP_GET(opcode != TFTP_RRQ) /* if not download */
> + IF_GETPUT(&&)
> + IF_FEATURE_TFTP_PUT(opcode != TFTP_WRQ) /* if not upload */
> + ) {
> + error_msg = "unsupported opcode";
> + goto err;
> + }
> local_file = block_buf + 2;
> if (local_file[0] == '.' || strstr(local_file, "/.")) {
> error_msg = "dot in file name";
> @@ -788,6 +786,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
> }
> mode = local_file + strlen(local_file) + 1;
> if (mode >= block_buf + result || strcmp(mode, "octet") != 0) {
> + error_msg = "only octet mode is supported";
> goto err;
> }
> # if ENABLE_FEATURE_TFTP_BLOCKSIZE
> @@ -815,16 +814,26 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
> }
> # endif
>
> - if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
> +#if ENABLE_FEATURE_TFTP_PUT
> + if (opcode == TFTP_WRQ) {
> if (opt & TFTPD_OPT_r) {
> /* This would mean "disk full" - not true */
> /*error_pkt_reason = ERR_WRITE;*/
> error_msg = bb_msg_write_error;
> goto err;
> }
> - IF_GETPUT(option_mask32 |= TFTP_OPT_GET;) /* will receive file's data */
> - } else {
> - IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */
> + option_mask32 |= TFTP_OPT_GET; /* will receive file's data */
> + }
> + else
> +#endif
> +#if ENABLE_FEATURE_TFTP_GET
> + if (opcode == TFTP_RRQ) {
> + option_mask32 |= TFTP_OPT_PUT; /* will send file's data */
> + }
> + else
> +#endif
> + {
> + goto err;
> }
>
> /* NB: if error_pkt_str or error_pkt_reason is set up,
>
>
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
More information about the busybox
mailing list