From 8a2fd06c310befa753ab047b891e8b0ecc59eeb2 Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 6 Jun 2012 09:55:08 +0100 Subject: [PATCH 1/5] flexnbd: Add --bind to flexnbd read and flexnbd write --- src/control.c | 2 +- src/flexnbd.c | 36 +++++++++++++++++++++++++----------- src/options.h | 35 +++++++++++++++++++++++------------ src/params.h | 1 + src/readwrite.c | 18 +++++++++++++----- src/readwrite.h | 2 +- 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/control.c b/src/control.c index 41ffcd5..8a6e6a8 100644 --- a/src/control.c +++ b/src/control.c @@ -217,7 +217,7 @@ int control_mirror(struct control_params* client, int linesc, char** lines) return -1; } - fd = socket_connect(&connect_to.generic); + fd = socket_connect(&connect_to.generic, NULL); remote_size = socket_nbd_read_hello(fd); remote_size = remote_size; // shush compiler diff --git a/src/flexnbd.c b/src/flexnbd.c index 8580fde..ea580fd 100644 --- a/src/flexnbd.c +++ b/src/flexnbd.c @@ -111,6 +111,7 @@ void params_readwrite( struct mode_readwrite_params* out, char* s_ip_address, char* s_port, + char* s_bind_address, char* s_from, char* s_length_or_filename ) @@ -128,6 +129,9 @@ void params_readwrite( SERVER_ERROR("Couldn't parse connection address '%s'", s_ip_address); + if (s_bind_address != NULL && parse_ip_to_sockaddr(&out->connect_from.generic, s_bind_address) == 0) + SERVER_ERROR("Couldn't parse bind address '%s'", s_bind_address); + /* FIXME: duplicated from above */ out->connect_to.v4.sin_port = atoi(s_port); if (out->connect_to.v4.sin_port < 0 || out->connect_to.v4.sin_port > 65535) @@ -198,7 +202,7 @@ void read_serve_param( int c, char **ip_addr, char **ip_port, char **file, char } -void read_readwrite_param( int c, char **ip_addr, char **ip_port, char **from, char **size) +void read_readwrite_param( int c, char **ip_addr, char **ip_port, char **bind_addr, char **from, char **size) { switch(c){ case 'h': @@ -217,6 +221,9 @@ void read_readwrite_param( int c, char **ip_addr, char **ip_port, char **from, c case 'S': *size = optarg; break; + case 'b': + *bind_addr = optarg; + break; case 'd': set_debug(1); break; @@ -320,8 +327,9 @@ int mode_serve( int argc, char *argv[] ) int mode_read( int argc, char *argv[] ) { int c; - char *ip_addr = NULL; - char *ip_port = NULL; + char *ip_addr = NULL; + char *ip_port = NULL; + char *bind_addr = NULL; char *from = NULL; char *size = NULL; int err = 0; @@ -330,8 +338,11 @@ int mode_read( int argc, char *argv[] ) while (1){ c = getopt_long(argc, argv, read_short_options, read_options, NULL); - if ( c == -1 ) break; - read_readwrite_param( c, &ip_addr, &ip_port, &from, &size ); + + if ( c == -1 ) + break; + + read_readwrite_param( c, &ip_addr, &ip_port, &bind_addr, &from, &size ); } if ( NULL == ip_addr || NULL == ip_port ) { @@ -345,7 +356,7 @@ int mode_read( int argc, char *argv[] ) if ( err ) { exit_err( read_help_text ); } memset( &readwrite, 0, sizeof( readwrite ) ); - params_readwrite( 0, &readwrite, ip_addr, ip_port, from, size ); + params_readwrite( 0, &readwrite, ip_addr, ip_port, bind_addr, from, size ); do_read( &readwrite ); return 0; } @@ -353,8 +364,9 @@ int mode_read( int argc, char *argv[] ) int mode_write( int argc, char *argv[] ) { int c; - char *ip_addr = NULL; - char *ip_port = NULL; + char *ip_addr = NULL; + char *ip_port = NULL; + char *bind_addr = NULL; char *from = NULL; char *size = NULL; int err = 0; @@ -363,8 +375,10 @@ int mode_write( int argc, char *argv[] ) while (1){ c = getopt_long(argc, argv, write_short_options, write_options, NULL); - if ( c == -1 ) break; - read_readwrite_param( c, &ip_addr, &ip_port, &from, &size ); + if ( c == -1 ) + break; + + read_readwrite_param( c, &ip_addr, &ip_port, &bind_addr, &from, &size ); } if ( NULL == ip_addr || NULL == ip_port ) { @@ -378,7 +392,7 @@ int mode_write( int argc, char *argv[] ) if ( err ) { exit_err( write_help_text ); } memset( &readwrite, 0, sizeof( readwrite ) ); - params_readwrite( 1, &readwrite, ip_addr, ip_port, from, size ); + params_readwrite( 1, &readwrite, ip_addr, ip_port, bind_addr, from, size ); do_write( &readwrite ); return 0; } diff --git a/src/options.h b/src/options.h index f25752f..7dea799 100644 --- a/src/options.h +++ b/src/options.h @@ -3,6 +3,7 @@ #define OPT_HELP "help" #define OPT_ADDR "addr" +#define OPT_BIND "bind" #define OPT_PORT "port" #define OPT_FILE "file" #define OPT_SOCK "sock" @@ -34,6 +35,7 @@ #define GETOPT_SOCK GETOPT_ARG( OPT_SOCK, 's' ) #define GETOPT_FROM GETOPT_ARG( OPT_FROM, 'F' ) #define GETOPT_SIZE GETOPT_ARG( OPT_SIZE, 'S' ) +#define GETOPT_BIND GETOPT_ARG( OPT_BIND, 'b' ) #ifdef DEBUG # define OPT_DEBUG "debug" @@ -45,6 +47,12 @@ # define DEBUG_LINE "" #endif +#define HELP_LINE \ + "\t--" OPT_HELP ",-h \tThis text.\n" +#define SOCK_LINE \ + "\t--" OPT_SOCK ",-s \tPath to the control socket.\n" +#define BIND_LINE \ + "\t--" OPT_BIND ",-b \tBind the local socket to a particular IP address.\n" static struct option serve_options[] = { GETOPT_HELP, @@ -60,12 +68,12 @@ static char serve_short_options[] = "Dhl:p:f:s:"; static char serve_help_text[] = "Usage: flexnbd " CMD_SERVE " [*]\n\n" "Serve FILE from ADDR:PORT, with an optional control socket at SOCK.\n\n" - "\t--" OPT_HELP ",-h\tThis text.\n" + HELP_LINE "\t--" OPT_ADDR ",-l \tThe address to serve on.\n" "\t--" OPT_PORT ",-p \tThe port to serve on.\n" "\t--" OPT_FILE ",-f \tThe file to serve.\n" - "\t--" OPT_DENY ",-D\tDeny connections by default unless in ACL\n" - "\t--" OPT_SOCK ",-s \tPath to the control socket to open.\n" + "\t--" OPT_DENY ",-D\tDeny connections by default unless in ACL.\n" + SOCK_LINE DEBUG_LINE; static struct option read_options[] = { @@ -74,18 +82,20 @@ static struct option read_options[] = { GETOPT_PORT, GETOPT_FROM, GETOPT_SIZE, + GETOPT_BIND, GETOPT_DEBUG, {0} }; -static char read_short_options[] = "hl:p:F:S:"; +static char read_short_options[] = "hl:p:F:S:b:"; static char read_help_text[] = "Usage: flexnbd " CMD_READ " \n\n" "Read SIZE bytes from a server at ADDR:PORT to stdout, starting at OFFSET.\n\n" - "\t--" OPT_HELP ",-h\tThis text.\n" + HELP_LINE "\t--" OPT_ADDR ",-l \tThe address to read from.\n" "\t--" OPT_PORT ",-p \tThe port to read from.\n" "\t--" OPT_FROM ",-F \tByte offset to read from.\n" "\t--" OPT_SIZE ",-S \tBytes to read.\n" + BIND_LINE DEBUG_LINE; @@ -94,11 +104,12 @@ static char *write_short_options = read_short_options; static char write_help_text[] = "Usage: flexnbd " CMD_WRITE" \n\n" "Write SIZE bytes from stdin to a server at ADDR:PORT, starting at OFFSET.\n\n" - "\t--" OPT_HELP ",-h\tThis text.\n" + HELP_LINE "\t--" OPT_ADDR ",-l \tThe address to write to.\n" "\t--" OPT_PORT ",-p \tThe port to write to.\n" "\t--" OPT_FROM ",-F \tByte offset to write from.\n" "\t--" OPT_SIZE ",-S \tBytes to write.\n" + BIND_LINE DEBUG_LINE; struct option acl_options[] = { @@ -111,8 +122,8 @@ static char acl_short_options[] = "hs:"; static char acl_help_text[] = "Usage: flexnbd " CMD_ACL " [+]\n\n" "Set the access control list for a server with control socket SOCK.\n\n" - "\t--" OPT_HELP ",-h\tThis text.\n" - "\t--" OPT_SOCK ",-s \tPath to the control socket.\n" + HELP_LINE + SOCK_LINE DEBUG_LINE; struct option mirror_options[] = { @@ -127,8 +138,7 @@ static char mirror_short_options[] = "hs:l:p:"; static char mirror_help_text[] = "Usage: flexnbd " CMD_MIRROR " \n\n" "Start mirroring from the server with control socket SOCK to one at ADDR:PORT.\n\n" - "\t--" OPT_HELP ",-h\tThis text.\n" - "\t--" OPT_SOCK ",-s \tPath to the control socket.\n" + HELP_LINE "\t--" OPT_ADDR ",-l \tThe address to mirror to.\n" "\t--" OPT_PORT ",-p \tThe port to mirror to.\n" DEBUG_LINE; @@ -144,8 +154,8 @@ static char status_short_options[] = "hs:"; static char status_help_text[] = "Usage: flexnbd " CMD_STATUS " \n\n" "Get the status for a server with control socket SOCK.\n\n" - "\t--" OPT_HELP ",-h\tThis text.\n" - "\t--" OPT_SOCK ",-s \tPath to the control socket.\n" + HELP_LINE + SOCK_LINE DEBUG_LINE; static char help_help_text[] = @@ -159,3 +169,4 @@ static char help_help_text[] = "\tflexnbd status\n" "\tflexnbd help\n\n" "See flexnbd help for further info\n"; + diff --git a/src/params.h b/src/params.h index a550817..a2f5552 100644 --- a/src/params.h +++ b/src/params.h @@ -82,6 +82,7 @@ struct mode_serve_params { struct mode_readwrite_params { union mysockaddr connect_to; + union mysockaddr connect_from; off64_t from; off64_t len; int data_fd; diff --git a/src/readwrite.c b/src/readwrite.c index 36418f6..5b2e391 100644 --- a/src/readwrite.c +++ b/src/readwrite.c @@ -7,12 +7,20 @@ #include #include -int socket_connect(struct sockaddr* to) +int socket_connect(struct sockaddr* to, struct sockaddr* from) { int fd = socket(to->sa_family == AF_INET ? PF_INET : PF_INET6, SOCK_STREAM, 0); SERVER_ERROR_ON_FAILURE(fd, "Couldn't create client socket"); - SERVER_ERROR_ON_FAILURE(connect(fd, to, sizeof(struct sockaddr_in6)), - "connect failed"); + + if (NULL != from) + SERVER_ERROR_ON_FAILURE( + bind(fd, from, sizeof(struct sockaddr_in6)), + "bind() failed" + ); + + SERVER_ERROR_ON_FAILURE( + connect(fd, to, sizeof(struct sockaddr_in6)),"connect failed" + ); return fd; } @@ -106,7 +114,7 @@ void socket_nbd_write(int fd, off64_t from, int len, int in_fd, void* in_buf) void do_read(struct mode_readwrite_params* params) { - params->client = socket_connect(¶ms->connect_to.generic); + params->client = socket_connect(¶ms->connect_to.generic, ¶ms->connect_from.generic); CHECK_RANGE("read"); socket_nbd_read(params->client, params->from, params->len, params->data_fd, NULL); @@ -115,7 +123,7 @@ void do_read(struct mode_readwrite_params* params) void do_write(struct mode_readwrite_params* params) { - params->client = socket_connect(¶ms->connect_to.generic); + params->client = socket_connect(¶ms->connect_to.generic, ¶ms->connect_from.generic); CHECK_RANGE("write"); socket_nbd_write(params->client, params->from, params->len, params->data_fd, NULL); diff --git a/src/readwrite.h b/src/readwrite.h index 6b0d3c4..2dabbfc 100644 --- a/src/readwrite.h +++ b/src/readwrite.h @@ -2,7 +2,7 @@ #define __READWRITE_H -int socket_connect(struct sockaddr* to); +int socket_connect(struct sockaddr* to, struct sockaddr* from); off64_t socket_nbd_read_hello(int fd); void socket_nbd_read(int fd, off64_t from, int len, int out_fd, void* out_buf); void socket_nbd_write(int fd, off64_t from, int len, int out_fd, void* out_buf); From 3e0628e2fce0c01b1119e4fa21dd4caae66432a9 Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 6 Jun 2012 09:55:47 +0100 Subject: [PATCH 2/5] flexnbd: Re-add --sock to flexnbd mirror --- src/options.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/options.h b/src/options.h index 7dea799..ad417cc 100644 --- a/src/options.h +++ b/src/options.h @@ -141,6 +141,7 @@ static char mirror_help_text[] = HELP_LINE "\t--" OPT_ADDR ",-l \tThe address to mirror to.\n" "\t--" OPT_PORT ",-p \tThe port to mirror to.\n" + SOCK_LINE DEBUG_LINE; From 15513c03dfec0499c2986cdf34940d5a4f0d517b Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 6 Jun 2012 10:05:12 +0100 Subject: [PATCH 3/5] Remove a duplicated line due to the last merge --- src/options.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/options.h b/src/options.h index e9fe3dc..3cb80f6 100644 --- a/src/options.h +++ b/src/options.h @@ -39,9 +39,6 @@ #define GETOPT_SIZE GETOPT_ARG( OPT_SIZE, 'S' ) #define GETOPT_BIND GETOPT_ARG( OPT_BIND, 'b' ) -#define HELP_LINE "\t--" OPT_HELP ",-h\t\tThis text.\n" - - #ifdef DEBUG # define OPT_VERBOSE "verbose" # define SOPT_VERBOSE "v" From f4a403842dbd6ba1ebb70d78e3a5b9c203a5a601 Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 6 Jun 2012 12:07:40 +0100 Subject: [PATCH 4/5] flexnbd: Fix specifying -d as --default-deny on the command line --- src/options.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.h b/src/options.h index 3cb80f6..0349d50 100644 --- a/src/options.h +++ b/src/options.h @@ -77,7 +77,7 @@ static char serve_help_text[] = "\t--" OPT_ADDR ",-l \tThe address to serve on.\n" "\t--" OPT_PORT ",-p \tThe port to serve on.\n" "\t--" OPT_FILE ",-f \tThe file to serve.\n" - "\t--" OPT_DENY ",-D\tDeny connections by default unless in ACL.\n" + "\t--" OPT_DENY ",-d\tDeny connections by default unless in ACL.\n" SOCK_LINE VERBOSE_LINE; From 7544a59da190f71edcfcca80b71e9cdc8f548052 Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 6 Jun 2012 12:35:01 +0100 Subject: [PATCH 5/5] mirror: Add --bind to our mirror mode. Mirroring doesn't actually work yet, of course. --- src/control.c | 28 ++++++++++++++++++++++------ src/flexnbd.c | 15 ++++++++++----- src/options.h | 4 +++- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/control.c b/src/control.c index 8a6e6a8..9d9c5fa 100644 --- a/src/control.c +++ b/src/control.c @@ -173,14 +173,17 @@ int control_mirror(struct control_params* client, int linesc, char** lines) int fd, map_fd; struct mirror_status *mirror; union mysockaddr connect_to; + union mysockaddr connect_from; + int use_connect_from = 0; uint64_t max_bytes_per_second; int action_at_finish; + if (linesc < 2) { write_socket("1: mirror takes at least two parameters"); return -1; } - + if (parse_ip_to_sockaddr(&connect_to.generic, lines[0]) == 0) { write_socket("1: bad IP address"); return -1; @@ -192,14 +195,22 @@ int control_mirror(struct control_params* client, int linesc, char** lines) return -1; } connect_to.v4.sin_port = htobe16(connect_to.v4.sin_port); - - max_bytes_per_second = 0; + if (linesc > 2) { + if (parse_ip_to_sockaddr(&connect_from.generic, lines[2]) == 0) { + write_socket("1: bad bind address"); + return -1; + } + use_connect_from = 1; + } + + max_bytes_per_second = 0; + if (linesc > 3) { max_bytes_per_second = atoi(lines[2]); } action_at_finish = ACTION_PROXY; - if (linesc > 3) { + if (linesc > 4) { if (strcmp("proxy", lines[3]) == 0) action_at_finish = ACTION_PROXY; else if (strcmp("exit", lines[3]) == 0) @@ -212,12 +223,17 @@ int control_mirror(struct control_params* client, int linesc, char** lines) } } - if (linesc > 4) { + if (linesc > 5) { write_socket("1: unrecognised parameters to mirror"); return -1; } + + /** I don't like use_connect_from but socket_connect doesn't take *mysockaddr :( */ + if (use_connect_from) + fd = socket_connect(&connect_to.generic, &connect_from.generic); + else + fd = socket_connect(&connect_to.generic, NULL); - fd = socket_connect(&connect_to.generic, NULL); remote_size = socket_nbd_read_hello(fd); remote_size = remote_size; // shush compiler diff --git a/src/flexnbd.c b/src/flexnbd.c index ac5abf8..2e15904 100644 --- a/src/flexnbd.c +++ b/src/flexnbd.c @@ -257,7 +257,7 @@ void read_acl_param( int c, char **sock ) read_sock_param( c, sock, acl_help_text ); } -void read_mirror_param( int c, char **sock, char **ip_addr, char **ip_port ) +void read_mirror_param( int c, char **sock, char **ip_addr, char **ip_port, char **bind_addr ) { switch( c ){ case 'h': @@ -273,6 +273,8 @@ void read_mirror_param( int c, char **sock, char **ip_addr, char **ip_port ) case 'p': *ip_port = optarg; break; + case 'b': + *bind_addr = optarg; case 'v': set_debug(1); break; @@ -426,13 +428,13 @@ int mode_mirror( int argc, char *argv[] ) { int c; char *sock = NULL; - char *remote_argv[3] = {0}; + char *remote_argv[4] = {0}; int err = 0; while (1) { c = getopt_long( argc, argv, mirror_short_options, mirror_options, NULL); if ( -1 == c ) break; - read_mirror_param( c, &sock, &remote_argv[0], &remote_argv[1] ); + read_mirror_param( c, &sock, &remote_argv[0], &remote_argv[1], &remote_argv[2] ); } if ( NULL == sock ){ @@ -444,8 +446,11 @@ int mode_mirror( int argc, char *argv[] ) err = 1; } if ( err ) { exit_err( mirror_help_text ); } - - do_remote_command( "mirror", sock, 2, remote_argv ); + + if (argv[2] == NULL) + do_remote_command( "mirror", sock, 2, remote_argv ); + else + do_remote_command( "mirror", sock, 3, remote_argv ); return 0; } diff --git a/src/options.h b/src/options.h index 0349d50..d1425a0 100644 --- a/src/options.h +++ b/src/options.h @@ -136,10 +136,11 @@ struct option mirror_options[] = { GETOPT_SOCK, GETOPT_ADDR, GETOPT_PORT, + GETOPT_BIND, GETOPT_VERBOSE, {0} }; -static char mirror_short_options[] = "hs:l:p:" SOPT_VERBOSE; +static char mirror_short_options[] = "hs:l:p:b:" SOPT_VERBOSE; static char mirror_help_text[] = "Usage: flexnbd " CMD_MIRROR " \n\n" "Start mirroring from the server with control socket SOCK to one at ADDR:PORT.\n\n" @@ -147,6 +148,7 @@ static char mirror_help_text[] = "\t--" OPT_ADDR ",-l \tThe address to mirror to.\n" "\t--" OPT_PORT ",-p \tThe port to mirror to.\n" SOCK_LINE + BIND_LINE VERBOSE_LINE;