lif: use of nativeEndian to make API endian agnostic

Change-Id: Ib5e3eac7c98d07c286dfb49fced89ac90bd0aafc
Reviewed-on: https://go-review.googlesource.com/37916
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matt Layher <mdlayher@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/lif/address.go b/lif/address.go
index f9b34ae..afb957f 100644
--- a/lif/address.go
+++ b/lif/address.go
@@ -67,7 +67,7 @@
 				continue
 			}
 			sa := (*sockaddrStorage)(unsafe.Pointer(&lifr.Lifru[0]))
-			l := int(littleEndian.Uint32(lifr.Lifru1[:4]))
+			l := int(nativeEndian.Uint32(lifr.Lifru1[:4]))
 			if l == 0 {
 				continue
 			}
@@ -77,7 +77,7 @@
 				copy(a.IP[:], lifr.Lifru[4:8])
 				as = append(as, a)
 			case sysAF_INET6:
-				a := &Inet6Addr{PrefixLen: l, ZoneID: int(littleEndian.Uint32(lifr.Lifru[24:28]))}
+				a := &Inet6Addr{PrefixLen: l, ZoneID: int(nativeEndian.Uint32(lifr.Lifru[24:28]))}
 				copy(a.IP[:], lifr.Lifru[8:24])
 				as = append(as, a)
 			}
diff --git a/lif/binary.go b/lif/binary.go
index aade9ea..738a94f 100644
--- a/lif/binary.go
+++ b/lif/binary.go
@@ -12,7 +12,10 @@
 // library. Therefore the package set used in the package must be the
 // same as net package.
 
-var littleEndian binaryLittleEndian
+var (
+	littleEndian binaryLittleEndian
+	bigEndian    binaryBigEndian
+)
 
 type binaryByteOrder interface {
 	Uint16([]byte) uint16
@@ -66,3 +69,47 @@
 	b[6] = byte(v >> 48)
 	b[7] = byte(v >> 56)
 }
+
+type binaryBigEndian struct{}
+
+func (binaryBigEndian) Uint16(b []byte) uint16 {
+	_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+	return uint16(b[1]) | uint16(b[0])<<8
+}
+
+func (binaryBigEndian) PutUint16(b []byte, v uint16) {
+	_ = b[1] // early bounds check to guarantee safety of writes below
+	b[0] = byte(v >> 8)
+	b[1] = byte(v)
+}
+
+func (binaryBigEndian) Uint32(b []byte) uint32 {
+	_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+	return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+}
+
+func (binaryBigEndian) PutUint32(b []byte, v uint32) {
+	_ = b[3] // early bounds check to guarantee safety of writes below
+	b[0] = byte(v >> 24)
+	b[1] = byte(v >> 16)
+	b[2] = byte(v >> 8)
+	b[3] = byte(v)
+}
+
+func (binaryBigEndian) Uint64(b []byte) uint64 {
+	_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+	return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+		uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+}
+
+func (binaryBigEndian) PutUint64(b []byte, v uint64) {
+	_ = b[7] // early bounds check to guarantee safety of writes below
+	b[0] = byte(v >> 56)
+	b[1] = byte(v >> 48)
+	b[2] = byte(v >> 40)
+	b[3] = byte(v >> 32)
+	b[4] = byte(v >> 24)
+	b[5] = byte(v >> 16)
+	b[6] = byte(v >> 8)
+	b[7] = byte(v)
+}
diff --git a/lif/link.go b/lif/link.go
index 76fa6c6..fce6b21 100644
--- a/lif/link.go
+++ b/lif/link.go
@@ -31,15 +31,15 @@
 	}
 	ioc := int64(sysSIOCGLIFINDEX)
 	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
-		ll.Index = int(littleEndian.Uint32(lifr.Lifru[:4]))
+		ll.Index = int(nativeEndian.Uint32(lifr.Lifru[:4]))
 	}
 	ioc = int64(sysSIOCGLIFFLAGS)
 	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
-		ll.Flags = int(littleEndian.Uint64(lifr.Lifru[:8]))
+		ll.Flags = int(nativeEndian.Uint64(lifr.Lifru[:8]))
 	}
 	ioc = int64(sysSIOCGLIFMTU)
 	if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
-		ll.MTU = int(littleEndian.Uint32(lifr.Lifru[:4]))
+		ll.MTU = int(nativeEndian.Uint32(lifr.Lifru[:4]))
 	}
 	switch ll.Type {
 	case sysIFT_IPV4, sysIFT_IPV6, sysIFT_6TO4:
@@ -84,7 +84,11 @@
 		b := make([]byte, lifn.Count*sizeofLifreq)
 		lifc.Family = uint16(ep.af)
 		lifc.Len = lifn.Count * sizeofLifreq
-		littleEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
+		if len(lifc.Lifcu) == 8 {
+			nativeEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
+		} else {
+			nativeEndian.PutUint32(lifc.Lifcu[:], uint32(uintptr(unsafe.Pointer(&b[0]))))
+		}
 		ioc = int64(sysSIOCGLIFCONF)
 		if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifc)); err != nil {
 			continue
diff --git a/lif/sys.go b/lif/sys.go
new file mode 100644
index 0000000..c896041
--- /dev/null
+++ b/lif/sys.go
@@ -0,0 +1,21 @@
+// Copyright 2017 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 solaris
+
+package lif
+
+import "unsafe"
+
+var nativeEndian binaryByteOrder
+
+func init() {
+	i := uint32(1)
+	b := (*[4]byte)(unsafe.Pointer(&i))
+	if b[0] == 1 {
+		nativeEndian = littleEndian
+	} else {
+		nativeEndian = bigEndian
+	}
+}