forked from libp2p/go-sockaddr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsockaddr_bsd.go
144 lines (131 loc) · 3.58 KB
/
sockaddr_bsd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// +build darwin dragonfly freebsd netbsd openbsd
package sockaddr
import (
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
func sockaddrToAny(sa unix.Sockaddr) (*unix.RawSockaddrAny, Socklen, error) {
if sa == nil {
return nil, 0, syscall.EINVAL
}
switch sa := sa.(type) {
case *unix.SockaddrInet4:
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, syscall.EINVAL
}
var raw unix.RawSockaddrInet4
raw.Len = unix.SizeofSockaddrInet4
raw.Family = unix.AF_INET
p := (*[2]byte)(unsafe.Pointer(&raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
raw.Addr[i] = sa.Addr[i]
}
return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil
case *unix.SockaddrInet6:
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, syscall.EINVAL
}
var raw unix.RawSockaddrInet6
raw.Len = unix.SizeofSockaddrInet6
raw.Family = unix.AF_INET6
p := (*[2]byte)(unsafe.Pointer(&raw.Port))
p[0] = byte(sa.Port >> 8)
p[1] = byte(sa.Port)
raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
raw.Addr[i] = sa.Addr[i]
}
return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil
case *unix.SockaddrUnix:
name := sa.Name
n := len(name)
var raw unix.RawSockaddrUnix
if n >= len(raw.Path) || n == 0 {
return nil, 0, syscall.EINVAL
}
raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
raw.Family = unix.AF_UNIX
for i := 0; i < n; i++ {
raw.Path[i] = int8(name[i])
}
return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), Socklen(raw.Len), nil
case *unix.SockaddrDatalink:
if sa.Index == 0 {
return nil, 0, syscall.EINVAL
}
var raw unix.RawSockaddrDatalink
raw.Len = sa.Len
raw.Family = unix.AF_LINK
raw.Index = sa.Index
raw.Type = sa.Type
raw.Nlen = sa.Nlen
raw.Alen = sa.Alen
raw.Slen = sa.Slen
for i := 0; i < len(raw.Data); i++ {
raw.Data[i] = sa.Data[i]
}
return (*unix.RawSockaddrAny)(unsafe.Pointer(&raw)), unix.SizeofSockaddrDatalink, nil
}
return nil, 0, syscall.EAFNOSUPPORT
}
func anyToSockaddr(rsa *unix.RawSockaddrAny) (unix.Sockaddr, error) {
if rsa == nil {
return nil, syscall.EINVAL
}
switch rsa.Addr.Family {
case unix.AF_LINK:
pp := (*unix.RawSockaddrDatalink)(unsafe.Pointer(rsa))
sa := new(unix.SockaddrDatalink)
sa.Len = pp.Len
sa.Family = pp.Family
sa.Index = pp.Index
sa.Type = pp.Type
sa.Nlen = pp.Nlen
sa.Alen = pp.Alen
sa.Slen = pp.Slen
for i := 0; i < len(sa.Data); i++ {
sa.Data[i] = pp.Data[i]
}
return sa, nil
case unix.AF_UNIX:
pp := (*unix.RawSockaddrUnix)(unsafe.Pointer(rsa))
if pp.Len < 3 || pp.Len > unix.SizeofSockaddrUnix {
return nil, syscall.EINVAL
}
sa := new(unix.SockaddrUnix)
n := int(pp.Len) - 3 // subtract leading Family, Len, terminating NUL
for i := 0; i < n; i++ {
if pp.Path[i] == 0 {
// found early NUL; assume Len is overestimating
n = i
break
}
}
bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
sa.Name = string(bytes)
return sa, nil
case unix.AF_INET:
pp := (*unix.RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(unix.SockaddrInet4)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
case unix.AF_INET6:
pp := (*unix.RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(unix.SockaddrInet6)
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
sa.Port = int(p[0])<<8 + int(p[1])
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
}
return nil, syscall.EAFNOSUPPORT
}