@@ -461,7 +461,20 @@ void parse_sizes(char *buf, uint64_t *size, uint16_t *flags) {
461461 printf ("\n" );
462462}
463463
464- void negotiate (int * sockp , u64 * rsize64 , uint16_t * flags , char * name , uint32_t needed_flags , uint32_t client_flags , uint32_t do_opts , char * certfile , char * keyfile , char * cacertfile , char * tlshostname , bool tls ) {
464+ void send_opt_exportname (int sock , u64 * rsize64 , uint16_t * flags , bool can_opt_go , char * name , uint16_t global_flags ) {
465+ send_request (sock , NBD_OPT_EXPORT_NAME , -1 , name );
466+ char b [sizeof (* flags ) + sizeof (* rsize64 )];
467+ if (readit (sock , b , sizeof (b )) < 0 && can_opt_go ) {
468+ err ("E: server does not support NBD_OPT_GO and dropped connection after sending NBD_OPT_EXPORT_NAME. Try -g." );
469+ }
470+ parse_sizes (b , rsize64 , flags );
471+ if (!global_flags & NBD_FLAG_NO_ZEROES ) {
472+ char buf [125 ];
473+ readit (sock , buf , 124 );
474+ }
475+ }
476+
477+ void negotiate (int * sockp , u64 * rsize64 , uint16_t * flags , char * name , uint32_t needed_flags , uint32_t client_flags , uint32_t do_opts , char * certfile , char * keyfile , char * cacertfile , char * tlshostname , bool tls , bool can_opt_go ) {
465478 u64 magic ;
466479 uint16_t tmp ;
467480 uint16_t global_flags ;
@@ -594,25 +607,24 @@ void negotiate(int *sockp, u64 *rsize64, uint16_t *flags, char* name, uint32_t n
594607 exit (EXIT_SUCCESS );
595608 }
596609
597- send_info_request (sock , NBD_OPT_GO , 0 , NULL , name );
598-
599610 struct reply * rep = NULL ;
600611
612+ if (!can_opt_go ) {
613+ send_opt_exportname (sock , rsize64 , flags , can_opt_go , name , global_flags );
614+ return ;
615+ }
616+
617+ send_info_request (sock , NBD_OPT_GO , 0 , NULL , name );
618+
601619 do {
602620 if (rep != NULL ) free (rep );
603621 rep = read_reply (sock );
604- if (rep -> reply_type & NBD_REP_FLAG_ERROR ) {
622+ if (rep && ( rep -> reply_type & NBD_REP_FLAG_ERROR ) ) {
605623 switch (rep -> reply_type ) {
606624 case NBD_REP_ERR_UNSUP :
607625 /* server doesn't support NBD_OPT_GO or NBD_OPT_INFO,
608626 * fall back to NBD_OPT_EXPORT_NAME */
609- send_request (sock , NBD_OPT_EXPORT_NAME , -1 , name );
610- char b [sizeof (* flags ) + sizeof (* rsize64 )];
611- readit (sock , b , sizeof (b ));
612- parse_sizes (b , rsize64 , flags );
613- if (!(global_flags & NBD_FLAG_NO_ZEROES )) {
614- readit (sock , buf , 124 );
615- }
627+ send_opt_exportname (sock , rsize64 , flags , can_opt_go , name , global_flags );
616628 free (rep );
617629 return ;
618630 case NBD_REP_ERR_POLICY :
@@ -654,13 +666,13 @@ void negotiate(int *sockp, u64 *rsize64, uint16_t *flags, char* name, uint32_t n
654666 case NBD_REP_ACK :
655667 break ;
656668 default :
657- err_nonfatal ("Unknown reply to NBD_OPT_GO received" );
669+ err_nonfatal ("Unknown reply to NBD_OPT_GO received, ignoring " );
658670 }
659671 } while (rep -> reply_type != NBD_REP_ACK );
660672 free (rep );
661673}
662674
663- bool get_from_config (char * cfgname , char * * name_ptr , char * * dev_ptr , char * * hostn_ptr , int * bs , int * timeout , int * persist , int * swap , int * sdp , int * b_unix , char * * port , int * num_conns , char * * certfile , char * * keyfile , char * * cacertfile , char * * tlshostname ) {
675+ bool get_from_config (char * cfgname , char * * name_ptr , char * * dev_ptr , char * * hostn_ptr , int * bs , int * timeout , int * persist , int * swap , int * sdp , int * b_unix , char * * port , int * num_conns , char * * certfile , char * * keyfile , char * * cacertfile , char * * tlshostname , bool can_opt_go ) {
664676 int fd = open (SYSCONFDIR "/nbdtab" , O_RDONLY );
665677 bool retval = false;
666678 if (fd < 0 ) {
@@ -769,6 +781,10 @@ bool get_from_config(char* cfgname, char** name_ptr, char** dev_ptr, char** host
769781 * tlshostname = strndup (loc + 9 , strcspn (loc + 9 , "," ));
770782 goto next ;
771783 }
784+ if (!strncmp (loc , "no_optgo" , 8 )) {
785+ * can_opt_go = false;
786+ goto next ;
787+ }
772788 // skip unknown options, with a warning unless they start with a '_'
773789 l = strcspn (loc , "," );
774790 if (* loc != '_' ) {
@@ -918,7 +934,7 @@ void disconnect(char* device) {
918934#if HAVE_NETLINK
919935static const char * short_opts = "-A:b:c:C:d:H:hK:LlnN:pSst:uVx" ;
920936#else
921- static const char * short_opts = "-A:b:c:C:d:H :hK:lnN:pSst:uVx" ;
937+ static const char * short_opts = "-A:b:c:C:d:gH :hK:lnN:pSst:uVx" ;
922938#endif
923939
924940int main (int argc , char * argv []) {
@@ -958,6 +974,7 @@ int main(int argc, char *argv[]) {
958974 { "check" , required_argument , NULL , 'c' },
959975 { "connections" , required_argument , NULL , 'C' },
960976 { "disconnect" , required_argument , NULL , 'd' },
977+ { "no-optgo" , no_argument , NULL , 'g' },
961978 { "help" , no_argument , NULL , 'h' },
962979 { "list" , no_argument , NULL , 'l' },
963980 { "name" , required_argument , NULL , 'N' },
@@ -980,6 +997,7 @@ int main(int argc, char *argv[]) {
980997 { 0 , 0 , 0 , 0 },
981998 };
982999 int i ;
1000+ bool can_opt_go = true;
9831001
9841002 logging (MY_NAME );
9851003
@@ -1043,6 +1061,9 @@ int main(int argc, char *argv[]) {
10431061 need_disconnect = 1 ;
10441062 nbddev = strdup (optarg );
10451063 break ;
1064+ case 'g' :
1065+ can_opt_go = false;
1066+ break ;
10461067 case 'h' :
10471068 usage (NULL );
10481069 exit (EXIT_SUCCESS );
@@ -1179,7 +1200,7 @@ int main(int argc, char *argv[]) {
11791200 if (sock < 0 )
11801201 exit (EXIT_FAILURE );
11811202
1182- negotiate (& sock , & size64 , & flags , name , needed_flags , cflags , opts , certfile , keyfile , cacertfile , tlshostname , tls );
1203+ negotiate (& sock , & size64 , & flags , name , needed_flags , cflags , opts , certfile , keyfile , cacertfile , tlshostname , tls , can_opt_go );
11831204 if (netlink ) {
11841205 sockfds [i ] = sock ;
11851206 continue ;
@@ -1293,7 +1314,7 @@ int main(int argc, char *argv[]) {
12931314 nbd = open (nbddev , O_RDWR );
12941315 if (nbd < 0 )
12951316 err ("Cannot open NBD: %m" );
1296- negotiate (& sock , & new_size , & new_flags , name , needed_flags , cflags , opts , certfile , keyfile , cacertfile , tlshostname , tls );
1317+ negotiate (& sock , & new_size , & new_flags , name , needed_flags , cflags , opts , certfile , keyfile , cacertfile , tlshostname , tls , can_opt_go );
12971318 if (size64 != new_size ) {
12981319 err ("Size of the device changed. Bye" );
12991320 }
0 commit comments