3
0

lighthouse_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. package nebula
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "testing"
  7. "github.com/slackhq/nebula/config"
  8. "github.com/slackhq/nebula/header"
  9. "github.com/slackhq/nebula/iputil"
  10. "github.com/slackhq/nebula/test"
  11. "github.com/slackhq/nebula/udp"
  12. "github.com/stretchr/testify/assert"
  13. "gopkg.in/yaml.v2"
  14. )
  15. //TODO: Add a test to ensure udpAddr is copied and not reused
  16. func TestOldIPv4Only(t *testing.T) {
  17. // This test ensures our new ipv6 enabled LH protobuf IpAndPorts works with the old style to enable backwards compatibility
  18. b := []byte{8, 129, 130, 132, 80, 16, 10}
  19. var m Ip4AndPort
  20. err := m.Unmarshal(b)
  21. assert.NoError(t, err)
  22. assert.Equal(t, "10.1.1.1", iputil.VpnIp(m.GetIp()).String())
  23. }
  24. func TestNewLhQuery(t *testing.T) {
  25. myIp := net.ParseIP("192.1.1.1")
  26. myIpint := iputil.Ip2VpnIp(myIp)
  27. // Generating a new lh query should work
  28. a := NewLhQueryByInt(myIpint)
  29. // The result should be a nebulameta protobuf
  30. assert.IsType(t, &NebulaMeta{}, a)
  31. // It should also Marshal fine
  32. b, err := a.Marshal()
  33. assert.Nil(t, err)
  34. // and then Unmarshal fine
  35. n := &NebulaMeta{}
  36. err = n.Unmarshal(b)
  37. assert.Nil(t, err)
  38. }
  39. func Test_lhStaticMapping(t *testing.T) {
  40. l := test.NewLogger()
  41. _, myVpnNet, _ := net.ParseCIDR("10.128.0.1/16")
  42. lh1 := "10.128.0.2"
  43. c := config.NewC(l)
  44. c.Settings["lighthouse"] = map[interface{}]interface{}{"hosts": []interface{}{lh1}}
  45. c.Settings["static_host_map"] = map[interface{}]interface{}{lh1: []interface{}{"1.1.1.1:4242"}}
  46. _, err := NewLightHouseFromConfig(context.Background(), l, c, myVpnNet, nil, nil)
  47. assert.Nil(t, err)
  48. lh2 := "10.128.0.3"
  49. c = config.NewC(l)
  50. c.Settings["lighthouse"] = map[interface{}]interface{}{"hosts": []interface{}{lh1, lh2}}
  51. c.Settings["static_host_map"] = map[interface{}]interface{}{lh1: []interface{}{"100.1.1.1:4242"}}
  52. _, err = NewLightHouseFromConfig(context.Background(), l, c, myVpnNet, nil, nil)
  53. assert.EqualError(t, err, "lighthouse 10.128.0.3 does not have a static_host_map entry")
  54. }
  55. func TestReloadLighthouseInterval(t *testing.T) {
  56. l := test.NewLogger()
  57. _, myVpnNet, _ := net.ParseCIDR("10.128.0.1/16")
  58. lh1 := "10.128.0.2"
  59. c := config.NewC(l)
  60. c.Settings["lighthouse"] = map[interface{}]interface{}{
  61. "hosts": []interface{}{lh1},
  62. "interval": "1s",
  63. }
  64. c.Settings["static_host_map"] = map[interface{}]interface{}{lh1: []interface{}{"1.1.1.1:4242"}}
  65. lh, err := NewLightHouseFromConfig(context.Background(), l, c, myVpnNet, nil, nil)
  66. assert.NoError(t, err)
  67. lh.ifce = &mockEncWriter{}
  68. // The first one routine is kicked off by main.go currently, lets make sure that one dies
  69. c.ReloadConfigString("lighthouse:\n interval: 5")
  70. assert.Equal(t, int64(5), lh.interval.Load())
  71. // Subsequent calls are killed off by the LightHouse.Reload function
  72. c.ReloadConfigString("lighthouse:\n interval: 10")
  73. assert.Equal(t, int64(10), lh.interval.Load())
  74. // If this completes then nothing is stealing our reload routine
  75. c.ReloadConfigString("lighthouse:\n interval: 11")
  76. assert.Equal(t, int64(11), lh.interval.Load())
  77. }
  78. func BenchmarkLighthouseHandleRequest(b *testing.B) {
  79. l := test.NewLogger()
  80. _, myVpnNet, _ := net.ParseCIDR("10.128.0.1/0")
  81. c := config.NewC(l)
  82. lh, err := NewLightHouseFromConfig(context.Background(), l, c, myVpnNet, nil, nil)
  83. if !assert.NoError(b, err) {
  84. b.Fatal()
  85. }
  86. hAddr := udp.NewAddrFromString("4.5.6.7:12345")
  87. hAddr2 := udp.NewAddrFromString("4.5.6.7:12346")
  88. lh.addrMap[3] = NewRemoteList(nil)
  89. lh.addrMap[3].unlockedSetV4(
  90. 3,
  91. 3,
  92. []*Ip4AndPort{
  93. NewIp4AndPort(hAddr.IP, uint32(hAddr.Port)),
  94. NewIp4AndPort(hAddr2.IP, uint32(hAddr2.Port)),
  95. },
  96. func(iputil.VpnIp, *Ip4AndPort) bool { return true },
  97. )
  98. rAddr := udp.NewAddrFromString("1.2.2.3:12345")
  99. rAddr2 := udp.NewAddrFromString("1.2.2.3:12346")
  100. lh.addrMap[2] = NewRemoteList(nil)
  101. lh.addrMap[2].unlockedSetV4(
  102. 3,
  103. 3,
  104. []*Ip4AndPort{
  105. NewIp4AndPort(rAddr.IP, uint32(rAddr.Port)),
  106. NewIp4AndPort(rAddr2.IP, uint32(rAddr2.Port)),
  107. },
  108. func(iputil.VpnIp, *Ip4AndPort) bool { return true },
  109. )
  110. mw := &mockEncWriter{}
  111. b.Run("notfound", func(b *testing.B) {
  112. lhh := lh.NewRequestHandler()
  113. req := &NebulaMeta{
  114. Type: NebulaMeta_HostQuery,
  115. Details: &NebulaMetaDetails{
  116. VpnIp: 4,
  117. Ip4AndPorts: nil,
  118. },
  119. }
  120. p, err := req.Marshal()
  121. assert.NoError(b, err)
  122. for n := 0; n < b.N; n++ {
  123. lhh.HandleRequest(rAddr, 2, p, mw)
  124. }
  125. })
  126. b.Run("found", func(b *testing.B) {
  127. lhh := lh.NewRequestHandler()
  128. req := &NebulaMeta{
  129. Type: NebulaMeta_HostQuery,
  130. Details: &NebulaMetaDetails{
  131. VpnIp: 3,
  132. Ip4AndPorts: nil,
  133. },
  134. }
  135. p, err := req.Marshal()
  136. assert.NoError(b, err)
  137. for n := 0; n < b.N; n++ {
  138. lhh.HandleRequest(rAddr, 2, p, mw)
  139. }
  140. })
  141. }
  142. func TestLighthouse_Memory(t *testing.T) {
  143. l := test.NewLogger()
  144. myUdpAddr0 := &udp.Addr{IP: net.ParseIP("10.0.0.2"), Port: 4242}
  145. myUdpAddr1 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4242}
  146. myUdpAddr2 := &udp.Addr{IP: net.ParseIP("172.16.0.2"), Port: 4242}
  147. myUdpAddr3 := &udp.Addr{IP: net.ParseIP("100.152.0.2"), Port: 4242}
  148. myUdpAddr4 := &udp.Addr{IP: net.ParseIP("24.15.0.2"), Port: 4242}
  149. myUdpAddr5 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4243}
  150. myUdpAddr6 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4244}
  151. myUdpAddr7 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4245}
  152. myUdpAddr8 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4246}
  153. myUdpAddr9 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4247}
  154. myUdpAddr10 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4248}
  155. myUdpAddr11 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4249}
  156. myVpnIp := iputil.Ip2VpnIp(net.ParseIP("10.128.0.2"))
  157. theirUdpAddr0 := &udp.Addr{IP: net.ParseIP("10.0.0.3"), Port: 4242}
  158. theirUdpAddr1 := &udp.Addr{IP: net.ParseIP("192.168.0.3"), Port: 4242}
  159. theirUdpAddr2 := &udp.Addr{IP: net.ParseIP("172.16.0.3"), Port: 4242}
  160. theirUdpAddr3 := &udp.Addr{IP: net.ParseIP("100.152.0.3"), Port: 4242}
  161. theirUdpAddr4 := &udp.Addr{IP: net.ParseIP("24.15.0.3"), Port: 4242}
  162. theirVpnIp := iputil.Ip2VpnIp(net.ParseIP("10.128.0.3"))
  163. c := config.NewC(l)
  164. c.Settings["lighthouse"] = map[interface{}]interface{}{"am_lighthouse": true}
  165. c.Settings["listen"] = map[interface{}]interface{}{"port": 4242}
  166. lh, err := NewLightHouseFromConfig(context.Background(), l, c, &net.IPNet{IP: net.IP{10, 128, 0, 1}, Mask: net.IPMask{255, 255, 255, 0}}, nil, nil)
  167. assert.NoError(t, err)
  168. lhh := lh.NewRequestHandler()
  169. // Test that my first update responds with just that
  170. newLHHostUpdate(myUdpAddr0, myVpnIp, []*udp.Addr{myUdpAddr1, myUdpAddr2}, lhh)
  171. r := newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  172. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr1, myUdpAddr2)
  173. // Ensure we don't accumulate addresses
  174. newLHHostUpdate(myUdpAddr0, myVpnIp, []*udp.Addr{myUdpAddr3}, lhh)
  175. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  176. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr3)
  177. // Grow it back to 2
  178. newLHHostUpdate(myUdpAddr0, myVpnIp, []*udp.Addr{myUdpAddr1, myUdpAddr4}, lhh)
  179. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  180. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr1, myUdpAddr4)
  181. // Update a different host and ask about it
  182. newLHHostUpdate(theirUdpAddr0, theirVpnIp, []*udp.Addr{theirUdpAddr1, theirUdpAddr2, theirUdpAddr3, theirUdpAddr4}, lhh)
  183. r = newLHHostRequest(theirUdpAddr0, theirVpnIp, theirVpnIp, lhh)
  184. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, theirUdpAddr1, theirUdpAddr2, theirUdpAddr3, theirUdpAddr4)
  185. // Have both hosts ask about the other
  186. r = newLHHostRequest(theirUdpAddr0, theirVpnIp, myVpnIp, lhh)
  187. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr1, myUdpAddr4)
  188. r = newLHHostRequest(myUdpAddr0, myVpnIp, theirVpnIp, lhh)
  189. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, theirUdpAddr1, theirUdpAddr2, theirUdpAddr3, theirUdpAddr4)
  190. // Make sure we didn't get changed
  191. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  192. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr1, myUdpAddr4)
  193. // Ensure proper ordering and limiting
  194. // Send 12 addrs, get 10 back, the last 2 removed, allowing the duplicate to remain (clients dedupe)
  195. newLHHostUpdate(
  196. myUdpAddr0,
  197. myVpnIp,
  198. []*udp.Addr{
  199. myUdpAddr1,
  200. myUdpAddr2,
  201. myUdpAddr3,
  202. myUdpAddr4,
  203. myUdpAddr5,
  204. myUdpAddr5, //Duplicated on purpose
  205. myUdpAddr6,
  206. myUdpAddr7,
  207. myUdpAddr8,
  208. myUdpAddr9,
  209. myUdpAddr10,
  210. myUdpAddr11, // This should get cut
  211. }, lhh)
  212. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  213. assertIp4InArray(
  214. t,
  215. r.msg.Details.Ip4AndPorts,
  216. myUdpAddr1, myUdpAddr2, myUdpAddr3, myUdpAddr4, myUdpAddr5, myUdpAddr5, myUdpAddr6, myUdpAddr7, myUdpAddr8, myUdpAddr9,
  217. )
  218. // Make sure we won't add ips in our vpn network
  219. bad1 := &udp.Addr{IP: net.ParseIP("10.128.0.99"), Port: 4242}
  220. bad2 := &udp.Addr{IP: net.ParseIP("10.128.0.100"), Port: 4242}
  221. good := &udp.Addr{IP: net.ParseIP("1.128.0.99"), Port: 4242}
  222. newLHHostUpdate(myUdpAddr0, myVpnIp, []*udp.Addr{bad1, bad2, good}, lhh)
  223. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  224. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, good)
  225. }
  226. func TestLighthouse_reload(t *testing.T) {
  227. l := test.NewLogger()
  228. c := config.NewC(l)
  229. c.Settings["lighthouse"] = map[interface{}]interface{}{"am_lighthouse": true}
  230. c.Settings["listen"] = map[interface{}]interface{}{"port": 4242}
  231. lh, err := NewLightHouseFromConfig(context.Background(), l, c, &net.IPNet{IP: net.IP{10, 128, 0, 1}, Mask: net.IPMask{255, 255, 255, 0}}, nil, nil)
  232. assert.NoError(t, err)
  233. nc := map[interface{}]interface{}{
  234. "static_host_map": map[interface{}]interface{}{
  235. "10.128.0.2": []interface{}{"1.1.1.1:4242"},
  236. },
  237. }
  238. rc, err := yaml.Marshal(nc)
  239. assert.NoError(t, err)
  240. c.ReloadConfigString(string(rc))
  241. err = lh.reload(c, false)
  242. assert.NoError(t, err)
  243. }
  244. func newLHHostRequest(fromAddr *udp.Addr, myVpnIp, queryVpnIp iputil.VpnIp, lhh *LightHouseHandler) testLhReply {
  245. req := &NebulaMeta{
  246. Type: NebulaMeta_HostQuery,
  247. Details: &NebulaMetaDetails{
  248. VpnIp: uint32(queryVpnIp),
  249. },
  250. }
  251. b, err := req.Marshal()
  252. if err != nil {
  253. panic(err)
  254. }
  255. filter := NebulaMeta_HostQueryReply
  256. w := &testEncWriter{
  257. metaFilter: &filter,
  258. }
  259. lhh.HandleRequest(fromAddr, myVpnIp, b, w)
  260. return w.lastReply
  261. }
  262. func newLHHostUpdate(fromAddr *udp.Addr, vpnIp iputil.VpnIp, addrs []*udp.Addr, lhh *LightHouseHandler) {
  263. req := &NebulaMeta{
  264. Type: NebulaMeta_HostUpdateNotification,
  265. Details: &NebulaMetaDetails{
  266. VpnIp: uint32(vpnIp),
  267. Ip4AndPorts: make([]*Ip4AndPort, len(addrs)),
  268. },
  269. }
  270. for k, v := range addrs {
  271. req.Details.Ip4AndPorts[k] = &Ip4AndPort{Ip: uint32(iputil.Ip2VpnIp(v.IP)), Port: uint32(v.Port)}
  272. }
  273. b, err := req.Marshal()
  274. if err != nil {
  275. panic(err)
  276. }
  277. w := &testEncWriter{}
  278. lhh.HandleRequest(fromAddr, vpnIp, b, w)
  279. }
  280. //TODO: this is a RemoteList test
  281. //func Test_lhRemoteAllowList(t *testing.T) {
  282. // l := NewLogger()
  283. // c := NewConfig(l)
  284. // c.Settings["remoteallowlist"] = map[interface{}]interface{}{
  285. // "10.20.0.0/12": false,
  286. // }
  287. // allowList, err := c.GetAllowList("remoteallowlist", false)
  288. // assert.Nil(t, err)
  289. //
  290. // lh1 := "10.128.0.2"
  291. // lh1IP := net.ParseIP(lh1)
  292. //
  293. // udpServer, _ := NewListener(l, "0.0.0.0", 0, true)
  294. //
  295. // lh := NewLightHouse(l, true, &net.IPNet{IP: net.IP{0, 0, 0, 1}, Mask: net.IPMask{255, 255, 255, 0}}, []uint32{ip2int(lh1IP)}, 10, 10003, udpServer, false, 1, false)
  296. // lh.SetRemoteAllowList(allowList)
  297. //
  298. // // A disallowed ip should not enter the cache but we should end up with an empty entry in the addrMap
  299. // remote1IP := net.ParseIP("10.20.0.3")
  300. // remotes := lh.unlockedGetRemoteList(ip2int(remote1IP))
  301. // remotes.unlockedPrependV4(ip2int(remote1IP), NewIp4AndPort(remote1IP, 4242))
  302. // assert.NotNil(t, lh.addrMap[ip2int(remote1IP)])
  303. // assert.Empty(t, lh.addrMap[ip2int(remote1IP)].CopyAddrs([]*net.IPNet{}))
  304. //
  305. // // Make sure a good ip enters the cache and addrMap
  306. // remote2IP := net.ParseIP("10.128.0.3")
  307. // remote2UDPAddr := NewUDPAddr(remote2IP, uint16(4242))
  308. // lh.addRemoteV4(ip2int(remote2IP), ip2int(remote2IP), NewIp4AndPort(remote2UDPAddr.IP, uint32(remote2UDPAddr.Port)), false, false)
  309. // assertUdpAddrInArray(t, lh.addrMap[ip2int(remote2IP)].CopyAddrs([]*net.IPNet{}), remote2UDPAddr)
  310. //
  311. // // Another good ip gets into the cache, ordering is inverted
  312. // remote3IP := net.ParseIP("10.128.0.4")
  313. // remote3UDPAddr := NewUDPAddr(remote3IP, uint16(4243))
  314. // lh.addRemoteV4(ip2int(remote2IP), ip2int(remote2IP), NewIp4AndPort(remote3UDPAddr.IP, uint32(remote3UDPAddr.Port)), false, false)
  315. // assertUdpAddrInArray(t, lh.addrMap[ip2int(remote2IP)].CopyAddrs([]*net.IPNet{}), remote2UDPAddr, remote3UDPAddr)
  316. //
  317. // // If we exceed the length limit we should only have the most recent addresses
  318. // addedAddrs := []*udpAddr{}
  319. // for i := 0; i < 11; i++ {
  320. // remoteUDPAddr := NewUDPAddr(net.IP{10, 128, 0, 4}, uint16(4243+i))
  321. // lh.addRemoteV4(ip2int(remote2IP), ip2int(remote2IP), NewIp4AndPort(remoteUDPAddr.IP, uint32(remoteUDPAddr.Port)), false, false)
  322. // // The first entry here is a duplicate, don't add it to the assert list
  323. // if i != 0 {
  324. // addedAddrs = append(addedAddrs, remoteUDPAddr)
  325. // }
  326. // }
  327. //
  328. // // We should only have the last 10 of what we tried to add
  329. // assert.True(t, len(addedAddrs) >= 10, "We should have tried to add at least 10 addresses")
  330. // assertUdpAddrInArray(
  331. // t,
  332. // lh.addrMap[ip2int(remote2IP)].CopyAddrs([]*net.IPNet{}),
  333. // addedAddrs[0],
  334. // addedAddrs[1],
  335. // addedAddrs[2],
  336. // addedAddrs[3],
  337. // addedAddrs[4],
  338. // addedAddrs[5],
  339. // addedAddrs[6],
  340. // addedAddrs[7],
  341. // addedAddrs[8],
  342. // addedAddrs[9],
  343. // )
  344. //}
  345. func Test_ipMaskContains(t *testing.T) {
  346. assert.True(t, ipMaskContains(iputil.Ip2VpnIp(net.ParseIP("10.0.0.1")), 32-24, iputil.Ip2VpnIp(net.ParseIP("10.0.0.255"))))
  347. assert.False(t, ipMaskContains(iputil.Ip2VpnIp(net.ParseIP("10.0.0.1")), 32-24, iputil.Ip2VpnIp(net.ParseIP("10.0.1.1"))))
  348. assert.True(t, ipMaskContains(iputil.Ip2VpnIp(net.ParseIP("10.0.0.1")), 32, iputil.Ip2VpnIp(net.ParseIP("10.0.1.1"))))
  349. }
  350. type testLhReply struct {
  351. nebType header.MessageType
  352. nebSubType header.MessageSubType
  353. vpnIp iputil.VpnIp
  354. msg *NebulaMeta
  355. }
  356. type testEncWriter struct {
  357. lastReply testLhReply
  358. metaFilter *NebulaMeta_MessageType
  359. }
  360. func (tw *testEncWriter) SendVia(via *HostInfo, relay *Relay, ad, nb, out []byte, nocopy bool) {
  361. }
  362. func (tw *testEncWriter) Handshake(vpnIp iputil.VpnIp) {
  363. }
  364. func (tw *testEncWriter) SendMessageToHostInfo(t header.MessageType, st header.MessageSubType, hostinfo *HostInfo, p, _, _ []byte) {
  365. msg := &NebulaMeta{}
  366. err := msg.Unmarshal(p)
  367. if tw.metaFilter == nil || msg.Type == *tw.metaFilter {
  368. tw.lastReply = testLhReply{
  369. nebType: t,
  370. nebSubType: st,
  371. vpnIp: hostinfo.vpnIp,
  372. msg: msg,
  373. }
  374. }
  375. if err != nil {
  376. panic(err)
  377. }
  378. }
  379. func (tw *testEncWriter) SendMessageToVpnIp(t header.MessageType, st header.MessageSubType, vpnIp iputil.VpnIp, p, _, _ []byte) {
  380. msg := &NebulaMeta{}
  381. err := msg.Unmarshal(p)
  382. if tw.metaFilter == nil || msg.Type == *tw.metaFilter {
  383. tw.lastReply = testLhReply{
  384. nebType: t,
  385. nebSubType: st,
  386. vpnIp: vpnIp,
  387. msg: msg,
  388. }
  389. }
  390. if err != nil {
  391. panic(err)
  392. }
  393. }
  394. // assertIp4InArray asserts every address in want is at the same position in have and that the lengths match
  395. func assertIp4InArray(t *testing.T, have []*Ip4AndPort, want ...*udp.Addr) {
  396. if !assert.Len(t, have, len(want)) {
  397. return
  398. }
  399. for k, w := range want {
  400. if !(have[k].Ip == uint32(iputil.Ip2VpnIp(w.IP)) && have[k].Port == uint32(w.Port)) {
  401. assert.Fail(t, fmt.Sprintf("Response did not contain: %v:%v at %v; %v", w.IP, w.Port, k, translateV4toUdpAddr(have)))
  402. }
  403. }
  404. }
  405. // assertUdpAddrInArray asserts every address in want is at the same position in have and that the lengths match
  406. func assertUdpAddrInArray(t *testing.T, have []*udp.Addr, want ...*udp.Addr) {
  407. if !assert.Len(t, have, len(want)) {
  408. return
  409. }
  410. for k, w := range want {
  411. if !(have[k].IP.Equal(w.IP) && have[k].Port == w.Port) {
  412. assert.Fail(t, fmt.Sprintf("Response did not contain: %v at %v; %v", w, k, have))
  413. }
  414. }
  415. }
  416. func translateV4toUdpAddr(ips []*Ip4AndPort) []*udp.Addr {
  417. addrs := make([]*udp.Addr, len(ips))
  418. for k, v := range ips {
  419. addrs[k] = NewUDPAddrFromLH4(v)
  420. }
  421. return addrs
  422. }