|
@@ -12,6 +12,8 @@
|
|
|
package unix
|
|
package unix
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
|
+ "encoding/binary"
|
|
|
|
|
+ "net"
|
|
|
"syscall"
|
|
"syscall"
|
|
|
"unsafe"
|
|
"unsafe"
|
|
|
)
|
|
)
|
|
@@ -710,6 +712,51 @@ func (sa *SockaddrXDP) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
|
|
return unsafe.Pointer(&sa.raw), SizeofSockaddrXDP, nil
|
|
return unsafe.Pointer(&sa.raw), SizeofSockaddrXDP, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// This constant mirrors the #define of PX_PROTO_OE in
|
|
|
|
|
+// linux/if_pppox.h. We're defining this by hand here instead of
|
|
|
|
|
+// autogenerating through mkerrors.sh because including
|
|
|
|
|
+// linux/if_pppox.h causes some declaration conflicts with other
|
|
|
|
|
+// includes (linux/if_pppox.h includes linux/in.h, which conflicts
|
|
|
|
|
+// with netinet/in.h). Given that we only need a single zero constant
|
|
|
|
|
+// out of that file, it's cleaner to just define it by hand here.
|
|
|
|
|
+const px_proto_oe = 0
|
|
|
|
|
+
|
|
|
|
|
+type SockaddrPPPoE struct {
|
|
|
|
|
+ SID uint16
|
|
|
|
|
+ Remote net.HardwareAddr
|
|
|
|
|
+ Dev string
|
|
|
|
|
+ raw RawSockaddrPPPoX
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
|
|
|
|
+ if len(sa.Remote) != 6 {
|
|
|
|
|
+ return nil, 0, EINVAL
|
|
|
|
|
+ }
|
|
|
|
|
+ if len(sa.Dev) > IFNAMSIZ-1 {
|
|
|
|
|
+ return nil, 0, EINVAL
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ *(*uint16)(unsafe.Pointer(&sa.raw[0])) = AF_PPPOX
|
|
|
|
|
+ // This next field is in host-endian byte order. We can't use the
|
|
|
|
|
+ // same unsafe pointer cast as above, because this value is not
|
|
|
|
|
+ // 32-bit aligned and some architectures don't allow unaligned
|
|
|
|
|
+ // access.
|
|
|
|
|
+ //
|
|
|
|
|
+ // However, the value of px_proto_oe is 0, so we can use
|
|
|
|
|
+ // encoding/binary helpers to write the bytes without worrying
|
|
|
|
|
+ // about the ordering.
|
|
|
|
|
+ binary.BigEndian.PutUint32(sa.raw[2:6], px_proto_oe)
|
|
|
|
|
+ // This field is deliberately big-endian, unlike the previous
|
|
|
|
|
+ // one. The kernel expects SID to be in network byte order.
|
|
|
|
|
+ binary.BigEndian.PutUint16(sa.raw[6:8], sa.SID)
|
|
|
|
|
+ copy(sa.raw[8:14], sa.Remote)
|
|
|
|
|
+ for i := 14; i < 14+IFNAMSIZ; i++ {
|
|
|
|
|
+ sa.raw[i] = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ copy(sa.raw[14:], sa.Dev)
|
|
|
|
|
+ return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|
|
switch rsa.Addr.Family {
|
|
switch rsa.Addr.Family {
|
|
|
case AF_NETLINK:
|
|
case AF_NETLINK:
|
|
@@ -820,6 +867,22 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
|
|
SharedUmemFD: pp.Shared_umem_fd,
|
|
SharedUmemFD: pp.Shared_umem_fd,
|
|
|
}
|
|
}
|
|
|
return sa, nil
|
|
return sa, nil
|
|
|
|
|
+ case AF_PPPOX:
|
|
|
|
|
+ pp := (*RawSockaddrPPPoX)(unsafe.Pointer(rsa))
|
|
|
|
|
+ if binary.BigEndian.Uint32(pp[2:6]) != px_proto_oe {
|
|
|
|
|
+ return nil, EINVAL
|
|
|
|
|
+ }
|
|
|
|
|
+ sa := &SockaddrPPPoE{
|
|
|
|
|
+ SID: binary.BigEndian.Uint16(pp[6:8]),
|
|
|
|
|
+ Remote: net.HardwareAddr(pp[8:14]),
|
|
|
|
|
+ }
|
|
|
|
|
+ for i := 14; i < 14+IFNAMSIZ; i++ {
|
|
|
|
|
+ if pp[i] == 0 {
|
|
|
|
|
+ sa.Dev = string(pp[14:i])
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return sa, nil
|
|
|
}
|
|
}
|
|
|
return nil, EAFNOSUPPORT
|
|
return nil, EAFNOSUPPORT
|
|
|
}
|
|
}
|