ipset.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // Copyright 2020 The Inet.Af 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. package netaddr
  5. import (
  6. "fmt"
  7. "runtime"
  8. "sort"
  9. "strings"
  10. )
  11. // IPSetBuilder builds an immutable IPSet.
  12. //
  13. // The zero value is a valid value representing a set of no IPs.
  14. //
  15. // The Add and Remove methods add or remove IPs to/from the set.
  16. // Removals only affect the current membership of the set, so in
  17. // general Adds should be called first. Input ranges may overlap in
  18. // any way.
  19. //
  20. // Most IPSetBuilder methods do not return errors.
  21. // Instead, errors are accumulated and reported by IPSetBuilder.IPSet.
  22. type IPSetBuilder struct {
  23. // in are the ranges in the set.
  24. in []IPRange
  25. // out are the ranges to be removed from 'in'.
  26. out []IPRange
  27. // errs are errors accumulated during construction.
  28. errs multiErr
  29. }
  30. // normalize normalizes s: s.in becomes the minimal sorted list of
  31. // ranges required to describe s, and s.out becomes empty.
  32. func (s *IPSetBuilder) normalize() {
  33. const debug = false
  34. if debug {
  35. debugf("ranges start in=%v out=%v", s.in, s.out)
  36. }
  37. in, ok := mergeIPRanges(s.in)
  38. if !ok {
  39. return
  40. }
  41. out, ok := mergeIPRanges(s.out)
  42. if !ok {
  43. return
  44. }
  45. if debug {
  46. debugf("ranges sort in=%v out=%v", in, out)
  47. }
  48. // in and out are sorted in ascending range order, and have no
  49. // overlaps within each other. We can run a merge of the two lists
  50. // in one pass.
  51. min := make([]IPRange, 0, len(in))
  52. for len(in) > 0 && len(out) > 0 {
  53. rin, rout := in[0], out[0]
  54. if debug {
  55. debugf("step in=%v out=%v", rin, rout)
  56. }
  57. switch {
  58. case !rout.IsValid() || !rin.IsValid():
  59. // mergeIPRanges should have prevented invalid ranges from
  60. // sneaking in.
  61. panic("invalid IPRanges during Ranges merge")
  62. case rout.entirelyBefore(rin):
  63. // "out" is entirely before "in".
  64. //
  65. // out in
  66. // f-------t f-------t
  67. out = out[1:]
  68. if debug {
  69. debugf("out before in; drop out")
  70. }
  71. case rin.entirelyBefore(rout):
  72. // "in" is entirely before "out".
  73. //
  74. // in out
  75. // f------t f-------t
  76. min = append(min, rin)
  77. in = in[1:]
  78. if debug {
  79. debugf("in before out; append in")
  80. debugf("min=%v", min)
  81. }
  82. case rin.coveredBy(rout):
  83. // "out" entirely covers "in".
  84. //
  85. // out
  86. // f-------------t
  87. // f------t
  88. // in
  89. in = in[1:]
  90. if debug {
  91. debugf("in inside out; drop in")
  92. }
  93. case rout.inMiddleOf(rin):
  94. // "in" entirely covers "out".
  95. //
  96. // in
  97. // f-------------t
  98. // f------t
  99. // out
  100. min = append(min, IPRange{from: rin.from, to: rout.from.Prior()})
  101. // Adjust in[0], not ir, because we want to consider the
  102. // mutated range on the next iteration.
  103. in[0].from = rout.to.Next()
  104. out = out[1:]
  105. if debug {
  106. debugf("out inside in; split in, append first in, drop out, adjust second in")
  107. debugf("min=%v", min)
  108. }
  109. case rout.overlapsStartOf(rin):
  110. // "out" overlaps start of "in".
  111. //
  112. // out
  113. // f------t
  114. // f------t
  115. // in
  116. in[0].from = rout.to.Next()
  117. // Can't move ir onto min yet, another later out might
  118. // trim it further. Just discard or and continue.
  119. out = out[1:]
  120. if debug {
  121. debugf("out cuts start of in; adjust in, drop out")
  122. }
  123. case rout.overlapsEndOf(rin):
  124. // "out" overlaps end of "in".
  125. //
  126. // out
  127. // f------t
  128. // f------t
  129. // in
  130. min = append(min, IPRange{from: rin.from, to: rout.from.Prior()})
  131. in = in[1:]
  132. if debug {
  133. debugf("merge out cuts end of in; append shortened in")
  134. debugf("min=%v", min)
  135. }
  136. default:
  137. // The above should account for all combinations of in and
  138. // out overlapping, but insert a panic to be sure.
  139. panic("unexpected additional overlap scenario")
  140. }
  141. }
  142. if len(in) > 0 {
  143. // Ran out of removals before the end of in.
  144. min = append(min, in...)
  145. if debug {
  146. debugf("min=%v", min)
  147. }
  148. }
  149. s.in = min
  150. s.out = nil
  151. }
  152. // Clone returns a copy of s that shares no memory with s.
  153. func (s *IPSetBuilder) Clone() *IPSetBuilder {
  154. return &IPSetBuilder{
  155. in: append([]IPRange(nil), s.in...),
  156. out: append([]IPRange(nil), s.out...),
  157. }
  158. }
  159. func (s *IPSetBuilder) addError(msg string, args ...interface{}) {
  160. se := new(stacktraceErr)
  161. // Skip three frames: runtime.Callers, addError, and the IPSetBuilder
  162. // method that called addError (such as IPSetBuilder.Add).
  163. // The resulting stack trace ends at the line in the user's
  164. // code where they called into netaddr.
  165. n := runtime.Callers(3, se.pcs[:])
  166. se.at = se.pcs[:n]
  167. se.err = fmt.Errorf(msg, args...)
  168. s.errs = append(s.errs, se)
  169. }
  170. // Add adds ip to s.
  171. func (s *IPSetBuilder) Add(ip IP) {
  172. if ip.IsZero() {
  173. s.addError("Add(IP{})")
  174. return
  175. }
  176. s.AddRange(IPRangeFrom(ip, ip))
  177. }
  178. // AddPrefix adds all IPs in p to s.
  179. func (s *IPSetBuilder) AddPrefix(p IPPrefix) {
  180. if r := p.Range(); r.IsValid() {
  181. s.AddRange(r)
  182. } else {
  183. s.addError("AddPrefix(%v/%v)", p.IP(), p.Bits())
  184. }
  185. }
  186. // AddRange adds r to s.
  187. // If r is not Valid, AddRange does nothing.
  188. func (s *IPSetBuilder) AddRange(r IPRange) {
  189. if !r.IsValid() {
  190. s.addError("AddRange(%v-%v)", r.From(), r.To())
  191. return
  192. }
  193. // If there are any removals (s.out), then we need to compact the set
  194. // first to get the order right.
  195. if len(s.out) > 0 {
  196. s.normalize()
  197. }
  198. s.in = append(s.in, r)
  199. }
  200. // AddSet adds all IPs in b to s.
  201. func (s *IPSetBuilder) AddSet(b *IPSet) {
  202. if b == nil {
  203. return
  204. }
  205. for _, r := range b.rr {
  206. s.AddRange(r)
  207. }
  208. }
  209. // Remove removes ip from s.
  210. func (s *IPSetBuilder) Remove(ip IP) {
  211. if ip.IsZero() {
  212. s.addError("Remove(IP{})")
  213. } else {
  214. s.RemoveRange(IPRangeFrom(ip, ip))
  215. }
  216. }
  217. // RemovePrefix removes all IPs in p from s.
  218. func (s *IPSetBuilder) RemovePrefix(p IPPrefix) {
  219. if r := p.Range(); r.IsValid() {
  220. s.RemoveRange(r)
  221. } else {
  222. s.addError("RemovePrefix(%v/%v)", p.IP(), p.Bits())
  223. }
  224. }
  225. // RemoveRange removes all IPs in r from s.
  226. func (s *IPSetBuilder) RemoveRange(r IPRange) {
  227. if r.IsValid() {
  228. s.out = append(s.out, r)
  229. } else {
  230. s.addError("RemoveRange(%v-%v)", r.From(), r.To())
  231. }
  232. }
  233. // RemoveSet removes all IPs in o from s.
  234. func (s *IPSetBuilder) RemoveSet(b *IPSet) {
  235. if b == nil {
  236. return
  237. }
  238. for _, r := range b.rr {
  239. s.RemoveRange(r)
  240. }
  241. }
  242. // removeBuilder removes all IPs in b from s.
  243. func (s *IPSetBuilder) removeBuilder(b *IPSetBuilder) {
  244. b.normalize()
  245. for _, r := range b.in {
  246. s.RemoveRange(r)
  247. }
  248. }
  249. // Complement updates s to contain the complement of its current
  250. // contents.
  251. func (s *IPSetBuilder) Complement() {
  252. s.normalize()
  253. s.out = s.in
  254. s.in = []IPRange{
  255. IPPrefix{ip: IPv4(0, 0, 0, 0), bits: 0}.Range(),
  256. IPPrefix{ip: IPv6Unspecified(), bits: 0}.Range(),
  257. }
  258. }
  259. // Intersect updates s to the set intersection of s and b.
  260. func (s *IPSetBuilder) Intersect(b *IPSet) {
  261. var o IPSetBuilder
  262. o.Complement()
  263. o.RemoveSet(b)
  264. s.removeBuilder(&o)
  265. }
  266. func discardf(format string, args ...interface{}) {}
  267. // debugf is reassigned by tests.
  268. var debugf = discardf
  269. // IPSet returns an immutable IPSet representing the current state of s.
  270. //
  271. // Most IPSetBuilder methods do not return errors.
  272. // Rather, the builder ignores any invalid inputs (such as an invalid IPPrefix),
  273. // and accumulates a list of any such errors that it encountered.
  274. //
  275. // IPSet also reports any such accumulated errors.
  276. // Even if the returned error is non-nil, the returned IPSet is usable
  277. // and contains all modifications made with valid inputs.
  278. //
  279. // The builder remains usable after calling IPSet.
  280. // Calling IPSet clears any accumulated errors.
  281. func (s *IPSetBuilder) IPSet() (*IPSet, error) {
  282. s.normalize()
  283. ret := &IPSet{
  284. rr: append([]IPRange{}, s.in...),
  285. }
  286. if len(s.errs) == 0 {
  287. return ret, nil
  288. } else {
  289. errs := s.errs
  290. s.errs = nil
  291. return ret, errs
  292. }
  293. }
  294. // IPSet represents a set of IP addresses.
  295. //
  296. // IPSet is safe for concurrent use.
  297. // The zero value is a valid value representing a set of no IPs.
  298. // Use IPSetBuilder to construct IPSets.
  299. type IPSet struct {
  300. // rr is the set of IPs that belong to this IPSet. The IPRanges
  301. // are normalized according to IPSetBuilder.normalize, meaning
  302. // they are a sorted, minimal representation (no overlapping
  303. // ranges, no contiguous ranges). The implementation of various
  304. // methods rely on this property.
  305. rr []IPRange
  306. }
  307. // Ranges returns the minimum and sorted set of IP
  308. // ranges that covers s.
  309. func (s *IPSet) Ranges() []IPRange {
  310. return append([]IPRange{}, s.rr...)
  311. }
  312. // Prefixes returns the minimum and sorted set of IP prefixes
  313. // that covers s.
  314. func (s *IPSet) Prefixes() []IPPrefix {
  315. out := make([]IPPrefix, 0, len(s.rr))
  316. for _, r := range s.rr {
  317. out = append(out, r.Prefixes()...)
  318. }
  319. return out
  320. }
  321. // Equal reports whether s and o represent the same set of IP
  322. // addresses.
  323. func (s *IPSet) Equal(o *IPSet) bool {
  324. if len(s.rr) != len(o.rr) {
  325. return false
  326. }
  327. for i := range s.rr {
  328. if s.rr[i] != o.rr[i] {
  329. return false
  330. }
  331. }
  332. return true
  333. }
  334. // Contains reports whether ip is in s.
  335. // If ip has an IPv6 zone, Contains returns false,
  336. // because IPSets do not track zones.
  337. func (s *IPSet) Contains(ip IP) bool {
  338. if ip.hasZone() {
  339. return false
  340. }
  341. // TODO: data structure permitting more efficient lookups:
  342. // https://github.com/inetaf/netaddr/issues/139
  343. i := sort.Search(len(s.rr), func(i int) bool {
  344. return ip.Less(s.rr[i].from)
  345. })
  346. if i == 0 {
  347. return false
  348. }
  349. i--
  350. return s.rr[i].contains(ip)
  351. }
  352. // ContainsRange reports whether all IPs in r are in s.
  353. func (s *IPSet) ContainsRange(r IPRange) bool {
  354. for _, x := range s.rr {
  355. if r.coveredBy(x) {
  356. return true
  357. }
  358. }
  359. return false
  360. }
  361. // ContainsPrefix reports whether all IPs in p are in s.
  362. func (s *IPSet) ContainsPrefix(p IPPrefix) bool {
  363. return s.ContainsRange(p.Range())
  364. }
  365. // Overlaps reports whether any IP in b is also in s.
  366. func (s *IPSet) Overlaps(b *IPSet) bool {
  367. // TODO: sorted ranges lets us do this in O(n+m)
  368. for _, r := range s.rr {
  369. for _, or := range b.rr {
  370. if r.Overlaps(or) {
  371. return true
  372. }
  373. }
  374. }
  375. return false
  376. }
  377. // OverlapsRange reports whether any IP in r is also in s.
  378. func (s *IPSet) OverlapsRange(r IPRange) bool {
  379. // TODO: sorted ranges lets us do this more efficiently.
  380. for _, x := range s.rr {
  381. if x.Overlaps(r) {
  382. return true
  383. }
  384. }
  385. return false
  386. }
  387. // OverlapsPrefix reports whether any IP in p is also in s.
  388. func (s *IPSet) OverlapsPrefix(p IPPrefix) bool {
  389. return s.OverlapsRange(p.Range())
  390. }
  391. // RemoveFreePrefix splits s into a Prefix of length bitLen and a new
  392. // IPSet with that prefix removed.
  393. //
  394. // If no contiguous prefix of length bitLen exists in s,
  395. // RemoveFreePrefix returns ok=false.
  396. func (s *IPSet) RemoveFreePrefix(bitLen uint8) (p IPPrefix, newSet *IPSet, ok bool) {
  397. var bestFit IPPrefix
  398. for _, r := range s.rr {
  399. for _, prefix := range r.Prefixes() {
  400. if prefix.bits > bitLen {
  401. continue
  402. }
  403. if bestFit.ip.IsZero() || prefix.bits > bestFit.bits {
  404. bestFit = prefix
  405. if bestFit.bits == bitLen {
  406. // exact match, done.
  407. break
  408. }
  409. }
  410. }
  411. }
  412. if bestFit.ip.IsZero() {
  413. return IPPrefix{}, s, false
  414. }
  415. prefix := IPPrefix{ip: bestFit.ip, bits: bitLen}
  416. var b IPSetBuilder
  417. b.AddSet(s)
  418. b.RemovePrefix(prefix)
  419. newSet, _ = b.IPSet()
  420. return prefix, newSet, true
  421. }
  422. type multiErr []error
  423. func (e multiErr) Error() string {
  424. var ret []string
  425. for _, err := range e {
  426. ret = append(ret, err.Error())
  427. }
  428. return strings.Join(ret, "; ")
  429. }
  430. // A stacktraceErr combines an error with a stack trace.
  431. type stacktraceErr struct {
  432. pcs [16]uintptr // preallocated array of PCs
  433. at []uintptr // stack trace whence the error
  434. err error // underlying error
  435. }
  436. func (e *stacktraceErr) Error() string {
  437. frames := runtime.CallersFrames(e.at)
  438. buf := new(strings.Builder)
  439. buf.WriteString(e.err.Error())
  440. buf.WriteString(" @ ")
  441. for {
  442. frame, more := frames.Next()
  443. if !more {
  444. break
  445. }
  446. fmt.Fprintf(buf, "%s:%d ", frame.File, frame.Line)
  447. }
  448. return strings.TrimSpace(buf.String())
  449. }
  450. func (e *stacktraceErr) Unwrap() error {
  451. return e.err
  452. }