flexnbd: Add --bind to flexnbd read and flexnbd write
This commit is contained in:
@@ -217,7 +217,7 @@ int control_mirror(struct control_params* client, int linesc, char** lines)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = socket_connect(&connect_to.generic);
|
fd = socket_connect(&connect_to.generic, NULL);
|
||||||
|
|
||||||
remote_size = socket_nbd_read_hello(fd);
|
remote_size = socket_nbd_read_hello(fd);
|
||||||
remote_size = remote_size; // shush compiler
|
remote_size = remote_size; // shush compiler
|
||||||
|
@@ -111,6 +111,7 @@ void params_readwrite(
|
|||||||
struct mode_readwrite_params* out,
|
struct mode_readwrite_params* out,
|
||||||
char* s_ip_address,
|
char* s_ip_address,
|
||||||
char* s_port,
|
char* s_port,
|
||||||
|
char* s_bind_address,
|
||||||
char* s_from,
|
char* s_from,
|
||||||
char* s_length_or_filename
|
char* s_length_or_filename
|
||||||
)
|
)
|
||||||
@@ -128,6 +129,9 @@ void params_readwrite(
|
|||||||
SERVER_ERROR("Couldn't parse connection address '%s'",
|
SERVER_ERROR("Couldn't parse connection address '%s'",
|
||||||
s_ip_address);
|
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 */
|
/* FIXME: duplicated from above */
|
||||||
out->connect_to.v4.sin_port = atoi(s_port);
|
out->connect_to.v4.sin_port = atoi(s_port);
|
||||||
if (out->connect_to.v4.sin_port < 0 || out->connect_to.v4.sin_port > 65535)
|
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){
|
switch(c){
|
||||||
case 'h':
|
case 'h':
|
||||||
@@ -217,6 +221,9 @@ void read_readwrite_param( int c, char **ip_addr, char **ip_port, char **from, c
|
|||||||
case 'S':
|
case 'S':
|
||||||
*size = optarg;
|
*size = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'b':
|
||||||
|
*bind_addr = optarg;
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
set_debug(1);
|
set_debug(1);
|
||||||
break;
|
break;
|
||||||
@@ -320,8 +327,9 @@ int mode_serve( int argc, char *argv[] )
|
|||||||
int mode_read( int argc, char *argv[] )
|
int mode_read( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
char *ip_addr = NULL;
|
char *ip_addr = NULL;
|
||||||
char *ip_port = NULL;
|
char *ip_port = NULL;
|
||||||
|
char *bind_addr = NULL;
|
||||||
char *from = NULL;
|
char *from = NULL;
|
||||||
char *size = NULL;
|
char *size = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -330,8 +338,11 @@ int mode_read( int argc, char *argv[] )
|
|||||||
|
|
||||||
while (1){
|
while (1){
|
||||||
c = getopt_long(argc, argv, read_short_options, read_options, NULL);
|
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 ) {
|
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 ); }
|
if ( err ) { exit_err( read_help_text ); }
|
||||||
|
|
||||||
memset( &readwrite, 0, sizeof( readwrite ) );
|
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 );
|
do_read( &readwrite );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -353,8 +364,9 @@ int mode_read( int argc, char *argv[] )
|
|||||||
int mode_write( int argc, char *argv[] )
|
int mode_write( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
char *ip_addr = NULL;
|
char *ip_addr = NULL;
|
||||||
char *ip_port = NULL;
|
char *ip_port = NULL;
|
||||||
|
char *bind_addr = NULL;
|
||||||
char *from = NULL;
|
char *from = NULL;
|
||||||
char *size = NULL;
|
char *size = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -363,8 +375,10 @@ int mode_write( int argc, char *argv[] )
|
|||||||
|
|
||||||
while (1){
|
while (1){
|
||||||
c = getopt_long(argc, argv, write_short_options, write_options, NULL);
|
c = getopt_long(argc, argv, write_short_options, write_options, NULL);
|
||||||
if ( c == -1 ) break;
|
if ( c == -1 )
|
||||||
read_readwrite_param( c, &ip_addr, &ip_port, &from, &size );
|
break;
|
||||||
|
|
||||||
|
read_readwrite_param( c, &ip_addr, &ip_port, &bind_addr, &from, &size );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( NULL == ip_addr || NULL == ip_port ) {
|
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 ); }
|
if ( err ) { exit_err( write_help_text ); }
|
||||||
|
|
||||||
memset( &readwrite, 0, sizeof( readwrite ) );
|
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 );
|
do_write( &readwrite );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#define OPT_HELP "help"
|
#define OPT_HELP "help"
|
||||||
#define OPT_ADDR "addr"
|
#define OPT_ADDR "addr"
|
||||||
|
#define OPT_BIND "bind"
|
||||||
#define OPT_PORT "port"
|
#define OPT_PORT "port"
|
||||||
#define OPT_FILE "file"
|
#define OPT_FILE "file"
|
||||||
#define OPT_SOCK "sock"
|
#define OPT_SOCK "sock"
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
#define GETOPT_SOCK GETOPT_ARG( OPT_SOCK, 's' )
|
#define GETOPT_SOCK GETOPT_ARG( OPT_SOCK, 's' )
|
||||||
#define GETOPT_FROM GETOPT_ARG( OPT_FROM, 'F' )
|
#define GETOPT_FROM GETOPT_ARG( OPT_FROM, 'F' )
|
||||||
#define GETOPT_SIZE GETOPT_ARG( OPT_SIZE, 'S' )
|
#define GETOPT_SIZE GETOPT_ARG( OPT_SIZE, 'S' )
|
||||||
|
#define GETOPT_BIND GETOPT_ARG( OPT_BIND, 'b' )
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
# define OPT_DEBUG "debug"
|
# define OPT_DEBUG "debug"
|
||||||
@@ -45,6 +47,12 @@
|
|||||||
# define DEBUG_LINE ""
|
# define DEBUG_LINE ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define HELP_LINE \
|
||||||
|
"\t--" OPT_HELP ",-h \tThis text.\n"
|
||||||
|
#define SOCK_LINE \
|
||||||
|
"\t--" OPT_SOCK ",-s <SOCK>\tPath to the control socket.\n"
|
||||||
|
#define BIND_LINE \
|
||||||
|
"\t--" OPT_BIND ",-b <ADDR>\tBind the local socket to a particular IP address.\n"
|
||||||
|
|
||||||
static struct option serve_options[] = {
|
static struct option serve_options[] = {
|
||||||
GETOPT_HELP,
|
GETOPT_HELP,
|
||||||
@@ -60,12 +68,12 @@ static char serve_short_options[] = "Dhl:p:f:s:";
|
|||||||
static char serve_help_text[] =
|
static char serve_help_text[] =
|
||||||
"Usage: flexnbd " CMD_SERVE " <options> [<acl address>*]\n\n"
|
"Usage: flexnbd " CMD_SERVE " <options> [<acl address>*]\n\n"
|
||||||
"Serve FILE from ADDR:PORT, with an optional control socket at SOCK.\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 <ADDR>\tThe address to serve on.\n"
|
"\t--" OPT_ADDR ",-l <ADDR>\tThe address to serve on.\n"
|
||||||
"\t--" OPT_PORT ",-p <PORT>\tThe port to serve on.\n"
|
"\t--" OPT_PORT ",-p <PORT>\tThe port to serve on.\n"
|
||||||
"\t--" OPT_FILE ",-f <FILE>\tThe file to serve.\n"
|
"\t--" OPT_FILE ",-f <FILE>\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"
|
||||||
"\t--" OPT_SOCK ",-s <SOCK>\tPath to the control socket to open.\n"
|
SOCK_LINE
|
||||||
DEBUG_LINE;
|
DEBUG_LINE;
|
||||||
|
|
||||||
static struct option read_options[] = {
|
static struct option read_options[] = {
|
||||||
@@ -74,18 +82,20 @@ static struct option read_options[] = {
|
|||||||
GETOPT_PORT,
|
GETOPT_PORT,
|
||||||
GETOPT_FROM,
|
GETOPT_FROM,
|
||||||
GETOPT_SIZE,
|
GETOPT_SIZE,
|
||||||
|
GETOPT_BIND,
|
||||||
GETOPT_DEBUG,
|
GETOPT_DEBUG,
|
||||||
{0}
|
{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[] =
|
static char read_help_text[] =
|
||||||
"Usage: flexnbd " CMD_READ " <options>\n\n"
|
"Usage: flexnbd " CMD_READ " <options>\n\n"
|
||||||
"Read SIZE bytes from a server at ADDR:PORT to stdout, starting at OFFSET.\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 <ADDR>\tThe address to read from.\n"
|
"\t--" OPT_ADDR ",-l <ADDR>\tThe address to read from.\n"
|
||||||
"\t--" OPT_PORT ",-p <PORT>\tThe port to read from.\n"
|
"\t--" OPT_PORT ",-p <PORT>\tThe port to read from.\n"
|
||||||
"\t--" OPT_FROM ",-F <OFFSET>\tByte offset to read from.\n"
|
"\t--" OPT_FROM ",-F <OFFSET>\tByte offset to read from.\n"
|
||||||
"\t--" OPT_SIZE ",-S <SIZE>\tBytes to read.\n"
|
"\t--" OPT_SIZE ",-S <SIZE>\tBytes to read.\n"
|
||||||
|
BIND_LINE
|
||||||
DEBUG_LINE;
|
DEBUG_LINE;
|
||||||
|
|
||||||
|
|
||||||
@@ -94,11 +104,12 @@ static char *write_short_options = read_short_options;
|
|||||||
static char write_help_text[] =
|
static char write_help_text[] =
|
||||||
"Usage: flexnbd " CMD_WRITE" <options>\n\n"
|
"Usage: flexnbd " CMD_WRITE" <options>\n\n"
|
||||||
"Write SIZE bytes from stdin to a server at ADDR:PORT, starting at OFFSET.\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 <ADDR>\tThe address to write to.\n"
|
"\t--" OPT_ADDR ",-l <ADDR>\tThe address to write to.\n"
|
||||||
"\t--" OPT_PORT ",-p <PORT>\tThe port to write to.\n"
|
"\t--" OPT_PORT ",-p <PORT>\tThe port to write to.\n"
|
||||||
"\t--" OPT_FROM ",-F <OFFSET>\tByte offset to write from.\n"
|
"\t--" OPT_FROM ",-F <OFFSET>\tByte offset to write from.\n"
|
||||||
"\t--" OPT_SIZE ",-S <SIZE>\tBytes to write.\n"
|
"\t--" OPT_SIZE ",-S <SIZE>\tBytes to write.\n"
|
||||||
|
BIND_LINE
|
||||||
DEBUG_LINE;
|
DEBUG_LINE;
|
||||||
|
|
||||||
struct option acl_options[] = {
|
struct option acl_options[] = {
|
||||||
@@ -111,8 +122,8 @@ static char acl_short_options[] = "hs:";
|
|||||||
static char acl_help_text[] =
|
static char acl_help_text[] =
|
||||||
"Usage: flexnbd " CMD_ACL " <options> [<acl address>+]\n\n"
|
"Usage: flexnbd " CMD_ACL " <options> [<acl address>+]\n\n"
|
||||||
"Set the access control list for a server with control socket SOCK.\n\n"
|
"Set the access control list for a server with control socket SOCK.\n\n"
|
||||||
"\t--" OPT_HELP ",-h\tThis text.\n"
|
HELP_LINE
|
||||||
"\t--" OPT_SOCK ",-s <SOCK>\tPath to the control socket.\n"
|
SOCK_LINE
|
||||||
DEBUG_LINE;
|
DEBUG_LINE;
|
||||||
|
|
||||||
struct option mirror_options[] = {
|
struct option mirror_options[] = {
|
||||||
@@ -127,8 +138,7 @@ static char mirror_short_options[] = "hs:l:p:";
|
|||||||
static char mirror_help_text[] =
|
static char mirror_help_text[] =
|
||||||
"Usage: flexnbd " CMD_MIRROR " <options>\n\n"
|
"Usage: flexnbd " CMD_MIRROR " <options>\n\n"
|
||||||
"Start mirroring from the server with control socket SOCK to one at ADDR:PORT.\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"
|
HELP_LINE
|
||||||
"\t--" OPT_SOCK ",-s <SOCK>\tPath to the control socket.\n"
|
|
||||||
"\t--" OPT_ADDR ",-l <ADDR>\tThe address to mirror to.\n"
|
"\t--" OPT_ADDR ",-l <ADDR>\tThe address to mirror to.\n"
|
||||||
"\t--" OPT_PORT ",-p <PORT>\tThe port to mirror to.\n"
|
"\t--" OPT_PORT ",-p <PORT>\tThe port to mirror to.\n"
|
||||||
DEBUG_LINE;
|
DEBUG_LINE;
|
||||||
@@ -144,8 +154,8 @@ static char status_short_options[] = "hs:";
|
|||||||
static char status_help_text[] =
|
static char status_help_text[] =
|
||||||
"Usage: flexnbd " CMD_STATUS " <options>\n\n"
|
"Usage: flexnbd " CMD_STATUS " <options>\n\n"
|
||||||
"Get the status for a server with control socket SOCK.\n\n"
|
"Get the status for a server with control socket SOCK.\n\n"
|
||||||
"\t--" OPT_HELP ",-h\tThis text.\n"
|
HELP_LINE
|
||||||
"\t--" OPT_SOCK ",-s <SOCK>\tPath to the control socket.\n"
|
SOCK_LINE
|
||||||
DEBUG_LINE;
|
DEBUG_LINE;
|
||||||
|
|
||||||
static char help_help_text[] =
|
static char help_help_text[] =
|
||||||
@@ -159,3 +169,4 @@ static char help_help_text[] =
|
|||||||
"\tflexnbd status\n"
|
"\tflexnbd status\n"
|
||||||
"\tflexnbd help\n\n"
|
"\tflexnbd help\n\n"
|
||||||
"See flexnbd help <cmd> for further info\n";
|
"See flexnbd help <cmd> for further info\n";
|
||||||
|
|
||||||
|
@@ -82,6 +82,7 @@ struct mode_serve_params {
|
|||||||
|
|
||||||
struct mode_readwrite_params {
|
struct mode_readwrite_params {
|
||||||
union mysockaddr connect_to;
|
union mysockaddr connect_to;
|
||||||
|
union mysockaddr connect_from;
|
||||||
off64_t from;
|
off64_t from;
|
||||||
off64_t len;
|
off64_t len;
|
||||||
int data_fd;
|
int data_fd;
|
||||||
|
@@ -7,12 +7,20 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
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);
|
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(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;
|
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)
|
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");
|
CHECK_RANGE("read");
|
||||||
socket_nbd_read(params->client, params->from, params->len,
|
socket_nbd_read(params->client, params->from, params->len,
|
||||||
params->data_fd, NULL);
|
params->data_fd, NULL);
|
||||||
@@ -115,7 +123,7 @@ void do_read(struct mode_readwrite_params* params)
|
|||||||
|
|
||||||
void do_write(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");
|
CHECK_RANGE("write");
|
||||||
socket_nbd_write(params->client, params->from, params->len,
|
socket_nbd_write(params->client, params->from, params->len,
|
||||||
params->data_fd, NULL);
|
params->data_fd, NULL);
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#define __READWRITE_H
|
#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);
|
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_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);
|
void socket_nbd_write(int fd, off64_t from, int len, int out_fd, void* out_buf);
|
||||||
|
Reference in New Issue
Block a user