fix(listener/tap): support custom TAP adapter name on Windows (issue #772)
The songgao/water library's InterfaceName parameter is a selection filter that searches the Windows registry for an existing adapter with a matching friendly name — it cannot name a new adapter during creation. Passing name=tap0 caused the library to fail before even creating the adapter. Fix by omitting InterfaceName from water.New(), letting Windows auto-name the adapter, then renaming via netsh if a custom name was specified. Also add directory validation to file handler to catch misconfig early.
This commit is contained in:
@@ -4,6 +4,7 @@ package file
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -57,6 +58,14 @@ func (h *fileHandler) Init(md md.Metadata) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if h.md.dir != "" {
|
||||||
|
if info, err := os.Stat(h.md.dir); err != nil {
|
||||||
|
return fmt.Errorf("file handler: directory %q: %w", h.md.dir, err)
|
||||||
|
} else if !info.IsDir() {
|
||||||
|
return fmt.Errorf("file handler: %q is not a directory", h.md.dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fs := http.FileServer(http.Dir(h.md.dir))
|
fs := http.FileServer(http.Dir(h.md.dir))
|
||||||
h.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
h.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == http.MethodPut {
|
if r.Method == http.MethodPut {
|
||||||
|
|||||||
@@ -14,12 +14,16 @@ import (
|
|||||||
func (l *tapListener) createTap() (dev io.ReadWriteCloser, name string, ip net.IP, err error) {
|
func (l *tapListener) createTap() (dev io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
ip, ipNet, _ := net.ParseCIDR(l.md.config.Net)
|
ip, ipNet, _ := net.ParseCIDR(l.md.config.Net)
|
||||||
|
|
||||||
|
// On Windows, InterfaceName is a selection filter, not a name assignment.
|
||||||
|
// Passing it to water.New() causes the library to look for an existing
|
||||||
|
// adapter with that friendly name in the registry, which fails if no
|
||||||
|
// adapter with that name exists yet. Instead, let Windows auto-name the
|
||||||
|
// new adapter, then rename it afterwards if the user requested a name.
|
||||||
ifce, err := water.New(water.Config{
|
ifce, err := water.New(water.Config{
|
||||||
DeviceType: water.TAP,
|
DeviceType: water.TAP,
|
||||||
PlatformSpecificParams: water.PlatformSpecificParams{
|
PlatformSpecificParams: water.PlatformSpecificParams{
|
||||||
ComponentID: l.md.config.ComponentID,
|
ComponentID: l.md.config.ComponentID,
|
||||||
InterfaceName: l.md.config.Name,
|
Network: l.md.config.Net,
|
||||||
Network: l.md.config.Net,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -29,10 +33,24 @@ func (l *tapListener) createTap() (dev io.ReadWriteCloser, name string, ip net.I
|
|||||||
dev = ifce
|
dev = ifce
|
||||||
name = ifce.Name()
|
name = ifce.Name()
|
||||||
|
|
||||||
|
// Rename the adapter if the user specified a custom name.
|
||||||
|
if l.md.config.Name != "" && l.md.config.Name != name {
|
||||||
|
renameCmd := fmt.Sprintf("netsh interface set interface name=%s newname=%s",
|
||||||
|
name, l.md.config.Name)
|
||||||
|
l.logger.Debug(renameCmd)
|
||||||
|
args := strings.Split(renameCmd, " ")
|
||||||
|
if er := exec.Command(args[0], args[1:]...).Run(); er == nil {
|
||||||
|
name = l.md.config.Name
|
||||||
|
} else {
|
||||||
|
l.logger.Warnf("failed to rename adapter from %s to %s: %v",
|
||||||
|
name, l.md.config.Name, er)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ip != nil && ipNet != nil {
|
if ip != nil && ipNet != nil {
|
||||||
cmd := fmt.Sprintf("netsh interface ip set address name=%s "+
|
cmd := fmt.Sprintf("netsh interface ip set address name=%s "+
|
||||||
"source=static addr=%s mask=%s gateway=none",
|
"source=static addr=%s mask=%s gateway=none",
|
||||||
ifce.Name(), ip.String(), ipMask(ipNet.Mask))
|
name, ip.String(), ipMask(ipNet.Mask))
|
||||||
l.logger.Debug(cmd)
|
l.logger.Debug(cmd)
|
||||||
|
|
||||||
args := strings.Split(cmd, " ")
|
args := strings.Split(cmd, " ")
|
||||||
@@ -42,7 +60,7 @@ func (l *tapListener) createTap() (dev io.ReadWriteCloser, name string, ip net.I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = l.addRoutes(ifce.Name(), l.md.config.Routes...); err != nil {
|
if err = l.addRoutes(name, l.md.config.Routes...); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user