syscall: import upstream code for BSD sockets and sysctls
authorNikhil Benesch <nikhil.benesch@gmail.com>
Sat, 10 Oct 2020 00:06:36 +0000 (00:06 +0000)
committerIan Lance Taylor <iant@golang.org>
Wed, 21 Oct 2020 23:57:59 +0000 (16:57 -0700)
Import some missing upstream code for BSD sockets and sysctls and
adapt it for gccgo.

Updates golang/go#38538.

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/261137

gcc/go/gofrontend/MERGE
libgo/go/syscall/route_bsd.go
libgo/go/syscall/socket_bsd.go
libgo/go/syscall/syscall_netbsd.go

index fb7aa3e6eaeca12b11556ec22f0a6a659183d3cb..aedaf4664d554972b372b202249a062be4a6cdd5 100644 (file)
@@ -1,4 +1,4 @@
-b2be94556bbc98f565fc277e30a038c742bf28a4
+64c25b2365f7125a32b3146618b627f26a78c1fc
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index b364eeaba5dc0570ea3204bf5cc49fb5a967806f..0c32594783c2b2e589dd55a77b766a2ba0aad0f8 100644 (file)
@@ -18,7 +18,7 @@ var (
 
 // Round the length of a raw sockaddr up to align it properly.
 func rsaAlignOf(salen int) int {
-       salign := sizeofPtr
+       salign := int(sizeofPtr)
        if darwin64Bit {
                // Darwin kernels require 32-bit aligned access to
                // routing facilities.
index 40637bc781866ae0eef351d23429e49ea27f4268..b230a3212e629b5deff2727052e7c10e55bc92f7 100644 (file)
@@ -13,6 +13,7 @@ import "unsafe"
 const SizeofSockaddrInet4 = 16
 const SizeofSockaddrInet6 = 28
 const SizeofSockaddrUnix = 110
+const SizeofSockaddrDatalink = 20
 
 type RawSockaddrInet4 struct {
        Len    uint8
@@ -76,6 +77,46 @@ func (sa *RawSockaddrUnix) adjustAbstract(sl Socklen_t) Socklen_t {
        return sl
 }
 
+type SockaddrDatalink struct {
+       Len    uint8
+       Family uint8
+       Index  uint16
+       Type   uint8
+       Nlen   uint8
+       Alen   uint8
+       Slen   uint8
+       Data   [12]int8
+       raw    RawSockaddrDatalink
+}
+
+func (sa *SockaddrDatalink) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
+       if sa.Index == 0 {
+               return nil, 0, EINVAL
+       }
+       sa.raw.Len = sa.Len
+       sa.raw.Family = AF_LINK
+       sa.raw.Index = sa.Index
+       sa.raw.Type = sa.Type
+       sa.raw.Nlen = sa.Nlen
+       sa.raw.Alen = sa.Alen
+       sa.raw.Slen = sa.Slen
+       for i := 0; i < len(sa.raw.Data); i++ {
+               sa.raw.Data[i] = sa.Data[i]
+       }
+       return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrDatalink, nil
+}
+
+type RawSockaddrDatalink struct {
+       Len    uint8
+       Family uint8
+       Index  uint16
+       Type   uint8
+       Nlen   uint8
+       Alen   uint8
+       Slen   uint8
+       Data   [12]int8
+}
+
 type RawSockaddr struct {
        Len    uint8
        Family uint8
index c67550a011d3589eddcc79cd75f679923190848c..bbc6799e3e6bb4f2705f9a3cff248920cf0b0bb2 100644 (file)
@@ -17,3 +17,64 @@ func direntReclen(buf []byte) (uint64, bool) {
 func direntNamlen(buf []byte) (uint64, bool) {
        return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
 }
+
+func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {
+       var olen uintptr
+
+       // Get a list of all sysctl nodes below the given MIB by performing
+       // a sysctl for the given MIB with CTL_QUERY appended.
+       mib = append(mib, CTL_QUERY)
+       qnode := Sysctlnode{Flags: SYSCTL_VERS_1}
+       qp := (*byte)(unsafe.Pointer(&qnode))
+       sz := unsafe.Sizeof(qnode)
+       if err = sysctl(mib, nil, &olen, qp, sz); err != nil {
+               return nil, err
+       }
+
+       // Now that we know the size, get the actual nodes.
+       nodes = make([]Sysctlnode, olen/sz)
+       np := (*byte)(unsafe.Pointer(&nodes[0]))
+       if err = sysctl(mib, np, &olen, qp, sz); err != nil {
+               return nil, err
+       }
+
+       return nodes, nil
+}
+
+func nametomib(name string) (mib []_C_int, err error) {
+       // Split name into components.
+       var parts []string
+       last := 0
+       for i := 0; i < len(name); i++ {
+               if name[i] == '.' {
+                       parts = append(parts, name[last:i])
+                       last = i + 1
+               }
+       }
+       parts = append(parts, name[last:])
+
+       // Discover the nodes and construct the MIB OID.
+       for partno, part := range parts {
+               nodes, err := sysctlNodes(mib)
+               if err != nil {
+                       return nil, err
+               }
+               for _, node := range nodes {
+                       n := make([]byte, 0)
+                       for i := range node.Name {
+                               if node.Name[i] != 0 {
+                                       n = append(n, byte(node.Name[i]))
+                               }
+                       }
+                       if string(n) == part {
+                               mib = append(mib, _C_int(node.Num))
+                               break
+                       }
+               }
+               if len(mib) != partno+1 {
+                       return nil, EINVAL
+               }
+       }
+
+       return mib, nil
+}