diff --git a/ipv6/sys.go b/ipv6/sys.go new file mode 100644 index 00000000..18b1acac --- /dev/null +++ b/ipv6/sys.go @@ -0,0 +1,23 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +type sysSockoptLen uint32 + +const ( + sysSizeofPacketInfo = 0x14 + sysSizeofMulticastReq = 0x14 + sysSizeofICMPFilter = 0x20 +) + +type sysPacketInfo struct { + IP [16]byte + IfIndex uint32 +} + +type sysMulticastReq struct { + IP [16]byte + IfIndex uint32 +} diff --git a/ipv6/sys_bsd.go b/ipv6/sys_bsd.go new file mode 100644 index 00000000..4a08217f --- /dev/null +++ b/ipv6/sys_bsd.go @@ -0,0 +1,48 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build freebsd netbsd openbsd + +package ipv6 + +import ( + "net" + "syscall" +) + +// RFC 3493 options +const ( + // See /usr/include/netinet6/in6.h. + sysSockoptUnicastHopLimit = 0x4 + sysSockoptMulticastHopLimit = 0xa + sysSockoptMulticastInterface = 0x9 + sysSockoptMulticastLoopback = 0xb + sysSockoptJoinGroup = 0xc + sysSockoptLeaveGroup = 0xd +) + +// RFC 3542 options +const ( + // See /usr/include/netinet6/in6.h. + sysSockoptReceiveTrafficClass = 0x39 + sysSockoptTrafficClass = 0x3d + sysSockoptReceiveHopLimit = 0x25 + sysSockoptHopLimit = 0x2f + sysSockoptReceivePacketInfo = 0x24 + sysSockoptPacketInfo = 0x2e + sysSockoptReceivePathMTU = 0x2b + sysSockoptPathMTU = 0x2c + sysSockoptNextHop = 0x30 + sysSockoptChecksum = 0x1a + + // See /usr/include/netinet6/in6.h. + sysSockoptICMPFilter = 0x12 +) + +func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) { + sa.Len = syscall.SizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(ifindex) +} diff --git a/ipv6/sys_darwin.go b/ipv6/sys_darwin.go new file mode 100644 index 00000000..3d07dff5 --- /dev/null +++ b/ipv6/sys_darwin.go @@ -0,0 +1,54 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "syscall" +) + +// RFC 2292 options +const ( + // See /usr/include/netinet6/in6.h. + sysSockopt2292HopLimit = 0x14 + sysSockopt2292PacketInfo = 0x13 + sysSockopt2292NextHop = 0x15 +) + +// RFC 3493 options +const ( + // See /usr/include/netinet6/in6.h. + sysSockoptUnicastHopLimit = 0x4 + sysSockoptMulticastHopLimit = 0xa + sysSockoptMulticastInterface = 0x9 + sysSockoptMulticastLoopback = 0xb + sysSockoptJoinGroup = 0xc + sysSockoptLeaveGroup = 0xd +) + +// RFC 3542 options +const ( + // See /usr/include/netinet6/in6.h. + sysSockoptReceiveTrafficClass = 0x23 + sysSockoptTrafficClass = 0x24 + sysSockoptReceiveHopLimit = 0x25 + sysSockoptHopLimit = 0x2f + sysSockoptReceivePacketInfo = 0x3d + sysSockoptPacketInfo = 0x2e + sysSockoptReceivePathMTU = 0x2b + sysSockoptPathMTU = 0x2c + sysSockoptNextHop = 0x30 + sysSockoptChecksum = 0x1a + + // See /usr/include/netinet6/in6.h. + sysSockoptICMPFilter = 0x12 +) + +func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) { + sa.Len = syscall.SizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(ifindex) +} diff --git a/ipv6/sys_linux.go b/ipv6/sys_linux.go new file mode 100644 index 00000000..d90c8cb8 --- /dev/null +++ b/ipv6/sys_linux.go @@ -0,0 +1,45 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "syscall" +) + +// RFC 3493 options +const ( + // See /usr/include/linux/in6.h. + sysSockoptUnicastHopLimit = 0x10 + sysSockoptMulticastHopLimit = 0x12 + sysSockoptMulticastInterface = 0x11 + sysSockoptMulticastLoopback = 0x13 + sysSockoptJoinGroup = 0x14 + sysSockoptLeaveGroup = 0x15 +) + +// RFC 3542 options +const ( + // See /usr/include/linux/ipv6.h,in6.h. + sysSockoptReceiveTrafficClass = 0x42 + sysSockoptTrafficClass = 0x43 + sysSockoptReceiveHopLimit = 0x33 + sysSockoptHopLimit = 0x34 + sysSockoptReceivePacketInfo = 0x31 + sysSockoptPacketInfo = 0x32 + sysSockoptReceivePathMTU = 0x3c + sysSockoptPathMTU = 0x3d + sysSockoptNextHop = 0x9 + sysSockoptChecksum = 0x7 + + // See /usr/include/linux/icmpv6.h. + sysSockoptICMPFilter = 0x1 +) + +func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) { + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(ifindex) +} diff --git a/ipv6/sys_unix.go b/ipv6/sys_unix.go new file mode 100644 index 00000000..40cdfc4d --- /dev/null +++ b/ipv6/sys_unix.go @@ -0,0 +1,16 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin freebsd linux netbsd openbsd + +package ipv6 + +import "syscall" + +const sysSizeofMTUInfo = 0x20 + +type sysMTUInfo struct { + Addr syscall.RawSockaddrInet6 + MTU uint32 +} diff --git a/ipv6/sys_windows.go b/ipv6/sys_windows.go new file mode 100644 index 00000000..c09672f2 --- /dev/null +++ b/ipv6/sys_windows.go @@ -0,0 +1,33 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "syscall" +) + +// RFC 3493 options +const ( + // See ws2tcpip.h. + sysSockoptUnicastHopLimit = 0x4 + sysSockoptMulticastHopLimit = 0xa + sysSockoptMulticastInterface = 0x9 + sysSockoptMulticastLoopback = 0xb + sysSockoptJoinGroup = 0xc + sysSockoptLeaveGroup = 0xd +) + +// RFC 3542 options +const ( + // See ws2tcpip.h. + sysSockoptPacketInfo = 0x13 +) + +func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) { + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(ifindex) +} diff --git a/ipv6/syscall_linux_386.go b/ipv6/syscall_linux_386.go new file mode 100644 index 00000000..a3866362 --- /dev/null +++ b/ipv6/syscall_linux_386.go @@ -0,0 +1,42 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code is a duplicate of syscall/syscall_linux_386.go with small +// modifications. + +package ipv6 + +import ( + "syscall" + "unsafe" +) + +// On x86 Linux, all the socket calls go through an extra indirection, +// I think because the 5-register system call interface can't handle +// the 6-argument calls like sendto and recvfrom. Instead the +// arguments to the underlying system call are the number below and a +// pointer to an array of uintptr. We hide the pointer in the +// socketcall assembly to avoid allocation on every system call. + +const ( + // See /usr/include/linux/net.h. + _SETSOCKOPT = 14 + _GETSOCKOPT = 15 +) + +var socketcall func(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno) + +func getsockopt(fd int, level int, name int, v uintptr, l *sysSockoptLen) error { + if _, errno := socketcall(_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 { + return error(errno) + } + return nil +} + +func setsockopt(fd int, level int, name int, v uintptr, l uintptr) error { + if _, errno := socketcall(_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), v, l, 0); errno != 0 { + return error(errno) + } + return nil +} diff --git a/ipv6/syscall_linux_386.s b/ipv6/syscall_linux_386.s new file mode 100644 index 00000000..34c0457f --- /dev/null +++ b/ipv6/syscall_linux_386.s @@ -0,0 +1,56 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This code is a duplicate of syscall/syscall_linux_386.s with small +// modifications. + +#define SYS_SOCKETCALL 102 // from zsysnum_linux_386.go + +// func socketcallnosplit7(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int) +// Kernel interface gets call sub-number and pointer to a0 for Go 1.1. +TEXT ·socketcallnosplit7(SB),7,$0 + CALL runtime·entersyscall(SB) + MOVL $SYS_SOCKETCALL, AX // syscall entry + MOVL 4(SP), BX // socket call number + LEAL 8(SP), CX // pointer to call arguments + MOVL $0, DX + MOVL $0, SI + MOVL $0, DI + CALL *runtime·_vdso(SB) + CMPL AX, $0xfffff001 + JLS ok1 + MOVL $-1, 32(SP) // n + NEGL AX + MOVL AX, 36(SP) // errno + CALL runtime·exitsyscall(SB) + RET +ok1: + MOVL AX, 32(SP) // n + MOVL $0, 36(SP) // errno + CALL runtime·exitsyscall(SB) + RET + +// func socketcallnosplit4(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int) +// Kernel interface gets call sub-number and pointer to a0 for Go 1.2. +TEXT ·socketcallnosplit4(SB),4,$0-40 + CALL runtime·entersyscall(SB) + MOVL $SYS_SOCKETCALL, AX // syscall entry + MOVL 4(SP), BX // socket call number + LEAL 8(SP), CX // pointer to call arguments + MOVL $0, DX + MOVL $0, SI + MOVL $0, DI + CALL *runtime·_vdso(SB) + CMPL AX, $0xfffff001 + JLS ok2 + MOVL $-1, 32(SP) // n + NEGL AX + MOVL AX, 36(SP) // errno + CALL runtime·exitsyscall(SB) + RET +ok2: + MOVL AX, 32(SP) // n + MOVL $0, 36(SP) // errno + CALL runtime·exitsyscall(SB) + RET diff --git a/ipv6/syscall_nosplit4_linux_386.go b/ipv6/syscall_nosplit4_linux_386.go new file mode 100644 index 00000000..6d4ac096 --- /dev/null +++ b/ipv6/syscall_nosplit4_linux_386.go @@ -0,0 +1,15 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.2 + +package ipv6 + +import "syscall" + +func socketcallnosplit4(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno) + +func init() { + socketcall = socketcallnosplit4 +} diff --git a/ipv6/syscall_nosplit7_linux_386.go b/ipv6/syscall_nosplit7_linux_386.go new file mode 100644 index 00000000..2e4da7b5 --- /dev/null +++ b/ipv6/syscall_nosplit7_linux_386.go @@ -0,0 +1,15 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.1,!go1.2 + +package ipv6 + +import "syscall" + +func socketcallnosplit7(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno) + +func init() { + socketcall = socketcallnosplit7 +} diff --git a/ipv6/syscall_unix.go b/ipv6/syscall_unix.go new file mode 100644 index 00000000..d88dab52 --- /dev/null +++ b/ipv6/syscall_unix.go @@ -0,0 +1,26 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin freebsd linux,amd64 linux,arm netbsd openbsd + +package ipv6 + +import ( + "syscall" + "unsafe" +) + +func getsockopt(fd int, level, name int, v uintptr, l *sysSockoptLen) error { + if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 { + return error(errno) + } + return nil +} + +func setsockopt(fd int, level int, name int, v uintptr, l uintptr) error { + if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 { + return error(errno) + } + return nil +}