PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/gofrontend/libgo/go/net/listen_test.go

http://github.com/axw/llgo
Go | 685 lines | 554 code | 58 blank | 73 comment | 213 complexity | 457de78f7aad3bbd538bf6196c4892b7 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. // Copyright 2011 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. // +build !plan9
  5. package net
  6. import (
  7. "fmt"
  8. "os"
  9. "runtime"
  10. "syscall"
  11. "testing"
  12. )
  13. func (ln *TCPListener) port() string {
  14. _, port, err := SplitHostPort(ln.Addr().String())
  15. if err != nil {
  16. return ""
  17. }
  18. return port
  19. }
  20. func (c *UDPConn) port() string {
  21. _, port, err := SplitHostPort(c.LocalAddr().String())
  22. if err != nil {
  23. return ""
  24. }
  25. return port
  26. }
  27. var tcpListenerTests = []struct {
  28. network string
  29. address string
  30. }{
  31. {"tcp", ""},
  32. {"tcp", "0.0.0.0"},
  33. {"tcp", "::ffff:0.0.0.0"},
  34. {"tcp", "::"},
  35. {"tcp", "127.0.0.1"},
  36. {"tcp", "::ffff:127.0.0.1"},
  37. {"tcp", "::1"},
  38. {"tcp4", ""},
  39. {"tcp4", "0.0.0.0"},
  40. {"tcp4", "::ffff:0.0.0.0"},
  41. {"tcp4", "127.0.0.1"},
  42. {"tcp4", "::ffff:127.0.0.1"},
  43. {"tcp6", ""},
  44. {"tcp6", "::"},
  45. {"tcp6", "::1"},
  46. }
  47. // TestTCPListener tests both single and double listen to a test
  48. // listener with same address family, same listening address and
  49. // same port.
  50. func TestTCPListener(t *testing.T) {
  51. switch runtime.GOOS {
  52. case "plan9":
  53. t.Skipf("not supported on %s", runtime.GOOS)
  54. }
  55. for _, tt := range tcpListenerTests {
  56. if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
  57. t.Logf("skipping %s test", tt.network+" "+tt.address)
  58. continue
  59. }
  60. ln1, err := Listen(tt.network, JoinHostPort(tt.address, "0"))
  61. if err != nil {
  62. t.Fatal(err)
  63. }
  64. if err := checkFirstListener(tt.network, ln1); err != nil {
  65. ln1.Close()
  66. t.Fatal(err)
  67. }
  68. ln2, err := Listen(tt.network, JoinHostPort(tt.address, ln1.(*TCPListener).port()))
  69. if err == nil {
  70. ln2.Close()
  71. }
  72. if err := checkSecondListener(tt.network, tt.address, err); err != nil {
  73. ln1.Close()
  74. t.Fatal(err)
  75. }
  76. ln1.Close()
  77. }
  78. }
  79. var udpListenerTests = []struct {
  80. network string
  81. address string
  82. }{
  83. {"udp", ""},
  84. {"udp", "0.0.0.0"},
  85. {"udp", "::ffff:0.0.0.0"},
  86. {"udp", "::"},
  87. {"udp", "127.0.0.1"},
  88. {"udp", "::ffff:127.0.0.1"},
  89. {"udp", "::1"},
  90. {"udp4", ""},
  91. {"udp4", "0.0.0.0"},
  92. {"udp4", "::ffff:0.0.0.0"},
  93. {"udp4", "127.0.0.1"},
  94. {"udp4", "::ffff:127.0.0.1"},
  95. {"udp6", ""},
  96. {"udp6", "::"},
  97. {"udp6", "::1"},
  98. }
  99. // TestUDPListener tests both single and double listen to a test
  100. // listener with same address family, same listening address and
  101. // same port.
  102. func TestUDPListener(t *testing.T) {
  103. switch runtime.GOOS {
  104. case "plan9":
  105. t.Skipf("not supported on %s", runtime.GOOS)
  106. }
  107. for _, tt := range udpListenerTests {
  108. if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
  109. t.Logf("skipping %s test", tt.network+" "+tt.address)
  110. continue
  111. }
  112. c1, err := ListenPacket(tt.network, JoinHostPort(tt.address, "0"))
  113. if err != nil {
  114. t.Fatal(err)
  115. }
  116. if err := checkFirstListener(tt.network, c1); err != nil {
  117. c1.Close()
  118. t.Fatal(err)
  119. }
  120. c2, err := ListenPacket(tt.network, JoinHostPort(tt.address, c1.(*UDPConn).port()))
  121. if err == nil {
  122. c2.Close()
  123. }
  124. if err := checkSecondListener(tt.network, tt.address, err); err != nil {
  125. c1.Close()
  126. t.Fatal(err)
  127. }
  128. c1.Close()
  129. }
  130. }
  131. var dualStackTCPListenerTests = []struct {
  132. network1, address1 string // first listener
  133. network2, address2 string // second listener
  134. xerr error // expected error value, nil or other
  135. }{
  136. // Test cases and expected results for the attemping 2nd listen on the same port
  137. // 1st listen 2nd listen darwin freebsd linux openbsd
  138. // ------------------------------------------------------------------------------------
  139. // "tcp" "" "tcp" "" - - - -
  140. // "tcp" "" "tcp" "0.0.0.0" - - - -
  141. // "tcp" "0.0.0.0" "tcp" "" - - - -
  142. // ------------------------------------------------------------------------------------
  143. // "tcp" "" "tcp" "[::]" - - - ok
  144. // "tcp" "[::]" "tcp" "" - - - ok
  145. // "tcp" "0.0.0.0" "tcp" "[::]" - - - ok
  146. // "tcp" "[::]" "tcp" "0.0.0.0" - - - ok
  147. // "tcp" "[::ffff:0.0.0.0]" "tcp" "[::]" - - - ok
  148. // "tcp" "[::]" "tcp" "[::ffff:0.0.0.0]" - - - ok
  149. // ------------------------------------------------------------------------------------
  150. // "tcp4" "" "tcp6" "" ok ok ok ok
  151. // "tcp6" "" "tcp4" "" ok ok ok ok
  152. // "tcp4" "0.0.0.0" "tcp6" "[::]" ok ok ok ok
  153. // "tcp6" "[::]" "tcp4" "0.0.0.0" ok ok ok ok
  154. // ------------------------------------------------------------------------------------
  155. // "tcp" "127.0.0.1" "tcp" "[::1]" ok ok ok ok
  156. // "tcp" "[::1]" "tcp" "127.0.0.1" ok ok ok ok
  157. // "tcp4" "127.0.0.1" "tcp6" "[::1]" ok ok ok ok
  158. // "tcp6" "[::1]" "tcp4" "127.0.0.1" ok ok ok ok
  159. //
  160. // Platform default configurations:
  161. // darwin, kernel version 11.3.0
  162. // net.inet6.ip6.v6only=0 (overridable by sysctl or IPV6_V6ONLY option)
  163. // freebsd, kernel version 8.2
  164. // net.inet6.ip6.v6only=1 (overridable by sysctl or IPV6_V6ONLY option)
  165. // linux, kernel version 3.0.0
  166. // net.ipv6.bindv6only=0 (overridable by sysctl or IPV6_V6ONLY option)
  167. // openbsd, kernel version 5.0
  168. // net.inet6.ip6.v6only=1 (overriding is prohibited)
  169. {"tcp", "", "tcp", "", syscall.EADDRINUSE},
  170. {"tcp", "", "tcp", "0.0.0.0", syscall.EADDRINUSE},
  171. {"tcp", "0.0.0.0", "tcp", "", syscall.EADDRINUSE},
  172. {"tcp", "", "tcp", "::", syscall.EADDRINUSE},
  173. {"tcp", "::", "tcp", "", syscall.EADDRINUSE},
  174. {"tcp", "0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
  175. {"tcp", "::", "tcp", "0.0.0.0", syscall.EADDRINUSE},
  176. {"tcp", "::ffff:0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
  177. {"tcp", "::", "tcp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
  178. {"tcp4", "", "tcp6", "", nil},
  179. {"tcp6", "", "tcp4", "", nil},
  180. {"tcp4", "0.0.0.0", "tcp6", "::", nil},
  181. {"tcp6", "::", "tcp4", "0.0.0.0", nil},
  182. {"tcp", "127.0.0.1", "tcp", "::1", nil},
  183. {"tcp", "::1", "tcp", "127.0.0.1", nil},
  184. {"tcp4", "127.0.0.1", "tcp6", "::1", nil},
  185. {"tcp6", "::1", "tcp4", "127.0.0.1", nil},
  186. }
  187. // TestDualStackTCPListener tests both single and double listen
  188. // to a test listener with various address families, different
  189. // listening address and same port.
  190. func TestDualStackTCPListener(t *testing.T) {
  191. switch runtime.GOOS {
  192. case "dragonfly", "nacl", "plan9": // re-enable on dragonfly once the new IP control block management has landed
  193. t.Skipf("not supported on %s", runtime.GOOS)
  194. }
  195. if !supportsIPv4 || !supportsIPv6 {
  196. t.Skip("both IPv4 and IPv6 are required")
  197. }
  198. for _, tt := range dualStackTCPListenerTests {
  199. if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
  200. t.Logf("skipping %s test", tt.network1+" "+tt.address1)
  201. continue
  202. }
  203. if !supportsIPv4map && differentWildcardAddr(tt.address1, tt.address2) {
  204. tt.xerr = nil
  205. }
  206. var firstErr, secondErr error
  207. for i := 0; i < 5; i++ {
  208. lns, err := newDualStackListener()
  209. if err != nil {
  210. t.Fatal(err)
  211. }
  212. port := lns[0].port()
  213. for _, ln := range lns {
  214. ln.Close()
  215. }
  216. var ln1 Listener
  217. ln1, firstErr = Listen(tt.network1, JoinHostPort(tt.address1, port))
  218. if firstErr != nil {
  219. continue
  220. }
  221. if err := checkFirstListener(tt.network1, ln1); err != nil {
  222. ln1.Close()
  223. t.Fatal(err)
  224. }
  225. ln2, err := Listen(tt.network2, JoinHostPort(tt.address2, ln1.(*TCPListener).port()))
  226. if err == nil {
  227. ln2.Close()
  228. }
  229. if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
  230. ln1.Close()
  231. continue
  232. }
  233. ln1.Close()
  234. break
  235. }
  236. if firstErr != nil {
  237. t.Error(firstErr)
  238. }
  239. if secondErr != nil {
  240. t.Error(secondErr)
  241. }
  242. }
  243. }
  244. var dualStackUDPListenerTests = []struct {
  245. network1, address1 string // first listener
  246. network2, address2 string // second listener
  247. xerr error // expected error value, nil or other
  248. }{
  249. {"udp", "", "udp", "", syscall.EADDRINUSE},
  250. {"udp", "", "udp", "0.0.0.0", syscall.EADDRINUSE},
  251. {"udp", "0.0.0.0", "udp", "", syscall.EADDRINUSE},
  252. {"udp", "", "udp", "::", syscall.EADDRINUSE},
  253. {"udp", "::", "udp", "", syscall.EADDRINUSE},
  254. {"udp", "0.0.0.0", "udp", "::", syscall.EADDRINUSE},
  255. {"udp", "::", "udp", "0.0.0.0", syscall.EADDRINUSE},
  256. {"udp", "::ffff:0.0.0.0", "udp", "::", syscall.EADDRINUSE},
  257. {"udp", "::", "udp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
  258. {"udp4", "", "udp6", "", nil},
  259. {"udp6", "", "udp4", "", nil},
  260. {"udp4", "0.0.0.0", "udp6", "::", nil},
  261. {"udp6", "::", "udp4", "0.0.0.0", nil},
  262. {"udp", "127.0.0.1", "udp", "::1", nil},
  263. {"udp", "::1", "udp", "127.0.0.1", nil},
  264. {"udp4", "127.0.0.1", "udp6", "::1", nil},
  265. {"udp6", "::1", "udp4", "127.0.0.1", nil},
  266. }
  267. // TestDualStackUDPListener tests both single and double listen
  268. // to a test listener with various address families, differnet
  269. // listening address and same port.
  270. func TestDualStackUDPListener(t *testing.T) {
  271. switch runtime.GOOS {
  272. case "dragonfly", "nacl", "plan9": // re-enable on dragonfly once the new IP control block management has landed
  273. t.Skipf("not supported on %s", runtime.GOOS)
  274. }
  275. if !supportsIPv4 || !supportsIPv6 {
  276. t.Skip("both IPv4 and IPv6 are required")
  277. }
  278. for _, tt := range dualStackUDPListenerTests {
  279. if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
  280. t.Logf("skipping %s test", tt.network1+" "+tt.address1)
  281. continue
  282. }
  283. if !supportsIPv4map && differentWildcardAddr(tt.address1, tt.address2) {
  284. tt.xerr = nil
  285. }
  286. var firstErr, secondErr error
  287. for i := 0; i < 5; i++ {
  288. cs, err := newDualStackPacketListener()
  289. if err != nil {
  290. t.Fatal(err)
  291. }
  292. port := cs[0].port()
  293. for _, c := range cs {
  294. c.Close()
  295. }
  296. var c1 PacketConn
  297. c1, firstErr = ListenPacket(tt.network1, JoinHostPort(tt.address1, port))
  298. if firstErr != nil {
  299. continue
  300. }
  301. if err := checkFirstListener(tt.network1, c1); err != nil {
  302. c1.Close()
  303. t.Fatal(err)
  304. }
  305. c2, err := ListenPacket(tt.network2, JoinHostPort(tt.address2, c1.(*UDPConn).port()))
  306. if err == nil {
  307. c2.Close()
  308. }
  309. if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
  310. c1.Close()
  311. continue
  312. }
  313. c1.Close()
  314. break
  315. }
  316. if firstErr != nil {
  317. t.Error(firstErr)
  318. }
  319. if secondErr != nil {
  320. t.Error(secondErr)
  321. }
  322. }
  323. }
  324. func differentWildcardAddr(i, j string) bool {
  325. if (i == "" || i == "0.0.0.0" || i == "::ffff:0.0.0.0") && (j == "" || j == "0.0.0.0" || j == "::ffff:0.0.0.0") {
  326. return false
  327. }
  328. if i == "[::]" && j == "[::]" {
  329. return false
  330. }
  331. return true
  332. }
  333. func checkFirstListener(network string, ln interface{}) error {
  334. switch network {
  335. case "tcp":
  336. fd := ln.(*TCPListener).fd
  337. if err := checkDualStackAddrFamily(fd); err != nil {
  338. return err
  339. }
  340. case "tcp4":
  341. fd := ln.(*TCPListener).fd
  342. if fd.family != syscall.AF_INET {
  343. return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
  344. }
  345. case "tcp6":
  346. fd := ln.(*TCPListener).fd
  347. if fd.family != syscall.AF_INET6 {
  348. return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
  349. }
  350. case "udp":
  351. fd := ln.(*UDPConn).fd
  352. if err := checkDualStackAddrFamily(fd); err != nil {
  353. return err
  354. }
  355. case "udp4":
  356. fd := ln.(*UDPConn).fd
  357. if fd.family != syscall.AF_INET {
  358. return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
  359. }
  360. case "udp6":
  361. fd := ln.(*UDPConn).fd
  362. if fd.family != syscall.AF_INET6 {
  363. return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
  364. }
  365. default:
  366. return UnknownNetworkError(network)
  367. }
  368. return nil
  369. }
  370. func checkSecondListener(network, address string, err error) error {
  371. switch network {
  372. case "tcp", "tcp4", "tcp6":
  373. if err == nil {
  374. return fmt.Errorf("%s should fail", network+" "+address)
  375. }
  376. case "udp", "udp4", "udp6":
  377. if err == nil {
  378. return fmt.Errorf("%s should fail", network+" "+address)
  379. }
  380. default:
  381. return UnknownNetworkError(network)
  382. }
  383. return nil
  384. }
  385. func checkDualStackSecondListener(network, address string, err, xerr error) error {
  386. switch network {
  387. case "tcp", "tcp4", "tcp6":
  388. if xerr == nil && err != nil || xerr != nil && err == nil {
  389. return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
  390. }
  391. case "udp", "udp4", "udp6":
  392. if xerr == nil && err != nil || xerr != nil && err == nil {
  393. return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
  394. }
  395. default:
  396. return UnknownNetworkError(network)
  397. }
  398. return nil
  399. }
  400. func checkDualStackAddrFamily(fd *netFD) error {
  401. switch a := fd.laddr.(type) {
  402. case *TCPAddr:
  403. // If a node under test supports both IPv6 capability
  404. // and IPv6 IPv4-mapping capability, we can assume
  405. // that the node listens on a wildcard address with an
  406. // AF_INET6 socket.
  407. if supportsIPv4map && fd.laddr.(*TCPAddr).isWildcard() {
  408. if fd.family != syscall.AF_INET6 {
  409. return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
  410. }
  411. } else {
  412. if fd.family != a.family() {
  413. return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
  414. }
  415. }
  416. case *UDPAddr:
  417. // If a node under test supports both IPv6 capability
  418. // and IPv6 IPv4-mapping capability, we can assume
  419. // that the node listens on a wildcard address with an
  420. // AF_INET6 socket.
  421. if supportsIPv4map && fd.laddr.(*UDPAddr).isWildcard() {
  422. if fd.family != syscall.AF_INET6 {
  423. return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
  424. }
  425. } else {
  426. if fd.family != a.family() {
  427. return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
  428. }
  429. }
  430. default:
  431. return fmt.Errorf("unexpected protocol address type: %T", a)
  432. }
  433. return nil
  434. }
  435. func TestWildWildcardListener(t *testing.T) {
  436. switch runtime.GOOS {
  437. case "plan9":
  438. t.Skipf("not supported on %s", runtime.GOOS)
  439. }
  440. if testing.Short() || !*testExternal {
  441. t.Skip("avoid external network")
  442. }
  443. defer func() {
  444. if p := recover(); p != nil {
  445. t.Fatalf("panicked: %v", p)
  446. }
  447. }()
  448. if ln, err := Listen("tcp", ""); err == nil {
  449. ln.Close()
  450. }
  451. if ln, err := ListenPacket("udp", ""); err == nil {
  452. ln.Close()
  453. }
  454. if ln, err := ListenTCP("tcp", nil); err == nil {
  455. ln.Close()
  456. }
  457. if ln, err := ListenUDP("udp", nil); err == nil {
  458. ln.Close()
  459. }
  460. if ln, err := ListenIP("ip:icmp", nil); err == nil {
  461. ln.Close()
  462. }
  463. }
  464. var ipv4MulticastListenerTests = []struct {
  465. net string
  466. gaddr *UDPAddr // see RFC 4727
  467. }{
  468. {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
  469. {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
  470. }
  471. // TestIPv4MulticastListener tests both single and double listen to a
  472. // test listener with same address family, same group address and same
  473. // port.
  474. func TestIPv4MulticastListener(t *testing.T) {
  475. switch runtime.GOOS {
  476. case "android", "nacl", "plan9":
  477. t.Skipf("not supported on %s", runtime.GOOS)
  478. case "solaris":
  479. t.Skipf("not supported on solaris, see golang.org/issue/7399")
  480. }
  481. closer := func(cs []*UDPConn) {
  482. for _, c := range cs {
  483. if c != nil {
  484. c.Close()
  485. }
  486. }
  487. }
  488. for _, ifi := range []*Interface{loopbackInterface(), nil} {
  489. // Note that multicast interface assignment by system
  490. // is not recommended because it usually relies on
  491. // routing stuff for finding out an appropriate
  492. // nexthop containing both network and link layer
  493. // adjacencies.
  494. if ifi == nil && (testing.Short() || !*testExternal) {
  495. continue
  496. }
  497. for _, tt := range ipv4MulticastListenerTests {
  498. var err error
  499. cs := make([]*UDPConn, 2)
  500. if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
  501. t.Fatal(err)
  502. }
  503. if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
  504. closer(cs)
  505. t.Fatal(err)
  506. }
  507. if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
  508. closer(cs)
  509. t.Fatal(err)
  510. }
  511. if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
  512. closer(cs)
  513. t.Fatal(err)
  514. }
  515. closer(cs)
  516. }
  517. }
  518. }
  519. var ipv6MulticastListenerTests = []struct {
  520. net string
  521. gaddr *UDPAddr // see RFC 4727
  522. }{
  523. {"udp", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
  524. {"udp", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
  525. {"udp", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
  526. {"udp", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
  527. {"udp", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
  528. {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
  529. {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
  530. {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
  531. {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
  532. {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
  533. {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
  534. {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
  535. }
  536. // TestIPv6MulticastListener tests both single and double listen to a
  537. // test listener with same address family, same group address and same
  538. // port.
  539. func TestIPv6MulticastListener(t *testing.T) {
  540. switch runtime.GOOS {
  541. case "plan9":
  542. t.Skipf("not supported on %s", runtime.GOOS)
  543. case "solaris":
  544. t.Skipf("not supported on solaris, see issue 7399")
  545. }
  546. if !supportsIPv6 {
  547. t.Skip("ipv6 is not supported")
  548. }
  549. if os.Getuid() != 0 {
  550. t.Skip("must be root")
  551. }
  552. closer := func(cs []*UDPConn) {
  553. for _, c := range cs {
  554. if c != nil {
  555. c.Close()
  556. }
  557. }
  558. }
  559. for _, ifi := range []*Interface{loopbackInterface(), nil} {
  560. // Note that multicast interface assignment by system
  561. // is not recommended because it usually relies on
  562. // routing stuff for finding out an appropriate
  563. // nexthop containing both network and link layer
  564. // adjacencies.
  565. if ifi == nil && (testing.Short() || !*testExternal || !*testIPv6) {
  566. continue
  567. }
  568. for _, tt := range ipv6MulticastListenerTests {
  569. var err error
  570. cs := make([]*UDPConn, 2)
  571. if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
  572. t.Fatal(err)
  573. }
  574. if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
  575. closer(cs)
  576. t.Fatal(err)
  577. }
  578. if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
  579. closer(cs)
  580. t.Fatal(err)
  581. }
  582. if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
  583. closer(cs)
  584. t.Fatal(err)
  585. }
  586. closer(cs)
  587. }
  588. }
  589. }
  590. func checkMulticastListener(c *UDPConn, ip IP) error {
  591. if ok, err := multicastRIBContains(ip); err != nil {
  592. return err
  593. } else if !ok {
  594. return fmt.Errorf("%s not found in multicast rib", ip.String())
  595. }
  596. la := c.LocalAddr()
  597. if la, ok := la.(*UDPAddr); !ok || la.Port == 0 {
  598. return fmt.Errorf("got %v; want a proper address with non-zero port number", la)
  599. }
  600. return nil
  601. }
  602. func multicastRIBContains(ip IP) (bool, error) {
  603. switch runtime.GOOS {
  604. case "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "windows":
  605. return true, nil // not implemented yet
  606. case "linux":
  607. if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
  608. return true, nil // not implemented yet
  609. }
  610. }
  611. ift, err := Interfaces()
  612. if err != nil {
  613. return false, err
  614. }
  615. for _, ifi := range ift {
  616. ifmat, err := ifi.MulticastAddrs()
  617. if err != nil {
  618. return false, err
  619. }
  620. for _, ifma := range ifmat {
  621. if ifma.(*IPAddr).IP.Equal(ip) {
  622. return true, nil
  623. }
  624. }
  625. }
  626. return false, nil
  627. }