This patch to libgo adds support for socket control messages. The source code was already there, but wasn't being built because mksysinfo didn't generate the necessary type information. This patch fixes that. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r e7bd4eb1ed7e libgo/Makefile.am --- a/libgo/Makefile.am Fri Jan 27 14:36:52 2012 -0800 +++ b/libgo/Makefile.am Mon Jan 30 15:50:31 2012 -0800 @@ -1593,6 +1593,13 @@ syscall_uname_file = go/syscall/libcall_uname.go endif +# GNU/Linux specific socket control messages. +if LIBGO_IS_LINUX +syscall_sockcmsg_file = go/syscall/sockcmsg_linux.go +else +syscall_sockcmsg_file = +endif + # Support for netlink sockets and messages. if LIBGO_IS_LINUX syscall_netlink_file = go/syscall/netlink_linux.go @@ -1606,8 +1613,10 @@ go/syscall/libcall_support.go \ go/syscall/libcall_posix.go \ go/syscall/socket.go \ + go/syscall/sockcmsg_unix.go \ go/syscall/str.go \ go/syscall/syscall.go \ + $(syscall_sockcmsg_file) \ $(syscall_syscall_file) \ $(syscall_exec_file) \ $(syscall_exec_os_file) \ diff -r e7bd4eb1ed7e libgo/go/syscall/sockcmsg_unix.go --- a/libgo/go/syscall/sockcmsg_unix.go Fri Jan 27 14:36:52 2012 -0800 +++ b/libgo/go/syscall/sockcmsg_unix.go Mon Jan 30 15:50:31 2012 -0800 @@ -14,7 +14,7 @@ // Round the length of a raw sockaddr up to align it propery. func cmsgAlignOf(salen int) int { - salign := sizeofPtr + salign := int(sizeofPtr) // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit // aligned access to BSD subsystem. if darwinAMD64 { @@ -39,7 +39,7 @@ } func cmsgData(cmsg *Cmsghdr) unsafe.Pointer { - return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + SizeofCmsghdr) + return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + uintptr(SizeofCmsghdr)) } type SocketControlMessage struct { @@ -72,7 +72,7 @@ func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, error) { h := (*Cmsghdr)(unsafe.Pointer(&buf[0])) - if h.Len < SizeofCmsghdr || int(h.Len) > len(buf) { + if int(h.Len) < SizeofCmsghdr || int(h.Len) > len(buf) { return nil, nil, EINVAL } return h, buf[cmsgAlignOf(SizeofCmsghdr):], nil diff -r e7bd4eb1ed7e libgo/go/syscall/socket.go --- a/libgo/go/syscall/socket.go Fri Jan 27 14:36:52 2012 -0800 +++ b/libgo/go/syscall/socket.go Mon Jan 30 15:50:31 2012 -0800 @@ -17,12 +17,12 @@ var SocketDisableIPv6 bool type Sockaddr interface { - sockaddr() (ptr *RawSockaddrAny, len Socklen_t, err error) // lowercase; only we can define Sockaddrs + sockaddr() (ptr *RawSockaddrAny, len Socklen_t, err error) // lowercase; only we can define Sockaddrs } type RawSockaddrAny struct { Addr RawSockaddr - Pad [12]int8 + Pad [12]int8 } const SizeofSockaddrAny = 0x1c @@ -30,7 +30,7 @@ type SockaddrInet4 struct { Port int Addr [4]byte - raw RawSockaddrInet4 + raw RawSockaddrInet4 } func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, error) { @@ -40,7 +40,7 @@ sa.raw.Family = AF_INET n := sa.raw.setLen() p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) - p[0] = byte(sa.Port>>8) + p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) for i := 0; i < len(sa.Addr); i++ { sa.raw.Addr[i] = sa.Addr[i] @@ -49,10 +49,10 @@ } type SockaddrInet6 struct { - Port int + Port int ZoneId uint32 - Addr [16]byte - raw RawSockaddrInet6 + Addr [16]byte + raw RawSockaddrInet6 } func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, error) { @@ -62,7 +62,7 @@ sa.raw.Family = AF_INET6 n := sa.raw.setLen() p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) - p[0] = byte(sa.Port>>8) + p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId for i := 0; i < len(sa.Addr); i++ { @@ -73,7 +73,7 @@ type SockaddrUnix struct { Name string - raw RawSockaddrUnix + raw RawSockaddrUnix } func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, error) { @@ -268,12 +268,12 @@ } type Linger struct { - Onoff int32; - Linger int32; + Onoff int32 + Linger int32 } func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { - return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(l)), Socklen_t(unsafe.Sizeof(*l))); + return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(l)), Socklen_t(unsafe.Sizeof(*l))) } func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { @@ -405,3 +405,7 @@ func (msghdr *Msghdr) SetControllen(length int) { msghdr.Controllen = Msghdr_controllen_t(length) } + +func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = Cmsghdr_len_t(length) +} diff -r e7bd4eb1ed7e libgo/mksysinfo.sh --- a/libgo/mksysinfo.sh Fri Jan 27 14:36:52 2012 -0800 +++ b/libgo/mksysinfo.sh Mon Jan 30 15:50:31 2012 -0800 @@ -483,6 +483,43 @@ -e 's/msg_flags/Flags/' \ >> ${OUT} +# The MSG_ flags for Msghdr. +grep '^const _MSG_' gen-sysinfo.go | \ + sed -e 's/^\(const \)_\(MSG_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} + +# The cmsghdr struct. +cmsghdr=`grep '^type _cmsghdr ' gen-sysinfo.go` +if test -n "$cmsghdr"; then + cmsghdr_len=`echo $cmsghdr | sed -n -e 's/^.*cmsg_len \([^ ]*\);.*$/\1/p'` + echo "type Cmsghdr_len_t $cmsghdr_len" >> ${OUT} + echo "$cmsghdr" | \ + sed -e 's/_cmsghdr/Cmsghdr/' \ + -e 's/cmsg_len *[a-zA-Z0-9_]*/Len Cmsghdr_len_t/' \ + -e 's/cmsg_level/Level/' \ + -e 's/cmsg_type/Type/' \ + >> ${OUT} + + # The size of the cmsghdr struct. + echo 'var SizeofCmsghdr = int(unsafe.Sizeof(Cmsghdr{}))' >> ${OUT} +fi + +# The SCM_ flags for Cmsghdr. +grep '^const _SCM_' gen-sysinfo.go | \ + sed -e 's/^\(const \)_\(SCM_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} + +# The ucred struct. +grep '^type _ucred ' gen-sysinfo.go | \ + sed -e 's/_ucred/Ucred/' \ + -e 's/pid/Pid/' \ + -e 's/uid/Uid/' \ + -e 's/gid/Gid/' \ + >> ${OUT} + +# The size of the ucred struct. +if grep 'type Ucred ' ${OUT} >/dev/null 2>&1; then + echo 'var SizeofUcred = int(unsafe.Sizeof(Ucred{}))' >> ${OUT} +fi + # The ip_mreq struct. grep '^type _ip_mreq ' gen-sysinfo.go | \ sed -e 's/_ip_mreq/IPMreq/' \