- if (write(client->net, INIT_PASSWD, 8) < 0)
- err("Negotiation failed: %m");
- cliserv_magic = htonll(cliserv_magic);
- if (write(client->net, &cliserv_magic, sizeof(cliserv_magic)) < 0)
- err("Negotiation failed: %m");
+ if(!client || !client->modern) {
+ /* common */
+ if (write(net, INIT_PASSWD, 8) < 0) {
+ err_nonfatal("Negotiation failed: %m");
+ if(client)
+ exit(EXIT_FAILURE);
+ }
+ if(!client || client->modern) {
+ /* modern */
+ magic = htonll(opts_magic);
+ } else {
+ /* oldstyle */
+ magic = htonll(cliserv_magic);
+ }
+ if (write(net, &magic, sizeof(magic)) < 0) {
+ err_nonfatal("Negotiation failed: %m");
+ if(client)
+ exit(EXIT_FAILURE);
+ }
+ }
+ if(!client) {
+ /* modern */
+ uint32_t reserved;
+ uint32_t opt;
+ uint32_t namelen;
+ char* name;
+ int i;
+
+ if(!servers)
+ err("programmer error");
+ write(net, &smallflags, sizeof(uint16_t));
+ read(net, &reserved, sizeof(reserved));
+ read(net, &magic, sizeof(magic));
+ magic = ntohll(magic);
+ if(magic != opts_magic) {
+ close(net);
+ return NULL;
+ }
+ read(net, &opt, sizeof(opt));
+ opt = ntohl(opt);
+ if(opt != NBD_OPT_EXPORT_NAME) {
+ close(net);
+ return NULL;
+ }
+ read(net, &namelen, sizeof(namelen));
+ namelen = ntohl(namelen);
+ name = malloc(namelen+1);
+ name[namelen]=0;
+ read(net, name, namelen);
+ for(i=0; i<servers->len; i++) {
+ SERVER* serve = &(g_array_index(servers, SERVER, i));
+ if(!strcmp(serve->servename, name)) {
+ CLIENT* client = g_new0(CLIENT, 1);
+ client->server = serve;
+ client->exportsize = OFFT_MAX;
+ client->net = net;
+ client->modern = TRUE;
+ return client;
+ }
+ }
+ return NULL;
+ }
+ /* common */