Source file
src/net/iprawsock_posix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "syscall"
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: zoneCache.name(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) sockaddr(family int) (syscall.Sockaddr, error) {
35 if a == nil {
36 return nil, nil
37 }
38 return ipToSockaddr(family, a.IP, 0, a.Zone)
39 }
40
41 func (a *IPAddr) toLocal(net string) sockaddr {
42 return &IPAddr{loopbackIP(net), a.Zone}
43 }
44
45 func (c *IPConn) readFrom(b []byte) (int, *IPAddr, error) {
46
47
48 var addr *IPAddr
49 n, sa, err := c.fd.readFrom(b)
50 switch sa := sa.(type) {
51 case *syscall.SockaddrInet4:
52 addr = &IPAddr{IP: sa.Addr[0:]}
53 n = stripIPv4Header(n, b)
54 case *syscall.SockaddrInet6:
55 addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneCache.name(int(sa.ZoneId))}
56 }
57 return n, addr, err
58 }
59
60 func stripIPv4Header(n int, b []byte) int {
61 if len(b) < 20 {
62 return n
63 }
64 l := int(b[0]&0x0f) << 2
65 if 20 > l || l > len(b) {
66 return n
67 }
68 if b[0]>>4 != 4 {
69 return n
70 }
71 copy(b, b[l:])
72 return n - l
73 }
74
75 func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
76 var sa syscall.Sockaddr
77 n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0)
78 switch sa := sa.(type) {
79 case *syscall.SockaddrInet4:
80 addr = &IPAddr{IP: sa.Addr[0:]}
81 case *syscall.SockaddrInet6:
82 addr = &IPAddr{IP: sa.Addr[0:], Zone: zoneCache.name(int(sa.ZoneId))}
83 }
84 return
85 }
86
87 func (c *IPConn) writeTo(b []byte, addr *IPAddr) (int, error) {
88 if c.fd.isConnected {
89 return 0, ErrWriteToConnected
90 }
91 if addr == nil {
92 return 0, errMissingAddress
93 }
94 sa, err := addr.sockaddr(c.fd.family)
95 if err != nil {
96 return 0, err
97 }
98 return c.fd.writeTo(b, sa)
99 }
100
101 func (c *IPConn) writeMsg(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
102 if c.fd.isConnected {
103 return 0, 0, ErrWriteToConnected
104 }
105 if addr == nil {
106 return 0, 0, errMissingAddress
107 }
108 sa, err := addr.sockaddr(c.fd.family)
109 if err != nil {
110 return 0, 0, err
111 }
112 return c.fd.writeMsg(b, oob, sa)
113 }
114
115 func (sd *sysDialer) dialIP(ctx context.Context, laddr, raddr *IPAddr) (*IPConn, error) {
116 network, proto, err := parseNetwork(ctx, sd.network, true)
117 if err != nil {
118 return nil, err
119 }
120 switch network {
121 case "ip", "ip4", "ip6":
122 default:
123 return nil, UnknownNetworkError(sd.network)
124 }
125 ctrlCtxFn := sd.Dialer.ControlContext
126 if ctrlCtxFn == nil && sd.Dialer.Control != nil {
127 ctrlCtxFn = func(ctx context.Context, network, address string, c syscall.RawConn) error {
128 return sd.Dialer.Control(network, address, c)
129 }
130 }
131 fd, err := internetSocket(ctx, network, laddr, raddr, syscall.SOCK_RAW, proto, "dial", ctrlCtxFn)
132 if err != nil {
133 return nil, err
134 }
135 return newIPConn(fd), nil
136 }
137
138 func (sl *sysListener) listenIP(ctx context.Context, laddr *IPAddr) (*IPConn, error) {
139 network, proto, err := parseNetwork(ctx, sl.network, true)
140 if err != nil {
141 return nil, err
142 }
143 switch network {
144 case "ip", "ip4", "ip6":
145 default:
146 return nil, UnknownNetworkError(sl.network)
147 }
148 var ctrlCtxFn func(ctx context.Context, network, address string, c syscall.RawConn) error
149 if sl.ListenConfig.Control != nil {
150 ctrlCtxFn = func(ctx context.Context, network, address string, c syscall.RawConn) error {
151 return sl.ListenConfig.Control(network, address, c)
152 }
153 }
154 fd, err := internetSocket(ctx, network, laddr, nil, syscall.SOCK_RAW, proto, "listen", ctrlCtxFn)
155 if err != nil {
156 return nil, err
157 }
158 return newIPConn(fd), nil
159 }
160
View as plain text