summaryrefslogtreecommitdiffhomepage
path: root/conn_linux.go
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2018-09-16 15:05:08 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-09-16 18:49:19 +0200
commit32d2148835d28f5927daee2d1206c88ac343cfb3 (patch)
tree37ce4a7731b0a305f0c9b4b006d5f614d9dfe194 /conn_linux.go
parent5be541d147562bf87f6a9ebd551412d4a6920b4b (diff)
Fixed port overwrite issue on kernels without ipv6
Fixed an issue in CreateBind for Linux: If ipv6 was not supported the error code would be correctly identified as EAFNOSUPPORT and ipv4 binding attempted. However the port would be set to 0, which results in the subsequent create4 call requesting a random port rather than the one provided to CreateBind. This issue was identified by: Kent Friis <leeloored@gmx.com>
Diffstat (limited to 'conn_linux.go')
-rw-r--r--conn_linux.go48
1 files changed, 35 insertions, 13 deletions
diff --git a/conn_linux.go b/conn_linux.go
index db0e3a6..0849920 100644
--- a/conn_linux.go
+++ b/conn_linux.go
@@ -27,6 +27,10 @@ import (
"unsafe"
)
+const (
+ FD_ERR = -1
+)
+
type IPv4Source struct {
src [4]byte
ifindex int32
@@ -126,6 +130,7 @@ func createNetlinkRouteSocket() (int, error) {
func CreateBind(port uint16, device *Device) (*NativeBind, uint16, error) {
var err error
var bind NativeBind
+ var newPort uint16
bind.netlinkSock, err = createNetlinkRouteSocket()
if err != nil {
@@ -139,18 +144,35 @@ func CreateBind(port uint16, device *Device) (*NativeBind, uint16, error) {
go bind.routineRouteListener(device)
- bind.sock6, port, err = create6(port)
- if err != nil && err != syscall.EAFNOSUPPORT {
- bind.netlinkCancel.Cancel()
- return nil, 0, err
+ // attempt ipv6 bind, update port if succesful
+
+ bind.sock6, newPort, err = create6(port)
+ if err != nil {
+ if err != syscall.EAFNOSUPPORT {
+ bind.netlinkCancel.Cancel()
+ return nil, 0, err
+ }
+ } else {
+ port = newPort
}
- bind.sock4, port, err = create4(port)
- if err != nil && err != syscall.EAFNOSUPPORT {
- bind.netlinkCancel.Cancel()
- unix.Close(bind.sock6)
- return nil, 0, err
+ // attempt ipv4 bind, update port if succesful
+
+ bind.sock4, newPort, err = create4(port)
+ if err != nil {
+ if err != syscall.EAFNOSUPPORT {
+ bind.netlinkCancel.Cancel()
+ unix.Close(bind.sock6)
+ return nil, 0, err
+ }
+ } else {
+ port = newPort
}
+
+ if bind.sock4 == FD_ERR && bind.sock6 == FD_ERR {
+ return nil, 0, errors.New("ipv4 and ipv6 not supported")
+ }
+
return &bind, port, nil
}
@@ -334,7 +356,7 @@ func create4(port uint16) (int, uint16, error) {
)
if err != nil {
- return -1, 0, err
+ return FD_ERR, 0, err
}
addr := unix.SockaddrInet4{
@@ -365,7 +387,7 @@ func create4(port uint16) (int, uint16, error) {
return unix.Bind(fd, &addr)
}(); err != nil {
unix.Close(fd)
- return -1, 0, err
+ return FD_ERR, 0, err
}
return fd, uint16(addr.Port), err
@@ -382,7 +404,7 @@ func create6(port uint16) (int, uint16, error) {
)
if err != nil {
- return -1, 0, err
+ return FD_ERR, 0, err
}
// set sockopts and bind
@@ -424,7 +446,7 @@ func create6(port uint16) (int, uint16, error) {
}(); err != nil {
unix.Close(fd)
- return -1, 0, err
+ return FD_ERR, 0, err
}
return fd, uint16(addr.Port), err