ifaddrs.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  1. package sockaddr
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "regexp"
  7. "sort"
  8. "strconv"
  9. "strings"
  10. )
  11. // IfAddrs is a slice of IfAddr
  12. type IfAddrs []IfAddr
  13. func (ifs IfAddrs) Len() int { return len(ifs) }
  14. // CmpIfFunc is the function signature that must be met to be used in the
  15. // OrderedIfAddrBy multiIfAddrSorter
  16. type CmpIfAddrFunc func(p1, p2 *IfAddr) int
  17. // multiIfAddrSorter implements the Sort interface, sorting the IfAddrs within.
  18. type multiIfAddrSorter struct {
  19. ifAddrs IfAddrs
  20. cmp []CmpIfAddrFunc
  21. }
  22. // Sort sorts the argument slice according to the Cmp functions passed to
  23. // OrderedIfAddrBy.
  24. func (ms *multiIfAddrSorter) Sort(ifAddrs IfAddrs) {
  25. ms.ifAddrs = ifAddrs
  26. sort.Sort(ms)
  27. }
  28. // OrderedIfAddrBy sorts SockAddr by the list of sort function pointers.
  29. func OrderedIfAddrBy(cmpFuncs ...CmpIfAddrFunc) *multiIfAddrSorter {
  30. return &multiIfAddrSorter{
  31. cmp: cmpFuncs,
  32. }
  33. }
  34. // Len is part of sort.Interface.
  35. func (ms *multiIfAddrSorter) Len() int {
  36. return len(ms.ifAddrs)
  37. }
  38. // Less is part of sort.Interface. It is implemented by looping along the Cmp()
  39. // functions until it finds a comparison that is either less than or greater
  40. // than. A return value of 0 defers sorting to the next function in the
  41. // multisorter (which means the results of sorting may leave the resutls in a
  42. // non-deterministic order).
  43. func (ms *multiIfAddrSorter) Less(i, j int) bool {
  44. p, q := &ms.ifAddrs[i], &ms.ifAddrs[j]
  45. // Try all but the last comparison.
  46. var k int
  47. for k = 0; k < len(ms.cmp)-1; k++ {
  48. cmp := ms.cmp[k]
  49. x := cmp(p, q)
  50. switch x {
  51. case -1:
  52. // p < q, so we have a decision.
  53. return true
  54. case 1:
  55. // p > q, so we have a decision.
  56. return false
  57. }
  58. // p == q; try the next comparison.
  59. }
  60. // All comparisons to here said "equal", so just return whatever the
  61. // final comparison reports.
  62. switch ms.cmp[k](p, q) {
  63. case -1:
  64. return true
  65. case 1:
  66. return false
  67. default:
  68. // Still a tie! Now what?
  69. return false
  70. panic("undefined sort order for remaining items in the list")
  71. }
  72. }
  73. // Swap is part of sort.Interface.
  74. func (ms *multiIfAddrSorter) Swap(i, j int) {
  75. ms.ifAddrs[i], ms.ifAddrs[j] = ms.ifAddrs[j], ms.ifAddrs[i]
  76. }
  77. // AscIfAddress is a sorting function to sort IfAddrs by their respective
  78. // address type. Non-equal types are deferred in the sort.
  79. func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int {
  80. return AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  81. }
  82. // AscIfName is a sorting function to sort IfAddrs by their interface names.
  83. func AscIfName(p1Ptr, p2Ptr *IfAddr) int {
  84. return strings.Compare(p1Ptr.Name, p2Ptr.Name)
  85. }
  86. // AscIfNetworkSize is a sorting function to sort IfAddrs by their respective
  87. // network mask size.
  88. func AscIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
  89. return AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  90. }
  91. // AscIfPort is a sorting function to sort IfAddrs by their respective
  92. // port type. Non-equal types are deferred in the sort.
  93. func AscIfPort(p1Ptr, p2Ptr *IfAddr) int {
  94. return AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  95. }
  96. // AscIfPrivate is a sorting function to sort IfAddrs by "private" values before
  97. // "public" values. Both IPv4 and IPv6 are compared against RFC6890 (RFC6890
  98. // includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and IPv6
  99. // includes RFC4193).
  100. func AscIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
  101. return AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  102. }
  103. // AscIfType is a sorting function to sort IfAddrs by their respective address
  104. // type. Non-equal types are deferred in the sort.
  105. func AscIfType(p1Ptr, p2Ptr *IfAddr) int {
  106. return AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  107. }
  108. // DescIfAddress is identical to AscIfAddress but reverse ordered.
  109. func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int {
  110. return -1 * AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  111. }
  112. // DescIfName is identical to AscIfName but reverse ordered.
  113. func DescIfName(p1Ptr, p2Ptr *IfAddr) int {
  114. return -1 * strings.Compare(p1Ptr.Name, p2Ptr.Name)
  115. }
  116. // DescIfNetworkSize is identical to AscIfNetworkSize but reverse ordered.
  117. func DescIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
  118. return -1 * AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  119. }
  120. // DescIfPort is identical to AscIfPort but reverse ordered.
  121. func DescIfPort(p1Ptr, p2Ptr *IfAddr) int {
  122. return -1 * AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  123. }
  124. // DescIfPrivate is identical to AscIfPrivate but reverse ordered.
  125. func DescIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
  126. return -1 * AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  127. }
  128. // DescIfType is identical to AscIfType but reverse ordered.
  129. func DescIfType(p1Ptr, p2Ptr *IfAddr) int {
  130. return -1 * AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  131. }
  132. // FilterIfByType filters IfAddrs and returns a list of the matching type
  133. func FilterIfByType(ifAddrs IfAddrs, type_ SockAddrType) (matchedIfs, excludedIfs IfAddrs) {
  134. excludedIfs = make(IfAddrs, 0, len(ifAddrs))
  135. matchedIfs = make(IfAddrs, 0, len(ifAddrs))
  136. for _, ifAddr := range ifAddrs {
  137. if ifAddr.SockAddr.Type()&type_ != 0 {
  138. matchedIfs = append(matchedIfs, ifAddr)
  139. } else {
  140. excludedIfs = append(excludedIfs, ifAddr)
  141. }
  142. }
  143. return matchedIfs, excludedIfs
  144. }
  145. // IfAttr forwards the selector to IfAttr.Attr() for resolution. If there is
  146. // more than one IfAddr, only the first IfAddr is used.
  147. func IfAttr(selectorName string, ifAddrs IfAddrs) (string, error) {
  148. if len(ifAddrs) == 0 {
  149. return "", nil
  150. }
  151. attrName := AttrName(strings.ToLower(selectorName))
  152. attrVal, err := ifAddrs[0].Attr(attrName)
  153. return attrVal, err
  154. }
  155. // GetAllInterfaces iterates over all available network interfaces and finds all
  156. // available IP addresses on each interface and converts them to
  157. // sockaddr.IPAddrs, and returning the result as an array of IfAddr.
  158. func GetAllInterfaces() (IfAddrs, error) {
  159. ifs, err := net.Interfaces()
  160. if err != nil {
  161. return nil, err
  162. }
  163. ifAddrs := make(IfAddrs, 0, len(ifs))
  164. for _, intf := range ifs {
  165. addrs, err := intf.Addrs()
  166. if err != nil {
  167. return nil, err
  168. }
  169. for _, addr := range addrs {
  170. var ipAddr IPAddr
  171. ipAddr, err = NewIPAddr(addr.String())
  172. if err != nil {
  173. return IfAddrs{}, fmt.Errorf("unable to create an IP address from %q", addr.String())
  174. }
  175. ifAddr := IfAddr{
  176. SockAddr: ipAddr,
  177. Interface: intf,
  178. }
  179. ifAddrs = append(ifAddrs, ifAddr)
  180. }
  181. }
  182. return ifAddrs, nil
  183. }
  184. // GetDefaultInterfaces returns IfAddrs of the addresses attached to the default
  185. // route.
  186. func GetDefaultInterfaces() (IfAddrs, error) {
  187. ri, err := NewRouteInfo()
  188. if err != nil {
  189. return nil, err
  190. }
  191. defaultIfName, err := ri.GetDefaultInterfaceName()
  192. if err != nil {
  193. return nil, err
  194. }
  195. var defaultIfs, ifAddrs IfAddrs
  196. ifAddrs, err = GetAllInterfaces()
  197. for _, ifAddr := range ifAddrs {
  198. if ifAddr.Name == defaultIfName {
  199. defaultIfs = append(defaultIfs, ifAddr)
  200. }
  201. }
  202. return defaultIfs, nil
  203. }
  204. // GetPrivateInterfaces returns an IfAddrs that are part of RFC 6890 and have a
  205. // default route. If the system can't determine its IP address or find an RFC
  206. // 6890 IP address, an empty IfAddrs will be returned instead. This function is
  207. // the `eval` equivalent of:
  208. //
  209. // ```
  210. // $ sockaddr eval -r '{{GetDefaultInterfaces | include "type" "ip" | include "flags" "forwardable|up" | sort "type,size" | include "RFC" "6890" }}'
  211. /// ```
  212. func GetPrivateInterfaces() (IfAddrs, error) {
  213. privateIfs, err := GetDefaultInterfaces()
  214. if err != nil {
  215. return IfAddrs{}, err
  216. }
  217. if len(privateIfs) == 0 {
  218. return IfAddrs{}, nil
  219. }
  220. privateIfs, _ = FilterIfByType(privateIfs, TypeIP)
  221. if len(privateIfs) == 0 {
  222. return IfAddrs{}, nil
  223. }
  224. privateIfs, _, err = IfByFlag("forwardable|up", privateIfs)
  225. if err != nil {
  226. return IfAddrs{}, err
  227. }
  228. if len(privateIfs) == 0 {
  229. return IfAddrs{}, nil
  230. }
  231. OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(privateIfs)
  232. privateIfs, _, err = IfByRFC("6890", privateIfs)
  233. if err != nil {
  234. return IfAddrs{}, err
  235. } else if len(privateIfs) == 0 {
  236. return IfAddrs{}, nil
  237. }
  238. return privateIfs, nil
  239. }
  240. // GetPublicInterfaces returns an IfAddrs that are NOT part of RFC 6890 and has a
  241. // default route. If the system can't determine its IP address or find a non
  242. // RFC 6890 IP address, an empty IfAddrs will be returned instead. This
  243. // function is the `eval` equivalent of:
  244. //
  245. // ```
  246. // $ sockaddr eval -r '{{GetDefaultInterfaces | include "type" "ip" | include "flags" "forwardable|up" | sort "type,size" | exclude "RFC" "6890" }}'
  247. /// ```
  248. func GetPublicInterfaces() (IfAddrs, error) {
  249. publicIfs, err := GetDefaultInterfaces()
  250. if err != nil {
  251. return IfAddrs{}, err
  252. }
  253. if len(publicIfs) == 0 {
  254. return IfAddrs{}, nil
  255. }
  256. publicIfs, _ = FilterIfByType(publicIfs, TypeIP)
  257. if len(publicIfs) == 0 {
  258. return IfAddrs{}, nil
  259. }
  260. publicIfs, _, err = IfByFlag("forwardable|up", publicIfs)
  261. if err != nil {
  262. return IfAddrs{}, err
  263. }
  264. if len(publicIfs) == 0 {
  265. return IfAddrs{}, nil
  266. }
  267. OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(publicIfs)
  268. _, publicIfs, err = IfByRFC("6890", publicIfs)
  269. if err != nil {
  270. return IfAddrs{}, err
  271. } else if len(publicIfs) == 0 {
  272. return IfAddrs{}, nil
  273. }
  274. return publicIfs, nil
  275. }
  276. // IfByAddress returns a list of matched and non-matched IfAddrs, or an error if
  277. // the regexp fails to compile.
  278. func IfByAddress(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  279. re, err := regexp.Compile(inputRe)
  280. if err != nil {
  281. return nil, nil, fmt.Errorf("Unable to compile address regexp %+q: %v", inputRe, err)
  282. }
  283. matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
  284. excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
  285. for _, addr := range ifAddrs {
  286. if re.MatchString(addr.SockAddr.String()) {
  287. matchedAddrs = append(matchedAddrs, addr)
  288. } else {
  289. excludedAddrs = append(excludedAddrs, addr)
  290. }
  291. }
  292. return matchedAddrs, excludedAddrs, nil
  293. }
  294. // IfByName returns a list of matched and non-matched IfAddrs, or an error if
  295. // the regexp fails to compile.
  296. func IfByName(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  297. re, err := regexp.Compile(inputRe)
  298. if err != nil {
  299. return nil, nil, fmt.Errorf("Unable to compile name regexp %+q: %v", inputRe, err)
  300. }
  301. matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
  302. excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
  303. for _, addr := range ifAddrs {
  304. if re.MatchString(addr.Name) {
  305. matchedAddrs = append(matchedAddrs, addr)
  306. } else {
  307. excludedAddrs = append(excludedAddrs, addr)
  308. }
  309. }
  310. return matchedAddrs, excludedAddrs, nil
  311. }
  312. // IfByPort returns a list of matched and non-matched IfAddrs, or an error if
  313. // the regexp fails to compile.
  314. func IfByPort(inputRe string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) {
  315. re, err := regexp.Compile(inputRe)
  316. if err != nil {
  317. return nil, nil, fmt.Errorf("Unable to compile port regexp %+q: %v", inputRe, err)
  318. }
  319. ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP)
  320. matchedIfs = make(IfAddrs, 0, len(ipIfs))
  321. excludedIfs = append(IfAddrs(nil), nonIfs...)
  322. for _, addr := range ipIfs {
  323. ipAddr := ToIPAddr(addr.SockAddr)
  324. if ipAddr == nil {
  325. continue
  326. }
  327. port := strconv.FormatInt(int64((*ipAddr).IPPort()), 10)
  328. if re.MatchString(port) {
  329. matchedIfs = append(matchedIfs, addr)
  330. } else {
  331. excludedIfs = append(excludedIfs, addr)
  332. }
  333. }
  334. return matchedIfs, excludedIfs, nil
  335. }
  336. // IfByRFC returns a list of matched and non-matched IfAddrs that contain the
  337. // relevant RFC-specified traits.
  338. func IfByRFC(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  339. inputRFC, err := strconv.ParseUint(selectorParam, 10, 64)
  340. if err != nil {
  341. return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to parse RFC number %q: %v", selectorParam, err)
  342. }
  343. matchedIfAddrs := make(IfAddrs, 0, len(ifAddrs))
  344. remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
  345. rfcNetMap := KnownRFCs()
  346. rfcNets, ok := rfcNetMap[uint(inputRFC)]
  347. if !ok {
  348. return nil, nil, fmt.Errorf("unsupported RFC %d", inputRFC)
  349. }
  350. for _, ifAddr := range ifAddrs {
  351. var contained bool
  352. for _, rfcNet := range rfcNets {
  353. if rfcNet.Contains(ifAddr.SockAddr) {
  354. matchedIfAddrs = append(matchedIfAddrs, ifAddr)
  355. contained = true
  356. break
  357. }
  358. }
  359. if !contained {
  360. remainingIfAddrs = append(remainingIfAddrs, ifAddr)
  361. }
  362. }
  363. return matchedIfAddrs, remainingIfAddrs, nil
  364. }
  365. // IfByRFCs returns a list of matched and non-matched IfAddrs that contain the
  366. // relevant RFC-specified traits. Multiple RFCs can be specified and separated
  367. // by the `|` symbol. No protection is taken to ensure an IfAddr does not end
  368. // up in both the included and excluded list.
  369. func IfByRFCs(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  370. var includedIfs, excludedIfs IfAddrs
  371. for _, rfcStr := range strings.Split(selectorParam, "|") {
  372. includedRFCIfs, excludedRFCIfs, err := IfByRFC(rfcStr, ifAddrs)
  373. if err != nil {
  374. return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to lookup RFC number %q: %v", rfcStr, err)
  375. }
  376. includedIfs = append(includedIfs, includedRFCIfs...)
  377. excludedIfs = append(excludedIfs, excludedRFCIfs...)
  378. }
  379. return includedIfs, excludedIfs, nil
  380. }
  381. // IfByMaskSize returns a list of matched and non-matched IfAddrs that have the
  382. // matching mask size.
  383. func IfByMaskSize(selectorParam string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) {
  384. maskSize, err := strconv.ParseUint(selectorParam, 10, 64)
  385. if err != nil {
  386. return IfAddrs{}, IfAddrs{}, fmt.Errorf("invalid exclude size argument (%q): %v", selectorParam, err)
  387. }
  388. ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP)
  389. matchedIfs = make(IfAddrs, 0, len(ipIfs))
  390. excludedIfs = append(IfAddrs(nil), nonIfs...)
  391. for _, addr := range ipIfs {
  392. ipAddr := ToIPAddr(addr.SockAddr)
  393. if ipAddr == nil {
  394. return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to filter mask sizes on non-IP type %s: %v", addr.SockAddr.Type().String(), addr.SockAddr.String())
  395. }
  396. switch {
  397. case (*ipAddr).Type()&TypeIPv4 != 0 && maskSize > 32:
  398. return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv4 address: %d", maskSize)
  399. case (*ipAddr).Type()&TypeIPv6 != 0 && maskSize > 128:
  400. return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv6 address: %d", maskSize)
  401. }
  402. if (*ipAddr).Maskbits() == int(maskSize) {
  403. matchedIfs = append(matchedIfs, addr)
  404. } else {
  405. excludedIfs = append(excludedIfs, addr)
  406. }
  407. }
  408. return matchedIfs, excludedIfs, nil
  409. }
  410. // IfByType returns a list of matching and non-matching IfAddr that match the
  411. // specified type. For instance:
  412. //
  413. // include "type" "IPv4,IPv6"
  414. //
  415. // will include any IfAddrs that is either an IPv4 or IPv6 address. Any
  416. // addresses on those interfaces that don't match will be included in the
  417. // remainder results.
  418. func IfByType(inputTypes string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  419. matchingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
  420. remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
  421. ifTypes := strings.Split(strings.ToLower(inputTypes), "|")
  422. for _, ifType := range ifTypes {
  423. switch ifType {
  424. case "ip", "ipv4", "ipv6", "unix":
  425. // Valid types
  426. default:
  427. return nil, nil, fmt.Errorf("unsupported type %q %q", ifType, inputTypes)
  428. }
  429. }
  430. for _, ifAddr := range ifAddrs {
  431. for _, ifType := range ifTypes {
  432. var matched bool
  433. switch {
  434. case ifType == "ip" && ifAddr.SockAddr.Type()&TypeIP != 0:
  435. matched = true
  436. case ifType == "ipv4" && ifAddr.SockAddr.Type()&TypeIPv4 != 0:
  437. matched = true
  438. case ifType == "ipv6" && ifAddr.SockAddr.Type()&TypeIPv6 != 0:
  439. matched = true
  440. case ifType == "unix" && ifAddr.SockAddr.Type()&TypeUnix != 0:
  441. matched = true
  442. }
  443. if matched {
  444. matchingIfAddrs = append(matchingIfAddrs, ifAddr)
  445. } else {
  446. remainingIfAddrs = append(remainingIfAddrs, ifAddr)
  447. }
  448. }
  449. }
  450. return matchingIfAddrs, remainingIfAddrs, nil
  451. }
  452. // IfByFlag returns a list of matching and non-matching IfAddrs that match the
  453. // specified type. For instance:
  454. //
  455. // include "flag" "up,broadcast"
  456. //
  457. // will include any IfAddrs that have both the "up" and "broadcast" flags set.
  458. // Any addresses on those interfaces that don't match will be omitted from the
  459. // results.
  460. func IfByFlag(inputFlags string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  461. matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
  462. excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
  463. var wantForwardable,
  464. wantGlobalUnicast,
  465. wantInterfaceLocalMulticast,
  466. wantLinkLocalMulticast,
  467. wantLinkLocalUnicast,
  468. wantLoopback,
  469. wantMulticast,
  470. wantUnspecified bool
  471. var ifFlags net.Flags
  472. var checkFlags, checkAttrs bool
  473. for _, flagName := range strings.Split(strings.ToLower(inputFlags), "|") {
  474. switch flagName {
  475. case "broadcast":
  476. checkFlags = true
  477. ifFlags = ifFlags | net.FlagBroadcast
  478. case "down":
  479. checkFlags = true
  480. ifFlags = (ifFlags &^ net.FlagUp)
  481. case "forwardable":
  482. checkAttrs = true
  483. wantForwardable = true
  484. case "global unicast":
  485. checkAttrs = true
  486. wantGlobalUnicast = true
  487. case "interface-local multicast":
  488. checkAttrs = true
  489. wantInterfaceLocalMulticast = true
  490. case "link-local multicast":
  491. checkAttrs = true
  492. wantLinkLocalMulticast = true
  493. case "link-local unicast":
  494. checkAttrs = true
  495. wantLinkLocalUnicast = true
  496. case "loopback":
  497. checkAttrs = true
  498. checkFlags = true
  499. ifFlags = ifFlags | net.FlagLoopback
  500. wantLoopback = true
  501. case "multicast":
  502. checkAttrs = true
  503. checkFlags = true
  504. ifFlags = ifFlags | net.FlagMulticast
  505. wantMulticast = true
  506. case "point-to-point":
  507. checkFlags = true
  508. ifFlags = ifFlags | net.FlagPointToPoint
  509. case "unspecified":
  510. checkAttrs = true
  511. wantUnspecified = true
  512. case "up":
  513. checkFlags = true
  514. ifFlags = ifFlags | net.FlagUp
  515. default:
  516. return nil, nil, fmt.Errorf("Unknown interface flag: %+q", flagName)
  517. }
  518. }
  519. for _, ifAddr := range ifAddrs {
  520. var matched bool
  521. if checkFlags && ifAddr.Interface.Flags&ifFlags == ifFlags {
  522. matched = true
  523. }
  524. if checkAttrs {
  525. if ip := ToIPAddr(ifAddr.SockAddr); ip != nil {
  526. netIP := (*ip).NetIP()
  527. switch {
  528. case wantGlobalUnicast && netIP.IsGlobalUnicast():
  529. matched = true
  530. case wantInterfaceLocalMulticast && netIP.IsInterfaceLocalMulticast():
  531. matched = true
  532. case wantLinkLocalMulticast && netIP.IsLinkLocalMulticast():
  533. matched = true
  534. case wantLinkLocalUnicast && netIP.IsLinkLocalUnicast():
  535. matched = true
  536. case wantLoopback && netIP.IsLoopback():
  537. matched = true
  538. case wantMulticast && netIP.IsMulticast():
  539. matched = true
  540. case wantUnspecified && netIP.IsUnspecified():
  541. matched = true
  542. case wantForwardable && !IsRFC(ForwardingBlacklist, ifAddr.SockAddr):
  543. matched = true
  544. }
  545. }
  546. }
  547. if matched {
  548. matchedAddrs = append(matchedAddrs, ifAddr)
  549. } else {
  550. excludedAddrs = append(excludedAddrs, ifAddr)
  551. }
  552. }
  553. return matchedAddrs, excludedAddrs, nil
  554. }
  555. // IfByNetwork returns an IfAddrs that are equal to or included within the
  556. // network passed in by selector.
  557. func IfByNetwork(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, IfAddrs, error) {
  558. var includedIfs, excludedIfs IfAddrs
  559. for _, netStr := range strings.Split(selectorParam, "|") {
  560. netAddr, err := NewIPAddr(netStr)
  561. if err != nil {
  562. return nil, nil, fmt.Errorf("unable to create an IP address from %+q: %v", netStr, err)
  563. }
  564. for _, ifAddr := range inputIfAddrs {
  565. if netAddr.Contains(ifAddr.SockAddr) {
  566. includedIfs = append(includedIfs, ifAddr)
  567. } else {
  568. excludedIfs = append(excludedIfs, ifAddr)
  569. }
  570. }
  571. }
  572. return includedIfs, excludedIfs, nil
  573. }
  574. // IncludeIfs returns an IfAddrs based on the passed in selector.
  575. func IncludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  576. var includedIfs IfAddrs
  577. var err error
  578. switch strings.ToLower(selectorName) {
  579. case "address":
  580. includedIfs, _, err = IfByAddress(selectorParam, inputIfAddrs)
  581. case "flag", "flags":
  582. includedIfs, _, err = IfByFlag(selectorParam, inputIfAddrs)
  583. case "name":
  584. includedIfs, _, err = IfByName(selectorParam, inputIfAddrs)
  585. case "network":
  586. includedIfs, _, err = IfByNetwork(selectorParam, inputIfAddrs)
  587. case "port":
  588. includedIfs, _, err = IfByPort(selectorParam, inputIfAddrs)
  589. case "rfc", "rfcs":
  590. includedIfs, _, err = IfByRFCs(selectorParam, inputIfAddrs)
  591. case "size":
  592. includedIfs, _, err = IfByMaskSize(selectorParam, inputIfAddrs)
  593. case "type":
  594. includedIfs, _, err = IfByType(selectorParam, inputIfAddrs)
  595. default:
  596. return IfAddrs{}, fmt.Errorf("invalid include selector %q", selectorName)
  597. }
  598. if err != nil {
  599. return IfAddrs{}, err
  600. }
  601. return includedIfs, nil
  602. }
  603. // ExcludeIfs returns an IfAddrs based on the passed in selector.
  604. func ExcludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  605. var excludedIfs IfAddrs
  606. var err error
  607. switch strings.ToLower(selectorName) {
  608. case "address":
  609. _, excludedIfs, err = IfByAddress(selectorParam, inputIfAddrs)
  610. case "flag", "flags":
  611. _, excludedIfs, err = IfByFlag(selectorParam, inputIfAddrs)
  612. case "name":
  613. _, excludedIfs, err = IfByName(selectorParam, inputIfAddrs)
  614. case "network":
  615. _, excludedIfs, err = IfByNetwork(selectorParam, inputIfAddrs)
  616. case "port":
  617. _, excludedIfs, err = IfByPort(selectorParam, inputIfAddrs)
  618. case "rfc", "rfcs":
  619. _, excludedIfs, err = IfByRFCs(selectorParam, inputIfAddrs)
  620. case "size":
  621. _, excludedIfs, err = IfByMaskSize(selectorParam, inputIfAddrs)
  622. case "type":
  623. _, excludedIfs, err = IfByType(selectorParam, inputIfAddrs)
  624. default:
  625. return IfAddrs{}, fmt.Errorf("invalid exclude selector %q", selectorName)
  626. }
  627. if err != nil {
  628. return IfAddrs{}, err
  629. }
  630. return excludedIfs, nil
  631. }
  632. // SortIfBy returns an IfAddrs sorted based on the passed in selector. Multiple
  633. // sort clauses can be passed in as a comma delimited list without whitespace.
  634. func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  635. sortedIfs := append(IfAddrs(nil), inputIfAddrs...)
  636. clauses := strings.Split(selectorParam, ",")
  637. sortFuncs := make([]CmpIfAddrFunc, len(clauses))
  638. for i, clause := range clauses {
  639. switch strings.TrimSpace(strings.ToLower(clause)) {
  640. case "+address", "address":
  641. // The "address" selector returns an array of IfAddrs
  642. // ordered by the network address. IfAddrs that are not
  643. // comparable will be at the end of the list and in a
  644. // non-deterministic order.
  645. sortFuncs[i] = AscIfAddress
  646. case "-address":
  647. sortFuncs[i] = DescIfAddress
  648. case "+name", "name":
  649. // The "name" selector returns an array of IfAddrs
  650. // ordered by the interface name.
  651. sortFuncs[i] = AscIfName
  652. case "-name":
  653. sortFuncs[i] = DescIfName
  654. case "+port", "port":
  655. // The "port" selector returns an array of IfAddrs
  656. // ordered by the port, if included in the IfAddr.
  657. // IfAddrs that are not comparable will be at the end of
  658. // the list and in a non-deterministic order.
  659. sortFuncs[i] = AscIfPort
  660. case "-port":
  661. sortFuncs[i] = DescIfPort
  662. case "+private", "private":
  663. // The "private" selector returns an array of IfAddrs
  664. // ordered by private addresses first. IfAddrs that are
  665. // not comparable will be at the end of the list and in
  666. // a non-deterministic order.
  667. sortFuncs[i] = AscIfPrivate
  668. case "-private":
  669. sortFuncs[i] = DescIfPrivate
  670. case "+size", "size":
  671. // The "size" selector returns an array of IfAddrs
  672. // ordered by the size of the network mask, smaller mask
  673. // (larger number of hosts per network) to largest
  674. // (e.g. a /24 sorts before a /32).
  675. sortFuncs[i] = AscIfNetworkSize
  676. case "-size":
  677. sortFuncs[i] = DescIfNetworkSize
  678. case "+type", "type":
  679. // The "type" selector returns an array of IfAddrs
  680. // ordered by the type of the IfAddr. The sort order is
  681. // Unix, IPv4, then IPv6.
  682. sortFuncs[i] = AscIfType
  683. case "-type":
  684. sortFuncs[i] = DescIfType
  685. default:
  686. // Return an empty list for invalid sort types.
  687. return IfAddrs{}, fmt.Errorf("unknown sort type: %q", clause)
  688. }
  689. }
  690. OrderedIfAddrBy(sortFuncs...).Sort(sortedIfs)
  691. return sortedIfs, nil
  692. }
  693. // UniqueIfAddrsBy creates a unique set of IfAddrs based on the matching
  694. // selector. UniqueIfAddrsBy assumes the input has already been sorted.
  695. func UniqueIfAddrsBy(selectorName string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  696. attrName := strings.ToLower(selectorName)
  697. ifs := make(IfAddrs, 0, len(inputIfAddrs))
  698. var lastMatch string
  699. for _, ifAddr := range inputIfAddrs {
  700. var out string
  701. switch attrName {
  702. case "address":
  703. out = ifAddr.SockAddr.String()
  704. case "name":
  705. out = ifAddr.Name
  706. default:
  707. return nil, fmt.Errorf("unsupported unique constraint %+q", selectorName)
  708. }
  709. switch {
  710. case lastMatch == "", lastMatch != out:
  711. lastMatch = out
  712. ifs = append(ifs, ifAddr)
  713. case lastMatch == out:
  714. continue
  715. }
  716. }
  717. return ifs, nil
  718. }
  719. // JoinIfAddrs joins an IfAddrs and returns a string
  720. func JoinIfAddrs(selectorName string, joinStr string, inputIfAddrs IfAddrs) (string, error) {
  721. outputs := make([]string, 0, len(inputIfAddrs))
  722. attrName := AttrName(strings.ToLower(selectorName))
  723. for _, ifAddr := range inputIfAddrs {
  724. var attrVal string
  725. var err error
  726. attrVal, err = ifAddr.Attr(attrName)
  727. if err != nil {
  728. return "", err
  729. }
  730. outputs = append(outputs, attrVal)
  731. }
  732. return strings.Join(outputs, joinStr), nil
  733. }
  734. // LimitIfAddrs returns a slice of IfAddrs based on the specified limit.
  735. func LimitIfAddrs(lim uint, in IfAddrs) (IfAddrs, error) {
  736. // Clamp the limit to the length of the array
  737. if int(lim) > len(in) {
  738. lim = uint(len(in))
  739. }
  740. return in[0:lim], nil
  741. }
  742. // OffsetIfAddrs returns a slice of IfAddrs based on the specified offset.
  743. func OffsetIfAddrs(off int, in IfAddrs) (IfAddrs, error) {
  744. var end bool
  745. if off < 0 {
  746. end = true
  747. off = off * -1
  748. }
  749. if off > len(in) {
  750. return IfAddrs{}, fmt.Errorf("unable to seek past the end of the interface array: offset (%d) exceeds the number of interfaces (%d)", off, len(in))
  751. }
  752. if end {
  753. return in[len(in)-off:], nil
  754. }
  755. return in[off:], nil
  756. }
  757. func (ifAddr IfAddr) String() string {
  758. return fmt.Sprintf("%s %v", ifAddr.SockAddr, ifAddr.Interface)
  759. }
  760. // parseDefaultIfNameFromRoute parses standard route(8)'s output for the *BSDs
  761. // and Solaris.
  762. func parseDefaultIfNameFromRoute(routeOut string) (string, error) {
  763. lines := strings.Split(routeOut, "\n")
  764. for _, line := range lines {
  765. kvs := strings.SplitN(line, ":", 2)
  766. if len(kvs) != 2 {
  767. continue
  768. }
  769. if strings.TrimSpace(kvs[0]) == "interface" {
  770. ifName := strings.TrimSpace(kvs[1])
  771. return ifName, nil
  772. }
  773. }
  774. return "", errors.New("No default interface found")
  775. }
  776. // parseDefaultIfNameFromIPCmd parses the default interface from ip(8) for
  777. // Linux.
  778. func parseDefaultIfNameFromIPCmd(routeOut string) (string, error) {
  779. lines := strings.Split(routeOut, "\n")
  780. re := regexp.MustCompile(`[\s]+`)
  781. for _, line := range lines {
  782. kvs := re.Split(line, -1)
  783. if len(kvs) < 5 {
  784. continue
  785. }
  786. if kvs[0] == "default" &&
  787. kvs[1] == "via" &&
  788. kvs[3] == "dev" {
  789. ifName := strings.TrimSpace(kvs[4])
  790. return ifName, nil
  791. }
  792. }
  793. return "", errors.New("No default interface found")
  794. }
  795. // parseDefaultIfNameWindows parses the default interface from `netstat -rn` and
  796. // `ipconfig` on Windows.
  797. func parseDefaultIfNameWindows(routeOut, ipconfigOut string) (string, error) {
  798. defaultIPAddr, err := parseDefaultIPAddrWindowsRoute(routeOut)
  799. if err != nil {
  800. return "", err
  801. }
  802. ifName, err := parseDefaultIfNameWindowsIPConfig(defaultIPAddr, ipconfigOut)
  803. if err != nil {
  804. return "", err
  805. }
  806. return ifName, nil
  807. }
  808. // parseDefaultIPAddrWindowsRoute parses the IP address on the default interface
  809. // `netstat -rn`.
  810. //
  811. // NOTES(sean): Only IPv4 addresses are parsed at this time. If you have an
  812. // IPv6 connected host, submit an issue on github.com/hashicorp/go-sockaddr with
  813. // the output from `netstat -rn`, `ipconfig`, and version of Windows to see IPv6
  814. // support added.
  815. func parseDefaultIPAddrWindowsRoute(routeOut string) (string, error) {
  816. lines := strings.Split(routeOut, "\n")
  817. re := regexp.MustCompile(`[\s]+`)
  818. for _, line := range lines {
  819. kvs := re.Split(strings.TrimSpace(line), -1)
  820. if len(kvs) < 3 {
  821. continue
  822. }
  823. if kvs[0] == "0.0.0.0" && kvs[1] == "0.0.0.0" {
  824. defaultIPAddr := strings.TrimSpace(kvs[3])
  825. return defaultIPAddr, nil
  826. }
  827. }
  828. return "", errors.New("No IP on default interface found")
  829. }
  830. // parseDefaultIfNameWindowsIPConfig parses the output of `ipconfig` to find the
  831. // interface name forwarding traffic to the default gateway.
  832. func parseDefaultIfNameWindowsIPConfig(defaultIPAddr, routeOut string) (string, error) {
  833. lines := strings.Split(routeOut, "\n")
  834. ifNameRE := regexp.MustCompile(`^Ethernet adapter ([^\s:]+):`)
  835. ipAddrRE := regexp.MustCompile(`^ IPv[46] Address\. \. \. \. \. \. \. \. \. \. \. : ([^\s]+)`)
  836. var ifName string
  837. for _, line := range lines {
  838. switch ifNameMatches := ifNameRE.FindStringSubmatch(line); {
  839. case len(ifNameMatches) > 1:
  840. ifName = ifNameMatches[1]
  841. continue
  842. }
  843. switch ipAddrMatches := ipAddrRE.FindStringSubmatch(line); {
  844. case len(ipAddrMatches) > 1 && ipAddrMatches[1] == defaultIPAddr:
  845. return ifName, nil
  846. }
  847. }
  848. return "", errors.New("No default interface found with matching IP")
  849. }