Diff for /qemu/net/tap.c between versions 1.1.1.5 and 1.1.1.6

version 1.1.1.5, 2018/04/24 19:04:22 version 1.1.1.6, 2018/04/24 19:53:42
Line 346  static TAPState *net_tap_fd_init(VLANSta Line 346  static TAPState *net_tap_fd_init(VLANSta
   
 static int launch_script(const char *setup_script, const char *ifname, int fd)  static int launch_script(const char *setup_script, const char *ifname, int fd)
 {  {
     sigset_t oldmask, mask;  
     int pid, status;      int pid, status;
     char *args[3];      char *args[3];
     char **parg;      char **parg;
   
     sigemptyset(&mask);  
     sigaddset(&mask, SIGCHLD);  
     sigprocmask(SIG_BLOCK, &mask, &oldmask);  
   
     /* try to launch network script */      /* try to launch network script */
     pid = fork();      pid = fork();
     if (pid == 0) {      if (pid == 0) {
Line 378  static int launch_script(const char *set Line 373  static int launch_script(const char *set
         while (waitpid(pid, &status, 0) != pid) {          while (waitpid(pid, &status, 0) != pid) {
             /* loop */              /* loop */
         }          }
         sigprocmask(SIG_SETMASK, &oldmask, NULL);  
   
         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {          if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
             return 0;              return 0;
Line 388  static int launch_script(const char *set Line 382  static int launch_script(const char *set
     return -1;      return -1;
 }  }
   
   static int recv_fd(int c)
   {
       int fd;
       uint8_t msgbuf[CMSG_SPACE(sizeof(fd))];
       struct msghdr msg = {
           .msg_control = msgbuf,
           .msg_controllen = sizeof(msgbuf),
       };
       struct cmsghdr *cmsg;
       struct iovec iov;
       uint8_t req[1];
       ssize_t len;
   
       cmsg = CMSG_FIRSTHDR(&msg);
       cmsg->cmsg_level = SOL_SOCKET;
       cmsg->cmsg_type = SCM_RIGHTS;
       cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
       msg.msg_controllen = cmsg->cmsg_len;
   
       iov.iov_base = req;
       iov.iov_len = sizeof(req);
   
       msg.msg_iov = &iov;
       msg.msg_iovlen = 1;
   
       len = recvmsg(c, &msg, 0);
       if (len > 0) {
           memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
           return fd;
       }
   
       return len;
   }
   
   static int net_bridge_run_helper(const char *helper, const char *bridge)
   {
       sigset_t oldmask, mask;
       int pid, status;
       char *args[5];
       char **parg;
       int sv[2];
   
       sigemptyset(&mask);
       sigaddset(&mask, SIGCHLD);
       sigprocmask(SIG_BLOCK, &mask, &oldmask);
   
       if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
           return -1;
       }
   
       /* try to launch bridge helper */
       pid = fork();
       if (pid == 0) {
           int open_max = sysconf(_SC_OPEN_MAX), i;
           char fd_buf[6+10];
           char br_buf[6+IFNAMSIZ] = {0};
           char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15];
   
           for (i = 0; i < open_max; i++) {
               if (i != STDIN_FILENO &&
                   i != STDOUT_FILENO &&
                   i != STDERR_FILENO &&
                   i != sv[1]) {
                   close(i);
               }
           }
   
           snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]);
   
           if (strrchr(helper, ' ') || strrchr(helper, '\t')) {
               /* assume helper is a command */
   
               if (strstr(helper, "--br=") == NULL) {
                   snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
               }
   
               snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s",
                        helper, "--use-vnet", fd_buf, br_buf);
   
               parg = args;
               *parg++ = (char *)"sh";
               *parg++ = (char *)"-c";
               *parg++ = helper_cmd;
               *parg++ = NULL;
   
               execv("/bin/sh", args);
           } else {
               /* assume helper is just the executable path name */
   
               snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
   
               parg = args;
               *parg++ = (char *)helper;
               *parg++ = (char *)"--use-vnet";
               *parg++ = fd_buf;
               *parg++ = br_buf;
               *parg++ = NULL;
   
               execv(helper, args);
           }
           _exit(1);
   
       } else if (pid > 0) {
           int fd;
   
           close(sv[1]);
   
           do {
               fd = recv_fd(sv[0]);
           } while (fd == -1 && errno == EINTR);
   
           close(sv[0]);
   
           while (waitpid(pid, &status, 0) != pid) {
               /* loop */
           }
           sigprocmask(SIG_SETMASK, &oldmask, NULL);
           if (fd < 0) {
               fprintf(stderr, "failed to recv file descriptor\n");
               return -1;
           }
   
           if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
               return fd;
           }
       }
       fprintf(stderr, "failed to launch bridge helper\n");
       return -1;
   }
   
   int net_init_bridge(QemuOpts *opts, Monitor *mon, const char *name,
                       VLANState *vlan)
   {
       TAPState *s;
       int fd, vnet_hdr;
   
       if (!qemu_opt_get(opts, "br")) {
           qemu_opt_set(opts, "br", DEFAULT_BRIDGE_INTERFACE);
       }
       if (!qemu_opt_get(opts, "helper")) {
           qemu_opt_set(opts, "helper", DEFAULT_BRIDGE_HELPER);
       }
   
       fd = net_bridge_run_helper(qemu_opt_get(opts, "helper"),
                                  qemu_opt_get(opts, "br"));
       if (fd == -1) {
           return -1;
       }
   
       fcntl(fd, F_SETFL, O_NONBLOCK);
   
       vnet_hdr = tap_probe_vnet_hdr(fd);
   
       s = net_tap_fd_init(vlan, "bridge", name, fd, vnet_hdr);
       if (!s) {
           close(fd);
           return -1;
       }
   
       snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s",
                qemu_opt_get(opts, "helper"), qemu_opt_get(opts, "br"));
   
       return 0;
   }
   
 static int net_tap_init(QemuOpts *opts, int *vnet_hdr)  static int net_tap_init(QemuOpts *opts, int *vnet_hdr)
 {  {
     int fd, vnet_hdr_required;      int fd, vnet_hdr_required;
Line 428  int net_init_tap(QemuOpts *opts, Monitor Line 587  int net_init_tap(QemuOpts *opts, Monitor
 {  {
     TAPState *s;      TAPState *s;
     int fd, vnet_hdr = 0;      int fd, vnet_hdr = 0;
       const char *model;
   
     if (qemu_opt_get(opts, "fd")) {      if (qemu_opt_get(opts, "fd")) {
         if (qemu_opt_get(opts, "ifname") ||          if (qemu_opt_get(opts, "ifname") ||
             qemu_opt_get(opts, "script") ||              qemu_opt_get(opts, "script") ||
             qemu_opt_get(opts, "downscript") ||              qemu_opt_get(opts, "downscript") ||
             qemu_opt_get(opts, "vnet_hdr")) {              qemu_opt_get(opts, "vnet_hdr") ||
             error_report("ifname=, script=, downscript= and vnet_hdr= is invalid with fd=");              qemu_opt_get(opts, "helper")) {
               error_report("ifname=, script=, downscript=, vnet_hdr=, "
                            "and helper= are invalid with fd=");
             return -1;              return -1;
         }          }
   
Line 446  int net_init_tap(QemuOpts *opts, Monitor Line 608  int net_init_tap(QemuOpts *opts, Monitor
         fcntl(fd, F_SETFL, O_NONBLOCK);          fcntl(fd, F_SETFL, O_NONBLOCK);
   
         vnet_hdr = tap_probe_vnet_hdr(fd);          vnet_hdr = tap_probe_vnet_hdr(fd);
   
           model = "tap";
   
       } else if (qemu_opt_get(opts, "helper")) {
           if (qemu_opt_get(opts, "ifname") ||
               qemu_opt_get(opts, "script") ||
               qemu_opt_get(opts, "downscript") ||
               qemu_opt_get(opts, "vnet_hdr")) {
               error_report("ifname=, script=, downscript=, and vnet_hdr= "
                            "are invalid with helper=");
               return -1;
           }
   
           fd = net_bridge_run_helper(qemu_opt_get(opts, "helper"),
                                      DEFAULT_BRIDGE_INTERFACE);
           if (fd == -1) {
               return -1;
           }
   
           fcntl(fd, F_SETFL, O_NONBLOCK);
   
           vnet_hdr = tap_probe_vnet_hdr(fd);
   
           model = "bridge";
   
     } else {      } else {
         if (!qemu_opt_get(opts, "script")) {          if (!qemu_opt_get(opts, "script")) {
             qemu_opt_set(opts, "script", DEFAULT_NETWORK_SCRIPT);              qemu_opt_set(opts, "script", DEFAULT_NETWORK_SCRIPT);
Line 459  int net_init_tap(QemuOpts *opts, Monitor Line 646  int net_init_tap(QemuOpts *opts, Monitor
         if (fd == -1) {          if (fd == -1) {
             return -1;              return -1;
         }          }
   
           model = "tap";
     }      }
   
     s = net_tap_fd_init(vlan, "tap", name, fd, vnet_hdr);      s = net_tap_fd_init(vlan, model, name, fd, vnet_hdr);
     if (!s) {      if (!s) {
         close(fd);          close(fd);
         return -1;          return -1;
Line 473  int net_init_tap(QemuOpts *opts, Monitor Line 662  int net_init_tap(QemuOpts *opts, Monitor
   
     if (qemu_opt_get(opts, "fd")) {      if (qemu_opt_get(opts, "fd")) {
         snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd);          snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd);
       } else if (qemu_opt_get(opts, "helper")) {
           snprintf(s->nc.info_str, sizeof(s->nc.info_str),
                    "helper=%s", qemu_opt_get(opts, "helper"));
     } else {      } else {
         const char *ifname, *script, *downscript;          const char *ifname, *script, *downscript;
   

Removed from v.1.1.1.5  
changed lines
  Added in v.1.1.1.6


unix.superglobalmegacorp.com