traverse.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package maxminddb
  2. import "net"
  3. // Internal structure used to keep track of nodes we still need to visit.
  4. type netNode struct {
  5. ip net.IP
  6. bit uint
  7. pointer uint
  8. }
  9. // Networks represents a set of subnets that we are iterating over.
  10. type Networks struct {
  11. reader *Reader
  12. nodes []netNode // Nodes we still have to visit.
  13. lastNode netNode
  14. err error
  15. }
  16. // Networks returns an iterator that can be used to traverse all networks in
  17. // the database.
  18. //
  19. // Please note that a MaxMind DB may map IPv4 networks into several locations
  20. // in in an IPv6 database. This iterator will iterate over all of these
  21. // locations separately.
  22. func (r *Reader) Networks() *Networks {
  23. s := 4
  24. if r.Metadata.IPVersion == 6 {
  25. s = 16
  26. }
  27. return &Networks{
  28. reader: r,
  29. nodes: []netNode{
  30. {
  31. ip: make(net.IP, s),
  32. },
  33. },
  34. }
  35. }
  36. // Next prepares the next network for reading with the Network method. It
  37. // returns true if there is another network to be processed and false if there
  38. // are no more networks or if there is an error.
  39. func (n *Networks) Next() bool {
  40. for len(n.nodes) > 0 {
  41. node := n.nodes[len(n.nodes)-1]
  42. n.nodes = n.nodes[:len(n.nodes)-1]
  43. for node.pointer != n.reader.Metadata.NodeCount {
  44. if node.pointer > n.reader.Metadata.NodeCount {
  45. n.lastNode = node
  46. return true
  47. }
  48. ipRight := make(net.IP, len(node.ip))
  49. copy(ipRight, node.ip)
  50. if len(ipRight) <= int(node.bit>>3) {
  51. n.err = newInvalidDatabaseError(
  52. "invalid search tree at %v/%v", ipRight, node.bit)
  53. return false
  54. }
  55. ipRight[node.bit>>3] |= 1 << (7 - (node.bit % 8))
  56. offset := node.pointer * n.reader.nodeOffsetMult
  57. rightPointer := n.reader.nodeReader.readRight(offset)
  58. node.bit++
  59. n.nodes = append(n.nodes, netNode{
  60. pointer: rightPointer,
  61. ip: ipRight,
  62. bit: node.bit,
  63. })
  64. node.pointer = n.reader.nodeReader.readLeft(offset)
  65. }
  66. }
  67. return false
  68. }
  69. // Network returns the current network or an error if there is a problem
  70. // decoding the data for the network. It takes a pointer to a result value to
  71. // decode the network's data into.
  72. func (n *Networks) Network(result interface{}) (*net.IPNet, error) {
  73. if err := n.reader.retrieveData(n.lastNode.pointer, result); err != nil {
  74. return nil, err
  75. }
  76. return &net.IPNet{
  77. IP: n.lastNode.ip,
  78. Mask: net.CIDRMask(int(n.lastNode.bit), len(n.lastNode.ip)*8),
  79. }, nil
  80. }
  81. // Err returns an error, if any, that was encountered during iteration.
  82. func (n *Networks) Err() error {
  83. return n.err
  84. }