Source file src/pkg/net/iprawsock_posix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "syscall"
11 "time"
12 )
13
14 func sockaddrToIP(sa syscall.Sockaddr) Addr {
15 switch sa := sa.(type) {
16 case *syscall.SockaddrInet4:
17 return &IPAddr{IP: sa.Addr[0:]}
18 case *syscall.SockaddrInet6:
19 return &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
20 }
21 return nil
22 }
23
24 func (a *IPAddr) family() int {
25 if a == nil || len(a.IP) <= IPv4len {
26 return syscall.AF_INET
27 }
28 if a.IP.To4() != nil {
29 return syscall.AF_INET
30 }
31 return syscall.AF_INET6
32 }
33
34 func (a *IPAddr) isWildcard() bool {
35 if a == nil || a.IP == nil {
36 return true
37 }
38 return a.IP.IsUnspecified()
39 }
40
41 func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
42 return ipToSockaddr(family, a.IP, 0, a.Zone)
43 }
44
45 func (a *IPAddr) toAddr() sockaddr {
46 if a == nil {
47 return nil
48 }
49 return a
50 }
51
52
53
54 type IPConn struct {
55 conn
56 }
57
58 func newIPConn(fd *netFD) *IPConn { return &IPConn{conn{fd}} }
59
60
61
62
63
64
65
66
67 func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
68 if !c.ok() {
69 return 0, nil, syscall.EINVAL
70 }
71
72
73 var addr *IPAddr
74 n, sa, err := c.fd.ReadFrom(b)
75 switch sa := sa.(type) {
76 case *syscall.SockaddrInet4:
77 addr = &IPAddr{IP: sa.Addr[0:]}
78 if len(b) >= IPv4len {
79 hsize := (int(b[0]) & 0xf) * 4
80 copy(b, b[hsize:])
81 n -= hsize
82 }
83 case *syscall.SockaddrInet6:
84 addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
85 }
86 return n, addr, err
87 }
88
89
90 func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
91 if !c.ok() {
92 return 0, nil, syscall.EINVAL
93 }
94 n, addr, err := c.ReadFromIP(b)
95 return n, addr.toAddr(), err
96 }
97
98
99
100
101
102 func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
103 if !c.ok() {
104 return 0, 0, 0, nil, syscall.EINVAL
105 }
106 var sa syscall.Sockaddr
107 n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
108 switch sa := sa.(type) {
109 case *syscall.SockaddrInet4:
110 addr = &IPAddr{IP: sa.Addr[0:]}
111 case *syscall.SockaddrInet6:
112 addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneToString(int(sa.ZoneId))}
113 }
114 return
115 }
116
117
118
119
120
121
122
123
124 func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
125 if !c.ok() {
126 return 0, syscall.EINVAL
127 }
128 sa, err := addr.sockaddr(c.fd.family)
129 if err != nil {
130 return 0, &OpError{"write", c.fd.net, addr, err}
131 }
132 return c.fd.WriteTo(b, sa)
133 }
134
135
136 func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
137 if !c.ok() {
138 return 0, syscall.EINVAL
139 }
140 a, ok := addr.(*IPAddr)
141 if !ok {
142 return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
143 }
144 return c.WriteToIP(b, a)
145 }
146
147
148
149
150 func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
151 if !c.ok() {
152 return 0, 0, syscall.EINVAL
153 }
154 sa, err := addr.sockaddr(c.fd.family)
155 if err != nil {
156 return 0, 0, &OpError{"write", c.fd.net, addr, err}
157 }
158 return c.fd.WriteMsg(b, oob, sa)
159 }
160
161
162
163
164 func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
165 return dialIP(netProto, laddr, raddr, noDeadline)
166 }
167
168 func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
169 net, proto, err := parseNetwork(netProto)
170 if err != nil {
171 return nil, err
172 }
173 switch net {
174 case "ip", "ip4", "ip6":
175 default:
176 return nil, UnknownNetworkError(netProto)
177 }
178 if raddr == nil {
179 return nil, &OpError{"dial", netProto, nil, errMissingAddress}
180 }
181 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
182 if err != nil {
183 return nil, err
184 }
185 return newIPConn(fd), nil
186 }
187
188
189
190
191
192 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
193 net, proto, err := parseNetwork(netProto)
194 if err != nil {
195 return nil, err
196 }
197 switch net {
198 case "ip", "ip4", "ip6":
199 default:
200 return nil, UnknownNetworkError(netProto)
201 }
202 fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
203 if err != nil {
204 return nil, err
205 }
206 return newIPConn(fd), nil
207 }
View as plain text