]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgo/go/net/iprawsock_posix.go
libgo: update to Go1.14beta1
[thirdparty/gcc.git] / libgo / go / 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 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris 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)
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 fd, err := internetSocket(ctx, network, laddr, raddr, syscall.SOCK_RAW, proto, "dial", sd.Dialer.Control)
126 if err != nil {
127 return nil, err
128 }
129 return newIPConn(fd), nil
130 }
131
132 func (sl *sysListener) listenIP(ctx context.Context, laddr *IPAddr) (*IPConn, error) {
133 network, proto, err := parseNetwork(ctx, sl.network, true)
134 if err != nil {
135 return nil, err
136 }
137 switch network {
138 case "ip", "ip4", "ip6":
139 default:
140 return nil, UnknownNetworkError(sl.network)
141 }
142 fd, err := internetSocket(ctx, network, laddr, nil, syscall.SOCK_RAW, proto, "listen", sl.ListenConfig.Control)
143 if err != nil {
144 return nil, err
145 }
146 return newIPConn(fd), nil
147 }