Diff for /qemu/qemu-sockets.c between versions 1.1.1.8 and 1.1.1.9

version 1.1.1.8, 2018/04/24 19:17:31 version 1.1.1.9, 2018/04/24 19:34:46
Line 26 Line 26
 # define AI_ADDRCONFIG 0  # define AI_ADDRCONFIG 0
 #endif  #endif
   
 static int sockets_debug = 0;  
 static const int on=1, off=0;  static const int on=1, off=0;
   
 /* used temporarely until all users are converted to QemuOpts */  /* used temporarely until all users are converted to QemuOpts */
Line 52  static QemuOptsList dummy_opts = { Line 51  static QemuOptsList dummy_opts = {
         },{          },{
             .name = "ipv6",              .name = "ipv6",
             .type = QEMU_OPT_BOOL,              .type = QEMU_OPT_BOOL,
           },{
               .name = "block",
               .type = QEMU_OPT_BOOL,
         },          },
         { /* end if list */ }          { /* end if list */ }
     },      },
Line 101  const char *inet_strfamily(int family) Line 103  const char *inet_strfamily(int family)
     return "unknown";      return "unknown";
 }  }
   
 static void inet_print_addrinfo(const char *tag, struct addrinfo *res)  int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
 {  
     struct addrinfo *e;  
     char uaddr[INET6_ADDRSTRLEN+1];  
     char uport[33];  
   
     for (e = res; e != NULL; e = e->ai_next) {  
         getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,  
                     uaddr,INET6_ADDRSTRLEN,uport,32,  
                     NI_NUMERICHOST | NI_NUMERICSERV);  
         fprintf(stderr,"%s: getaddrinfo: family %s, host %s, port %s\n",  
                 tag, inet_strfamily(e->ai_family), uaddr, uport);  
     }  
 }  
   
 int inet_listen_opts(QemuOpts *opts, int port_offset)  
 {  {
     struct addrinfo ai,*res,*e;      struct addrinfo ai,*res,*e;
     const char *addr;      const char *addr;
     char port[33];      char port[33];
     char uaddr[INET6_ADDRSTRLEN+1];      char uaddr[INET6_ADDRSTRLEN+1];
     char uport[33];      char uport[33];
     int slisten,rc,to,try_next;      int slisten, rc, to, port_min, port_max, p;
   
     memset(&ai,0, sizeof(ai));      memset(&ai,0, sizeof(ai));
     ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;      ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
Line 133  int inet_listen_opts(QemuOpts *opts, int Line 120  int inet_listen_opts(QemuOpts *opts, int
     if ((qemu_opt_get(opts, "host") == NULL) ||      if ((qemu_opt_get(opts, "host") == NULL) ||
         (qemu_opt_get(opts, "port") == NULL)) {          (qemu_opt_get(opts, "port") == NULL)) {
         fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);          fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
           error_set(errp, QERR_SOCKET_CREATE_FAILED);
         return -1;          return -1;
     }      }
     pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));      pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
Line 151  int inet_listen_opts(QemuOpts *opts, int Line 139  int inet_listen_opts(QemuOpts *opts, int
     if (rc != 0) {      if (rc != 0) {
         fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,          fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
                 gai_strerror(rc));                  gai_strerror(rc));
           error_set(errp, QERR_SOCKET_CREATE_FAILED);
         return -1;          return -1;
     }      }
     if (sockets_debug)  
         inet_print_addrinfo(__FUNCTION__, res);  
   
     /* create socket + bind */      /* create socket + bind */
     for (e = res; e != NULL; e = e->ai_next) {      for (e = res; e != NULL; e = e->ai_next) {
Line 165  int inet_listen_opts(QemuOpts *opts, int Line 152  int inet_listen_opts(QemuOpts *opts, int
         if (slisten < 0) {          if (slisten < 0) {
             fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,              fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
                     inet_strfamily(e->ai_family), strerror(errno));                      inet_strfamily(e->ai_family), strerror(errno));
               if (!e->ai_next) {
                   error_set(errp, QERR_SOCKET_CREATE_FAILED);
               }
             continue;              continue;
         }          }
   
Line 177  int inet_listen_opts(QemuOpts *opts, int Line 167  int inet_listen_opts(QemuOpts *opts, int
         }          }
 #endif  #endif
   
         for (;;) {          port_min = inet_getport(e);
           port_max = to ? to + port_offset : port_min;
           for (p = port_min; p <= port_max; p++) {
               inet_setport(e, p);
             if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {              if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
                 if (sockets_debug)  
                     fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,  
                         inet_strfamily(e->ai_family), uaddr, inet_getport(e));  
                 goto listen;                  goto listen;
             }              }
             try_next = to && (inet_getport(e) <= to + port_offset);              if (p == port_max) {
             if (!try_next || sockets_debug)  
                 fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,                  fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
                         inet_strfamily(e->ai_family), uaddr, inet_getport(e),                          inet_strfamily(e->ai_family), uaddr, inet_getport(e),
                         strerror(errno));                          strerror(errno));
             if (try_next) {                  if (!e->ai_next) {
                 inet_setport(e, inet_getport(e) + 1);                      error_set(errp, QERR_SOCKET_BIND_FAILED);
                 continue;                  }
             }              }
             break;  
         }          }
         closesocket(slisten);          closesocket(slisten);
     }      }
Line 203  int inet_listen_opts(QemuOpts *opts, int Line 191  int inet_listen_opts(QemuOpts *opts, int
   
 listen:  listen:
     if (listen(slisten,1) != 0) {      if (listen(slisten,1) != 0) {
           error_set(errp, QERR_SOCKET_LISTEN_FAILED);
         perror("listen");          perror("listen");
         closesocket(slisten);          closesocket(slisten);
         freeaddrinfo(res);          freeaddrinfo(res);
Line 217  listen: Line 206  listen:
     return slisten;      return slisten;
 }  }
   
 int inet_connect_opts(QemuOpts *opts)  int inet_connect_opts(QemuOpts *opts, Error **errp)
 {  {
     struct addrinfo ai,*res,*e;      struct addrinfo ai,*res,*e;
     const char *addr;      const char *addr;
Line 225  int inet_connect_opts(QemuOpts *opts) Line 214  int inet_connect_opts(QemuOpts *opts)
     char uaddr[INET6_ADDRSTRLEN+1];      char uaddr[INET6_ADDRSTRLEN+1];
     char uport[33];      char uport[33];
     int sock,rc;      int sock,rc;
       bool block;
   
     memset(&ai,0, sizeof(ai));      memset(&ai,0, sizeof(ai));
     ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;      ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
Line 233  int inet_connect_opts(QemuOpts *opts) Line 223  int inet_connect_opts(QemuOpts *opts)
   
     addr = qemu_opt_get(opts, "host");      addr = qemu_opt_get(opts, "host");
     port = qemu_opt_get(opts, "port");      port = qemu_opt_get(opts, "port");
       block = qemu_opt_get_bool(opts, "block", 0);
     if (addr == NULL || port == NULL) {      if (addr == NULL || port == NULL) {
         fprintf(stderr, "inet_connect: host and/or port not specified\n");          fprintf(stderr, "inet_connect: host and/or port not specified\n");
           error_set(errp, QERR_SOCKET_CREATE_FAILED);
         return -1;          return -1;
     }      }
   
Line 247  int inet_connect_opts(QemuOpts *opts) Line 239  int inet_connect_opts(QemuOpts *opts)
     if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) {      if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) {
         fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,          fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
                 gai_strerror(rc));                  gai_strerror(rc));
           error_set(errp, QERR_SOCKET_CREATE_FAILED);
         return -1;          return -1;
     }      }
     if (sockets_debug)  
         inet_print_addrinfo(__FUNCTION__, res);  
   
     for (e = res; e != NULL; e = e->ai_next) {      for (e = res; e != NULL; e = e->ai_next) {
         if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,          if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
Line 266  int inet_connect_opts(QemuOpts *opts) Line 257  int inet_connect_opts(QemuOpts *opts)
             continue;              continue;
         }          }
         setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));          setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
           if (!block) {
               socket_set_nonblock(sock);
           }
         /* connect to peer */          /* connect to peer */
         if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {          do {
             if (sockets_debug || NULL == e->ai_next)              rc = 0;
               if (connect(sock, e->ai_addr, e->ai_addrlen) < 0) {
                   rc = -socket_error();
               }
           } while (rc == -EINTR);
   
     #ifdef _WIN32
           if (!block && (rc == -EINPROGRESS || rc == -EWOULDBLOCK
                          || rc == -WSAEALREADY)) {
     #else
           if (!block && (rc == -EINPROGRESS)) {
     #endif
               error_set(errp, QERR_SOCKET_CONNECT_IN_PROGRESS);
           } else if (rc < 0) {
               if (NULL == e->ai_next)
                 fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,                  fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
                         inet_strfamily(e->ai_family),                          inet_strfamily(e->ai_family),
                         e->ai_canonname, uaddr, uport, strerror(errno));                          e->ai_canonname, uaddr, uport, strerror(errno));
             closesocket(sock);              closesocket(sock);
               sock = -1;
             continue;              continue;
         }          }
         if (sockets_debug)  
             fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,  
                     inet_strfamily(e->ai_family),  
                     e->ai_canonname, uaddr, uport);  
         freeaddrinfo(res);          freeaddrinfo(res);
         return sock;          return sock;
     }      }
       error_set(errp, QERR_SOCKET_CONNECT_FAILED);
     freeaddrinfo(res);      freeaddrinfo(res);
     return -1;      return -1;
 }  }
Line 322  int inet_dgram_opts(QemuOpts *opts) Line 327  int inet_dgram_opts(QemuOpts *opts)
                 gai_strerror(rc));                  gai_strerror(rc));
         return -1;          return -1;
     }      }
     if (sockets_debug) {  
         fprintf(stderr, "%s: peer (%s:%s)\n", __FUNCTION__, addr, port);  
         inet_print_addrinfo(__FUNCTION__, peer);  
     }  
   
     /* lookup local addr */      /* lookup local addr */
     memset(&ai,0, sizeof(ai));      memset(&ai,0, sizeof(ai));
Line 346  int inet_dgram_opts(QemuOpts *opts) Line 347  int inet_dgram_opts(QemuOpts *opts)
                 gai_strerror(rc));                  gai_strerror(rc));
         return -1;          return -1;
     }      }
     if (sockets_debug) {  
         fprintf(stderr, "%s: local (%s:%s)\n", __FUNCTION__, addr, port);  
         inet_print_addrinfo(__FUNCTION__, local);  
     }  
   
     /* create socket */      /* create socket */
     sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);      sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
Line 458  static int inet_parse(QemuOpts *opts, co Line 455  static int inet_parse(QemuOpts *opts, co
 }  }
   
 int inet_listen(const char *str, char *ostr, int olen,  int inet_listen(const char *str, char *ostr, int olen,
                 int socktype, int port_offset)                  int socktype, int port_offset, Error **errp)
 {  {
     QemuOpts *opts;      QemuOpts *opts;
     char *optstr;      char *optstr;
Line 466  int inet_listen(const char *str, char *o Line 463  int inet_listen(const char *str, char *o
   
     opts = qemu_opts_create(&dummy_opts, NULL, 0);      opts = qemu_opts_create(&dummy_opts, NULL, 0);
     if (inet_parse(opts, str) == 0) {      if (inet_parse(opts, str) == 0) {
         sock = inet_listen_opts(opts, port_offset);          sock = inet_listen_opts(opts, port_offset, errp);
         if (sock != -1 && ostr) {          if (sock != -1 && ostr) {
             optstr = strchr(str, ',');              optstr = strchr(str, ',');
             if (qemu_opt_get_bool(opts, "ipv6", 0)) {              if (qemu_opt_get_bool(opts, "ipv6", 0)) {
Line 481  int inet_listen(const char *str, char *o Line 478  int inet_listen(const char *str, char *o
                          optstr ? optstr : "");                           optstr ? optstr : "");
             }              }
         }          }
       } else {
           error_set(errp, QERR_SOCKET_CREATE_FAILED);
     }      }
     qemu_opts_del(opts);      qemu_opts_del(opts);
     return sock;      return sock;
 }  }
   
 int inet_connect(const char *str, int socktype)  int inet_connect(const char *str, bool block, Error **errp)
 {  {
     QemuOpts *opts;      QemuOpts *opts;
     int sock = -1;      int sock = -1;
   
     opts = qemu_opts_create(&dummy_opts, NULL, 0);      opts = qemu_opts_create(&dummy_opts, NULL, 0);
     if (inet_parse(opts, str) == 0)      if (inet_parse(opts, str) == 0) {
         sock = inet_connect_opts(opts);          if (block) {
               qemu_opt_set(opts, "block", "on");
           }
           sock = inet_connect_opts(opts, errp);
       } else {
           error_set(errp, QERR_SOCKET_CREATE_FAILED);
       }
     qemu_opts_del(opts);      qemu_opts_del(opts);
     return sock;      return sock;
 }  }
Line 541  int unix_listen_opts(QemuOpts *opts) Line 546  int unix_listen_opts(QemuOpts *opts)
         goto err;          goto err;
     }      }
   
     if (sockets_debug)  
         fprintf(stderr, "bind(unix:%s): OK\n", un.sun_path);  
     return sock;      return sock;
   
 err:  err:
Line 576  int unix_connect_opts(QemuOpts *opts) Line 579  int unix_connect_opts(QemuOpts *opts)
         return -1;          return -1;
     }      }
   
     if (sockets_debug)  
         fprintf(stderr, "connect(unix:%s): OK\n", path);  
     return sock;      return sock;
 }  }
   

Removed from v.1.1.1.8  
changed lines
  Added in v.1.1.1.9


unix.superglobalmegacorp.com