]> Cypherpunks.ru repositories - gostls13.git/blob - src/net/iprawsock_posix.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / net / iprawsock_posix.go
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 //go:build unix || js || wasip1 || windows
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         // TODO(cw,rsc): consider using readv if we know the family
47         // type to avoid the header trim/copy
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(cxt 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(cxt context.Context, network, address string, c syscall.RawConn) error
149         if sl.ListenConfig.Control != nil {
150                 ctrlCtxFn = func(cxt 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 }