1// Copyright 2015 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 5package net 6 7import ( 8 "internal/testenv" 9 "os" 10 "os/exec" 11 "runtime" 12 "strconv" 13 "strings" 14 "testing" 15) 16 17var unixEnabledOnAIX bool 18 19func init() { 20 if runtime.GOOS == "aix" { 21 // Unix network isn't properly working on AIX 7.2 with 22 // Technical Level < 2. 23 // The information is retrieved only once in this init() 24 // instead of everytime testableNetwork is called. 25 out, _ := exec.Command("oslevel", "-s").Output() 26 if len(out) >= len("7200-XX-ZZ-YYMM") { // AIX 7.2, Tech Level XX, Service Pack ZZ, date YYMM 27 aixVer := string(out[:4]) 28 tl, _ := strconv.Atoi(string(out[5:7])) 29 unixEnabledOnAIX = aixVer > "7200" || (aixVer == "7200" && tl >= 2) 30 } 31 } 32} 33 34// testableNetwork reports whether network is testable on the current 35// platform configuration. 36func testableNetwork(network string) bool { 37 net, _, _ := strings.Cut(network, ":") 38 switch net { 39 case "ip+nopriv": 40 case "ip", "ip4", "ip6": 41 switch runtime.GOOS { 42 case "plan9": 43 return false 44 default: 45 if os.Getuid() != 0 { 46 return false 47 } 48 } 49 case "unix", "unixgram": 50 switch runtime.GOOS { 51 case "android", "ios", "plan9", "windows": 52 return false 53 case "aix": 54 return unixEnabledOnAIX 55 } 56 case "unixpacket": 57 switch runtime.GOOS { 58 case "aix", "android", "darwin", "ios", "plan9", "windows": 59 return false 60 } 61 } 62 switch net { 63 case "tcp4", "udp4", "ip4": 64 if !supportsIPv4() { 65 return false 66 } 67 case "tcp6", "udp6", "ip6": 68 if !supportsIPv6() { 69 return false 70 } 71 } 72 return true 73} 74 75// testableAddress reports whether address of network is testable on 76// the current platform configuration. 77func testableAddress(network, address string) bool { 78 switch net, _, _ := strings.Cut(network, ":"); net { 79 case "unix", "unixgram", "unixpacket": 80 // Abstract unix domain sockets, a Linux-ism. 81 if address[0] == '@' && runtime.GOOS != "linux" { 82 return false 83 } 84 } 85 return true 86} 87 88// testableListenArgs reports whether arguments are testable on the 89// current platform configuration. 90func testableListenArgs(network, address, client string) bool { 91 if !testableNetwork(network) || !testableAddress(network, address) { 92 return false 93 } 94 95 var err error 96 var addr Addr 97 switch net, _, _ := strings.Cut(network, ":"); net { 98 case "tcp", "tcp4", "tcp6": 99 addr, err = ResolveTCPAddr("tcp", address) 100 case "udp", "udp4", "udp6": 101 addr, err = ResolveUDPAddr("udp", address) 102 case "ip", "ip4", "ip6": 103 addr, err = ResolveIPAddr("ip", address) 104 default: 105 return true 106 } 107 if err != nil { 108 return false 109 } 110 var ip IP 111 var wildcard bool 112 switch addr := addr.(type) { 113 case *TCPAddr: 114 ip = addr.IP 115 wildcard = addr.isWildcard() 116 case *UDPAddr: 117 ip = addr.IP 118 wildcard = addr.isWildcard() 119 case *IPAddr: 120 ip = addr.IP 121 wildcard = addr.isWildcard() 122 } 123 124 // Test wildcard IP addresses. 125 if wildcard && !testenv.HasExternalNetwork() { 126 return false 127 } 128 129 // Test functionality of IPv4 communication using AF_INET and 130 // IPv6 communication using AF_INET6 sockets. 131 if !supportsIPv4() && ip.To4() != nil { 132 return false 133 } 134 if !supportsIPv6() && ip.To16() != nil && ip.To4() == nil { 135 return false 136 } 137 cip := ParseIP(client) 138 if cip != nil { 139 if !supportsIPv4() && cip.To4() != nil { 140 return false 141 } 142 if !supportsIPv6() && cip.To16() != nil && cip.To4() == nil { 143 return false 144 } 145 } 146 147 // Test functionality of IPv4 communication using AF_INET6 148 // sockets. 149 if !supportsIPv4map() && supportsIPv4() && (network == "tcp" || network == "udp" || network == "ip") && wildcard { 150 // At this point, we prefer IPv4 when ip is nil. 151 // See favoriteAddrFamily for further information. 152 if ip.To16() != nil && ip.To4() == nil && cip.To4() != nil { // a pair of IPv6 server and IPv4 client 153 return false 154 } 155 if (ip.To4() != nil || ip == nil) && cip.To16() != nil && cip.To4() == nil { // a pair of IPv4 server and IPv6 client 156 return false 157 } 158 } 159 160 return true 161} 162 163func condFatalf(t *testing.T, network string, format string, args ...any) { 164 t.Helper() 165 // A few APIs like File and Read/WriteMsg{UDP,IP} are not 166 // fully implemented yet on Plan 9 and Windows. 167 switch runtime.GOOS { 168 case "windows", "js", "wasip1": 169 if network == "file+net" { 170 t.Logf(format, args...) 171 return 172 } 173 case "plan9": 174 t.Logf(format, args...) 175 return 176 } 177 t.Fatalf(format, args...) 178} 179