-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from libp2p/remove-sockaddr-dependency
move some functions from go-sockaddr here, remove go-sockaddr dependency
- Loading branch information
Showing
4 changed files
with
135 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
package netroute | ||
|
||
import ( | ||
"net" | ||
"strconv" | ||
"syscall" | ||
"unsafe" | ||
|
||
"golang.org/x/sys/windows" | ||
) | ||
|
||
// socklen is a type for the length of a sockaddr. | ||
type socklen uint | ||
|
||
// ipAndZoneToSockaddr converts a net.IP (with optional IPv6 Zone) to a Sockaddr | ||
// Returns nil if conversion fails. | ||
func ipAndZoneToSockaddr(ip net.IP, zone string) windows.Sockaddr { | ||
// Unspecified? | ||
if ip == nil { | ||
if zone != "" { | ||
return &windows.SockaddrInet6{ZoneId: uint32(ip6ZoneToInt(zone))} | ||
} | ||
return new(windows.SockaddrInet4) | ||
} | ||
|
||
// Valid IPv4? | ||
if ip4 := ip.To4(); ip4 != nil && zone == "" { | ||
var buf [4]byte | ||
copy(buf[:], ip4) // last 4 bytes | ||
return &windows.SockaddrInet4{Addr: buf} | ||
} | ||
|
||
// Valid IPv6 address? | ||
if ip6 := ip.To16(); ip6 != nil { | ||
var buf [16]byte | ||
copy(buf[:], ip6) | ||
return &windows.SockaddrInet6{Addr: buf, ZoneId: uint32(ip6ZoneToInt(zone))} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// sockaddrToIPAndZone converts a Sockaddr to a net.IP (with optional IPv6 Zone) | ||
// Returns nil if conversion fails. | ||
func sockaddrToIPAndZone(sa windows.Sockaddr) (net.IP, string) { | ||
switch sa := sa.(type) { | ||
case *windows.SockaddrInet4: | ||
ip := make([]byte, 16) | ||
// V4InV6Prefix | ||
ip[10] = 0xff | ||
ip[11] = 0xff | ||
copy(ip[12:16], sa.Addr[:]) | ||
return ip, "" | ||
case *windows.SockaddrInet6: | ||
ip := make([]byte, 16) | ||
copy(ip, sa.Addr[:]) | ||
return ip, ip6ZoneToString(int(sa.ZoneId)) | ||
} | ||
return nil, "" | ||
} | ||
|
||
func sockaddrToAny(sa windows.Sockaddr) (*windows.RawSockaddrAny, socklen, error) { | ||
if sa == nil { | ||
return nil, 0, syscall.EINVAL | ||
} | ||
|
||
switch sa := sa.(type) { | ||
case *windows.SockaddrInet4: | ||
if sa.Port < 0 || sa.Port > 0xFFFF { | ||
return nil, 0, syscall.EINVAL | ||
} | ||
raw := new(windows.RawSockaddrAny) | ||
raw.Addr.Family = windows.AF_INET | ||
raw4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(raw)) | ||
p := (*[2]byte)(unsafe.Pointer(&raw4.Port)) | ||
p[0] = byte(sa.Port >> 8) | ||
p[1] = byte(sa.Port) | ||
for i := 0; i < len(sa.Addr); i++ { | ||
raw4.Addr[i] = sa.Addr[i] | ||
} | ||
return raw, socklen(unsafe.Sizeof(*raw4)), nil | ||
case *windows.SockaddrInet6: | ||
if sa.Port < 0 || sa.Port > 0xFFFF { | ||
return nil, 0, syscall.EINVAL | ||
} | ||
raw := new(windows.RawSockaddrAny) | ||
raw.Addr.Family = windows.AF_INET6 | ||
raw6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(raw)) | ||
p := (*[2]byte)(unsafe.Pointer(&raw6.Port)) | ||
p[0] = byte(sa.Port >> 8) | ||
p[1] = byte(sa.Port) | ||
raw6.Scope_id = sa.ZoneId | ||
for i := 0; i < len(sa.Addr); i++ { | ||
raw6.Addr[i] = sa.Addr[i] | ||
} | ||
return raw, socklen(unsafe.Sizeof(*raw6)), nil | ||
case *windows.SockaddrUnix: | ||
return nil, 0, syscall.EWINDOWS | ||
} | ||
return nil, 0, syscall.EAFNOSUPPORT | ||
} | ||
|
||
// from: go/src/pkg/net/ipsock.go | ||
|
||
// ip6ZoneToString converts an IP6 Zone unix int to a net string | ||
// returns "" if zone is 0 | ||
func ip6ZoneToString(zone int) string { | ||
if zone == 0 { | ||
return "" | ||
} | ||
if ifi, err := net.InterfaceByIndex(zone); err == nil { | ||
return ifi.Name | ||
} | ||
return strconv.Itoa(zone) | ||
} | ||
|
||
// ip6ZoneToInt converts an IP6 Zone net string to a unix int | ||
// returns 0 if zone is "" | ||
func ip6ZoneToInt(zone string) int { | ||
if zone == "" { | ||
return 0 | ||
} | ||
if ifi, err := net.InterfaceByName(zone); err == nil { | ||
return ifi.Index | ||
} | ||
n, _ := strconv.ParseInt(zone, 10, 32) | ||
return int(n) | ||
} |