runtime: correct facilities names in s390 CPU support
[gcc.git] / libgo / go / net / rawconn_unix_test.go
1 // Copyright 2017 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 linux netbsd openbsd solaris
6
7 package net
8
9 import (
10 "errors"
11 "syscall"
12 )
13
14 func readRawConn(c syscall.RawConn, b []byte) (int, error) {
15 var operr error
16 var n int
17 err := c.Read(func(s uintptr) bool {
18 n, operr = syscall.Read(int(s), b)
19 if operr == syscall.EAGAIN {
20 return false
21 }
22 return true
23 })
24 if err != nil {
25 return n, err
26 }
27 if operr != nil {
28 return n, operr
29 }
30 return n, nil
31 }
32
33 func writeRawConn(c syscall.RawConn, b []byte) error {
34 var operr error
35 err := c.Write(func(s uintptr) bool {
36 _, operr = syscall.Write(int(s), b)
37 if operr == syscall.EAGAIN {
38 return false
39 }
40 return true
41 })
42 if err != nil {
43 return err
44 }
45 if operr != nil {
46 return operr
47 }
48 return nil
49 }
50
51 func controlRawConn(c syscall.RawConn, addr Addr) error {
52 var operr error
53 fn := func(s uintptr) {
54 _, operr = syscall.GetsockoptInt(int(s), syscall.SOL_SOCKET, syscall.SO_REUSEADDR)
55 if operr != nil {
56 return
57 }
58 switch addr := addr.(type) {
59 case *TCPAddr:
60 // There's no guarantee that IP-level socket
61 // options work well with dual stack sockets.
62 // A simple solution would be to take a look
63 // at the bound address to the raw connection
64 // and to classify the address family of the
65 // underlying socket by the bound address:
66 //
67 // - When IP.To16() != nil and IP.To4() == nil,
68 // we can assume that the raw connection
69 // consists of an IPv6 socket using only
70 // IPv6 addresses.
71 //
72 // - When IP.To16() == nil and IP.To4() != nil,
73 // the raw connection consists of an IPv4
74 // socket using only IPv4 addresses.
75 //
76 // - Otherwise, the raw connection is a dual
77 // stack socket, an IPv6 socket using IPv6
78 // addresses including IPv4-mapped or
79 // IPv4-embedded IPv6 addresses.
80 if addr.IP.To16() != nil && addr.IP.To4() == nil {
81 operr = syscall.SetsockoptInt(int(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
82 } else if addr.IP.To16() == nil && addr.IP.To4() != nil {
83 operr = syscall.SetsockoptInt(int(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
84 }
85 }
86 }
87 if err := c.Control(fn); err != nil {
88 return err
89 }
90 if operr != nil {
91 return operr
92 }
93 return nil
94 }
95
96 func controlOnConnSetup(network string, address string, c syscall.RawConn) error {
97 var operr error
98 var fn func(uintptr)
99 switch network {
100 case "tcp", "udp", "ip":
101 return errors.New("ambiguous network: " + network)
102 case "unix", "unixpacket", "unixgram":
103 fn = func(s uintptr) {
104 _, operr = syscall.GetsockoptInt(int(s), syscall.SOL_SOCKET, syscall.SO_ERROR)
105 }
106 default:
107 switch network[len(network)-1] {
108 case '4':
109 fn = func(s uintptr) {
110 operr = syscall.SetsockoptInt(int(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
111 }
112 case '6':
113 fn = func(s uintptr) {
114 operr = syscall.SetsockoptInt(int(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
115 }
116 default:
117 return errors.New("unknown network: " + network)
118 }
119 }
120 if err := c.Control(fn); err != nil {
121 return err
122 }
123 if operr != nil {
124 return operr
125 }
126 return nil
127 }