|
@@ -655,7 +655,7 @@ type RawSockaddr struct {
|
|
|
|
|
|
|
|
type RawSockaddrAny struct {
|
|
type RawSockaddrAny struct {
|
|
|
Addr RawSockaddr
|
|
Addr RawSockaddr
|
|
|
- Pad [96]int8
|
|
|
|
|
|
|
+ Pad [100]int8
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type Sockaddr interface {
|
|
type Sockaddr interface {
|
|
@@ -704,19 +704,69 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
|
|
|
return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
|
|
return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+type RawSockaddrUnix struct {
|
|
|
|
|
+ Family uint16
|
|
|
|
|
+ Path [UNIX_PATH_MAX]int8
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
type SockaddrUnix struct {
|
|
type SockaddrUnix struct {
|
|
|
Name string
|
|
Name string
|
|
|
|
|
+ raw RawSockaddrUnix
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
|
|
func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
|
|
|
- // TODO(brainman): implement SockaddrUnix.sockaddr()
|
|
|
|
|
- return nil, 0, syscall.EWINDOWS
|
|
|
|
|
|
|
+ name := sa.Name
|
|
|
|
|
+ n := len(name)
|
|
|
|
|
+ if n > len(sa.raw.Path) {
|
|
|
|
|
+ return nil, 0, syscall.EINVAL
|
|
|
|
|
+ }
|
|
|
|
|
+ if n == len(sa.raw.Path) && name[0] != '@' {
|
|
|
|
|
+ return nil, 0, syscall.EINVAL
|
|
|
|
|
+ }
|
|
|
|
|
+ sa.raw.Family = AF_UNIX
|
|
|
|
|
+ for i := 0; i < n; i++ {
|
|
|
|
|
+ sa.raw.Path[i] = int8(name[i])
|
|
|
|
|
+ }
|
|
|
|
|
+ // length is family (uint16), name, NUL.
|
|
|
|
|
+ sl := int32(2)
|
|
|
|
|
+ if n > 0 {
|
|
|
|
|
+ sl += int32(n) + 1
|
|
|
|
|
+ }
|
|
|
|
|
+ if sa.raw.Path[0] == '@' {
|
|
|
|
|
+ sa.raw.Path[0] = 0
|
|
|
|
|
+ // Don't count trailing NUL for abstract address.
|
|
|
|
|
+ sl--
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return unsafe.Pointer(&sa.raw), sl, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
|
|
func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
|
|
|
switch rsa.Addr.Family {
|
|
switch rsa.Addr.Family {
|
|
|
case AF_UNIX:
|
|
case AF_UNIX:
|
|
|
- return nil, syscall.EWINDOWS
|
|
|
|
|
|
|
+ pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
|
|
|
|
|
+ sa := new(SockaddrUnix)
|
|
|
|
|
+ if pp.Path[0] == 0 {
|
|
|
|
|
+ // "Abstract" Unix domain socket.
|
|
|
|
|
+ // Rewrite leading NUL as @ for textual display.
|
|
|
|
|
+ // (This is the standard convention.)
|
|
|
|
|
+ // Not friendly to overwrite in place,
|
|
|
|
|
+ // but the callers below don't care.
|
|
|
|
|
+ pp.Path[0] = '@'
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Assume path ends at NUL.
|
|
|
|
|
+ // This is not technically the Linux semantics for
|
|
|
|
|
+ // abstract Unix domain sockets--they are supposed
|
|
|
|
|
+ // to be uninterpreted fixed-size binary blobs--but
|
|
|
|
|
+ // everyone uses this convention.
|
|
|
|
|
+ n := 0
|
|
|
|
|
+ for n < len(pp.Path) && pp.Path[n] != 0 {
|
|
|
|
|
+ n++
|
|
|
|
|
+ }
|
|
|
|
|
+ bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
|
|
|
|
|
+ sa.Name = string(bytes)
|
|
|
|
|
+ return sa, nil
|
|
|
|
|
|
|
|
case AF_INET:
|
|
case AF_INET:
|
|
|
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
|
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|