Hi, For symmetry, there should be a script called before a tap device is brought down IMHO. Please consider the appended patch.
Regards, Wolfram. --- vl.c.orig 2007-07-29 19:57:25.000000000 +0200 +++ vl.c 2007-10-13 16:04:51.000000000 +0200 @@ -107,6 +107,7 @@ #include "exec-all.h" #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" +#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" #ifdef __sun__ #define SMBD_COMMAND "/usr/sfw/sbin/smbd" #else @@ -3412,6 +3413,7 @@ typedef struct TAPState { VLANClientState *vc; int fd; + char down_script[1024]; } TAPState; static void tap_receive(void *opaque, const uint8_t *buf, int size) @@ -3647,27 +3649,13 @@ } #endif -static int net_tap_init(VLANState *vlan, const char *ifname1, - const char *setup_script) +static int launch_script(const char *setup_script, const char *ifname, int fd) { - TAPState *s; - int pid, status, fd; + int pid, status; char *args[3]; char **parg; - char ifname[128]; - - if (ifname1 != NULL) - pstrcpy(ifname, sizeof(ifname), ifname1); - else - ifname[0] = '\0'; - TFR(fd = tap_open(ifname, sizeof(ifname))); - if (fd < 0) - return -1; - if (!setup_script || !strcmp(setup_script, "no")) - setup_script = ""; - if (setup_script[0] != '\0') { - /* try to launch network init script */ + /* try to launch network script */ pid = fork(); if (pid >= 0) { if (pid == 0) { @@ -3681,7 +3669,7 @@ parg = args; *parg++ = (char *)setup_script; - *parg++ = ifname; + *parg++ = (char *)ifname; *parg++ = NULL; execv(setup_script, args); _exit(1); @@ -3694,12 +3682,37 @@ return -1; } } + return 0; +} + +static int net_tap_init(VLANState *vlan, const char *ifname1, + const char *setup_script, const char *down_script) +{ + TAPState *s; + int fd; + char ifname[128]; + + if (ifname1 != NULL) + pstrcpy(ifname, sizeof(ifname), ifname1); + else + ifname[0] = '\0'; + TFR(fd = tap_open(ifname, sizeof(ifname))); + if (fd < 0) + return -1; + + if (!setup_script || !strcmp(setup_script, "no")) + setup_script = ""; + if (setup_script[0] != '\0') { + if (launch_script(setup_script, ifname, fd)) + return -1; } s = net_tap_fd_init(vlan, fd); if (!s) return -1; snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: ifname=%s setup_script=%s", ifname, setup_script); + if (down_script && strcmp(down_script, "no")) + snprintf(s->down_script, sizeof(s->down_script), "%s", down_script); return 0; } @@ -4243,7 +4256,7 @@ #else if (!strcmp(device, "tap")) { char ifname[64]; - char setup_script[1024]; + char setup_script[1024], down_script[1024]; int fd; vlan->nb_host_devs++; if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { @@ -4258,7 +4271,10 @@ if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) { pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT); } - ret = net_tap_init(vlan, ifname, setup_script); + if (get_param_value(down_script, sizeof(down_script), "downscript", p) == 0) { + pstrcpy(down_script, sizeof(down_script), DEFAULT_NETWORK_DOWN_SCRIPT); + } + ret = net_tap_init(vlan, ifname, setup_script, down_script); } } else #endif @@ -6646,10 +6662,11 @@ "-net tap[,vlan=n],ifname=name\n" " connect the host TAP network interface to VLAN 'n'\n" #else - "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file]\n" - " connect the host TAP network interface to VLAN 'n' and use\n" - " the network script 'file' (default=%s);\n" - " use 'script=no' to disable script execution;\n" + "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file][,downscript=dfile]\n" + " connect the host TAP network interface to VLAN 'n' and use the\n" + " network scripts 'file' (default=%s)\n" + " and 'dfile' (default=%s);\n" + " use '[down]script=no' to disable script execution;\n" " use 'fd=h' to connect to an already opened TAP interface\n" #endif "-net socket[,vlan=n][,fd=h][,listen=[host]:port][,connect=host:port]\n" @@ -6720,6 +6737,7 @@ DEFAULT_RAM_SIZE, #ifndef _WIN32 DEFAULT_NETWORK_SCRIPT, + DEFAULT_NETWORK_DOWN_SCRIPT, #endif DEFAULT_GDBSTUB_PORT, "/tmp/qemu.log"); @@ -8071,5 +8089,22 @@ main_loop(); quit_timers(); + + /* close network clients */ + for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { + VLANClientState *vc; + + for(vc = vlan->first_client; vc != NULL; vc = vc->next) +#if !defined(_WIN32) + if (vc->fd_read == tap_receive) { + char ifname[64]; + TAPState *s = vc->opaque; + + if (sscanf(vc->info_str, "tap: ifname=%63s ", ifname) == 1 && + s->down_script[0]) + launch_script(s->down_script, ifname, s->fd); + } +#endif + } return 0; }