ifaddrs.go 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  1. package sockaddr
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. "math/big"
  7. "net"
  8. "regexp"
  9. "sort"
  10. "strconv"
  11. "strings"
  12. )
  13. var (
  14. // Centralize all regexps and regexp.Copy() where necessary.
  15. signRE *regexp.Regexp = regexp.MustCompile(`^[\s]*[+-]`)
  16. whitespaceRE *regexp.Regexp = regexp.MustCompile(`[\s]+`)
  17. ifNameRE *regexp.Regexp = regexp.MustCompile(`^(?:Ethernet|Wireless LAN) adapter ([^:]+):`)
  18. ipAddrRE *regexp.Regexp = regexp.MustCompile(`^ IPv[46] Address\. \. \. \. \. \. \. \. \. \. \. : ([^\s]+)`)
  19. )
  20. // IfAddrs is a slice of IfAddr
  21. type IfAddrs []IfAddr
  22. func (ifs IfAddrs) Len() int { return len(ifs) }
  23. // CmpIfFunc is the function signature that must be met to be used in the
  24. // OrderedIfAddrBy multiIfAddrSorter
  25. type CmpIfAddrFunc func(p1, p2 *IfAddr) int
  26. // multiIfAddrSorter implements the Sort interface, sorting the IfAddrs within.
  27. type multiIfAddrSorter struct {
  28. ifAddrs IfAddrs
  29. cmp []CmpIfAddrFunc
  30. }
  31. // Sort sorts the argument slice according to the Cmp functions passed to
  32. // OrderedIfAddrBy.
  33. func (ms *multiIfAddrSorter) Sort(ifAddrs IfAddrs) {
  34. ms.ifAddrs = ifAddrs
  35. sort.Sort(ms)
  36. }
  37. // OrderedIfAddrBy sorts SockAddr by the list of sort function pointers.
  38. func OrderedIfAddrBy(cmpFuncs ...CmpIfAddrFunc) *multiIfAddrSorter {
  39. return &multiIfAddrSorter{
  40. cmp: cmpFuncs,
  41. }
  42. }
  43. // Len is part of sort.Interface.
  44. func (ms *multiIfAddrSorter) Len() int {
  45. return len(ms.ifAddrs)
  46. }
  47. // Less is part of sort.Interface. It is implemented by looping along the Cmp()
  48. // functions until it finds a comparison that is either less than or greater
  49. // than. A return value of 0 defers sorting to the next function in the
  50. // multisorter (which means the results of sorting may leave the resutls in a
  51. // non-deterministic order).
  52. func (ms *multiIfAddrSorter) Less(i, j int) bool {
  53. p, q := &ms.ifAddrs[i], &ms.ifAddrs[j]
  54. // Try all but the last comparison.
  55. var k int
  56. for k = 0; k < len(ms.cmp)-1; k++ {
  57. cmp := ms.cmp[k]
  58. x := cmp(p, q)
  59. switch x {
  60. case -1:
  61. // p < q, so we have a decision.
  62. return true
  63. case 1:
  64. // p > q, so we have a decision.
  65. return false
  66. }
  67. // p == q; try the next comparison.
  68. }
  69. // All comparisons to here said "equal", so just return whatever the
  70. // final comparison reports.
  71. switch ms.cmp[k](p, q) {
  72. case -1:
  73. return true
  74. case 1:
  75. return false
  76. default:
  77. // Still a tie! Now what?
  78. return false
  79. panic("undefined sort order for remaining items in the list")
  80. }
  81. }
  82. // Swap is part of sort.Interface.
  83. func (ms *multiIfAddrSorter) Swap(i, j int) {
  84. ms.ifAddrs[i], ms.ifAddrs[j] = ms.ifAddrs[j], ms.ifAddrs[i]
  85. }
  86. // AscIfAddress is a sorting function to sort IfAddrs by their respective
  87. // address type. Non-equal types are deferred in the sort.
  88. func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int {
  89. return AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  90. }
  91. // AscIfDefault is a sorting function to sort IfAddrs by whether or not they
  92. // have a default route or not. Non-equal types are deferred in the sort.
  93. //
  94. // FIXME: This is a particularly expensive sorting operation because of the
  95. // non-memoized calls to NewRouteInfo(). In an ideal world the routeInfo data
  96. // once at the start of the sort and pass it along as a context or by wrapping
  97. // the IfAddr type with this information (this would also solve the inability to
  98. // return errors and the possibility of failing silently). Fortunately,
  99. // N*log(N) where N = 3 is only ~6.2 invocations. Not ideal, but not worth
  100. // optimizing today. The common case is this gets called once or twice.
  101. // Patches welcome.
  102. func AscIfDefault(p1Ptr, p2Ptr *IfAddr) int {
  103. ri, err := NewRouteInfo()
  104. if err != nil {
  105. return sortDeferDecision
  106. }
  107. defaultIfName, err := ri.GetDefaultInterfaceName()
  108. if err != nil {
  109. return sortDeferDecision
  110. }
  111. switch {
  112. case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName:
  113. return sortDeferDecision
  114. case p1Ptr.Interface.Name == defaultIfName:
  115. return sortReceiverBeforeArg
  116. case p2Ptr.Interface.Name == defaultIfName:
  117. return sortArgBeforeReceiver
  118. default:
  119. return sortDeferDecision
  120. }
  121. }
  122. // AscIfName is a sorting function to sort IfAddrs by their interface names.
  123. func AscIfName(p1Ptr, p2Ptr *IfAddr) int {
  124. return strings.Compare(p1Ptr.Name, p2Ptr.Name)
  125. }
  126. // AscIfNetworkSize is a sorting function to sort IfAddrs by their respective
  127. // network mask size.
  128. func AscIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
  129. return AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  130. }
  131. // AscIfPort is a sorting function to sort IfAddrs by their respective
  132. // port type. Non-equal types are deferred in the sort.
  133. func AscIfPort(p1Ptr, p2Ptr *IfAddr) int {
  134. return AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  135. }
  136. // AscIfPrivate is a sorting function to sort IfAddrs by "private" values before
  137. // "public" values. Both IPv4 and IPv6 are compared against RFC6890 (RFC6890
  138. // includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and IPv6
  139. // includes RFC4193).
  140. func AscIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
  141. return AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  142. }
  143. // AscIfType is a sorting function to sort IfAddrs by their respective address
  144. // type. Non-equal types are deferred in the sort.
  145. func AscIfType(p1Ptr, p2Ptr *IfAddr) int {
  146. return AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  147. }
  148. // DescIfAddress is identical to AscIfAddress but reverse ordered.
  149. func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int {
  150. return -1 * AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  151. }
  152. // DescIfDefault is identical to AscIfDefault but reverse ordered.
  153. func DescIfDefault(p1Ptr, p2Ptr *IfAddr) int {
  154. return -1 * AscIfDefault(p1Ptr, p2Ptr)
  155. }
  156. // DescIfName is identical to AscIfName but reverse ordered.
  157. func DescIfName(p1Ptr, p2Ptr *IfAddr) int {
  158. return -1 * strings.Compare(p1Ptr.Name, p2Ptr.Name)
  159. }
  160. // DescIfNetworkSize is identical to AscIfNetworkSize but reverse ordered.
  161. func DescIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
  162. return -1 * AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  163. }
  164. // DescIfPort is identical to AscIfPort but reverse ordered.
  165. func DescIfPort(p1Ptr, p2Ptr *IfAddr) int {
  166. return -1 * AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  167. }
  168. // DescIfPrivate is identical to AscIfPrivate but reverse ordered.
  169. func DescIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
  170. return -1 * AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  171. }
  172. // DescIfType is identical to AscIfType but reverse ordered.
  173. func DescIfType(p1Ptr, p2Ptr *IfAddr) int {
  174. return -1 * AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
  175. }
  176. // FilterIfByType filters IfAddrs and returns a list of the matching type
  177. func FilterIfByType(ifAddrs IfAddrs, type_ SockAddrType) (matchedIfs, excludedIfs IfAddrs) {
  178. excludedIfs = make(IfAddrs, 0, len(ifAddrs))
  179. matchedIfs = make(IfAddrs, 0, len(ifAddrs))
  180. for _, ifAddr := range ifAddrs {
  181. if ifAddr.SockAddr.Type()&type_ != 0 {
  182. matchedIfs = append(matchedIfs, ifAddr)
  183. } else {
  184. excludedIfs = append(excludedIfs, ifAddr)
  185. }
  186. }
  187. return matchedIfs, excludedIfs
  188. }
  189. // IfAttr forwards the selector to IfAttr.Attr() for resolution. If there is
  190. // more than one IfAddr, only the first IfAddr is used.
  191. func IfAttr(selectorName string, ifAddr IfAddr) (string, error) {
  192. attrName := AttrName(strings.ToLower(selectorName))
  193. attrVal, err := ifAddr.Attr(attrName)
  194. return attrVal, err
  195. }
  196. // IfAttrs forwards the selector to IfAttrs.Attr() for resolution. If there is
  197. // more than one IfAddr, only the first IfAddr is used.
  198. func IfAttrs(selectorName string, ifAddrs IfAddrs) (string, error) {
  199. if len(ifAddrs) == 0 {
  200. return "", nil
  201. }
  202. attrName := AttrName(strings.ToLower(selectorName))
  203. attrVal, err := ifAddrs[0].Attr(attrName)
  204. return attrVal, err
  205. }
  206. // GetAllInterfaces iterates over all available network interfaces and finds all
  207. // available IP addresses on each interface and converts them to
  208. // sockaddr.IPAddrs, and returning the result as an array of IfAddr.
  209. func GetAllInterfaces() (IfAddrs, error) {
  210. ifs, err := net.Interfaces()
  211. if err != nil {
  212. return nil, err
  213. }
  214. ifAddrs := make(IfAddrs, 0, len(ifs))
  215. for _, intf := range ifs {
  216. addrs, err := intf.Addrs()
  217. if err != nil {
  218. return nil, err
  219. }
  220. for _, addr := range addrs {
  221. var ipAddr IPAddr
  222. ipAddr, err = NewIPAddr(addr.String())
  223. if err != nil {
  224. return IfAddrs{}, fmt.Errorf("unable to create an IP address from %q", addr.String())
  225. }
  226. ifAddr := IfAddr{
  227. SockAddr: ipAddr,
  228. Interface: intf,
  229. }
  230. ifAddrs = append(ifAddrs, ifAddr)
  231. }
  232. }
  233. return ifAddrs, nil
  234. }
  235. // GetDefaultInterfaces returns IfAddrs of the addresses attached to the default
  236. // route.
  237. func GetDefaultInterfaces() (IfAddrs, error) {
  238. ri, err := NewRouteInfo()
  239. if err != nil {
  240. return nil, err
  241. }
  242. defaultIfName, err := ri.GetDefaultInterfaceName()
  243. if err != nil {
  244. return nil, err
  245. }
  246. var defaultIfs, ifAddrs IfAddrs
  247. ifAddrs, err = GetAllInterfaces()
  248. for _, ifAddr := range ifAddrs {
  249. if ifAddr.Name == defaultIfName {
  250. defaultIfs = append(defaultIfs, ifAddr)
  251. }
  252. }
  253. return defaultIfs, nil
  254. }
  255. // GetPrivateInterfaces returns an IfAddrs that are part of RFC 6890 and have a
  256. // default route. If the system can't determine its IP address or find an RFC
  257. // 6890 IP address, an empty IfAddrs will be returned instead. This function is
  258. // the `eval` equivalent of:
  259. //
  260. // ```
  261. // $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | include "RFC" "6890" }}'
  262. /// ```
  263. func GetPrivateInterfaces() (IfAddrs, error) {
  264. privateIfs, err := GetAllInterfaces()
  265. if err != nil {
  266. return IfAddrs{}, err
  267. }
  268. if len(privateIfs) == 0 {
  269. return IfAddrs{}, nil
  270. }
  271. privateIfs, _ = FilterIfByType(privateIfs, TypeIP)
  272. if len(privateIfs) == 0 {
  273. return IfAddrs{}, nil
  274. }
  275. privateIfs, _, err = IfByFlag("forwardable", privateIfs)
  276. if err != nil {
  277. return IfAddrs{}, err
  278. }
  279. privateIfs, _, err = IfByFlag("up", privateIfs)
  280. if err != nil {
  281. return IfAddrs{}, err
  282. }
  283. if len(privateIfs) == 0 {
  284. return IfAddrs{}, nil
  285. }
  286. OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(privateIfs)
  287. privateIfs, _, err = IfByRFC("6890", privateIfs)
  288. if err != nil {
  289. return IfAddrs{}, err
  290. } else if len(privateIfs) == 0 {
  291. return IfAddrs{}, nil
  292. }
  293. return privateIfs, nil
  294. }
  295. // GetPublicInterfaces returns an IfAddrs that are NOT part of RFC 6890 and has a
  296. // default route. If the system can't determine its IP address or find a non
  297. // RFC 6890 IP address, an empty IfAddrs will be returned instead. This
  298. // function is the `eval` equivalent of:
  299. //
  300. // ```
  301. // $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | exclude "RFC" "6890" }}'
  302. /// ```
  303. func GetPublicInterfaces() (IfAddrs, error) {
  304. publicIfs, err := GetAllInterfaces()
  305. if err != nil {
  306. return IfAddrs{}, err
  307. }
  308. if len(publicIfs) == 0 {
  309. return IfAddrs{}, nil
  310. }
  311. publicIfs, _ = FilterIfByType(publicIfs, TypeIP)
  312. if len(publicIfs) == 0 {
  313. return IfAddrs{}, nil
  314. }
  315. publicIfs, _, err = IfByFlag("forwardable", publicIfs)
  316. if err != nil {
  317. return IfAddrs{}, err
  318. }
  319. publicIfs, _, err = IfByFlag("up", publicIfs)
  320. if err != nil {
  321. return IfAddrs{}, err
  322. }
  323. if len(publicIfs) == 0 {
  324. return IfAddrs{}, nil
  325. }
  326. OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(publicIfs)
  327. _, publicIfs, err = IfByRFC("6890", publicIfs)
  328. if err != nil {
  329. return IfAddrs{}, err
  330. } else if len(publicIfs) == 0 {
  331. return IfAddrs{}, nil
  332. }
  333. return publicIfs, nil
  334. }
  335. // IfByAddress returns a list of matched and non-matched IfAddrs, or an error if
  336. // the regexp fails to compile.
  337. func IfByAddress(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  338. re, err := regexp.Compile(inputRe)
  339. if err != nil {
  340. return nil, nil, fmt.Errorf("Unable to compile address regexp %+q: %v", inputRe, err)
  341. }
  342. matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
  343. excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
  344. for _, addr := range ifAddrs {
  345. if re.MatchString(addr.SockAddr.String()) {
  346. matchedAddrs = append(matchedAddrs, addr)
  347. } else {
  348. excludedAddrs = append(excludedAddrs, addr)
  349. }
  350. }
  351. return matchedAddrs, excludedAddrs, nil
  352. }
  353. // IfByName returns a list of matched and non-matched IfAddrs, or an error if
  354. // the regexp fails to compile.
  355. func IfByName(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  356. re, err := regexp.Compile(inputRe)
  357. if err != nil {
  358. return nil, nil, fmt.Errorf("Unable to compile name regexp %+q: %v", inputRe, err)
  359. }
  360. matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
  361. excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
  362. for _, addr := range ifAddrs {
  363. if re.MatchString(addr.Name) {
  364. matchedAddrs = append(matchedAddrs, addr)
  365. } else {
  366. excludedAddrs = append(excludedAddrs, addr)
  367. }
  368. }
  369. return matchedAddrs, excludedAddrs, nil
  370. }
  371. // IfByPort returns a list of matched and non-matched IfAddrs, or an error if
  372. // the regexp fails to compile.
  373. func IfByPort(inputRe string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) {
  374. re, err := regexp.Compile(inputRe)
  375. if err != nil {
  376. return nil, nil, fmt.Errorf("Unable to compile port regexp %+q: %v", inputRe, err)
  377. }
  378. ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP)
  379. matchedIfs = make(IfAddrs, 0, len(ipIfs))
  380. excludedIfs = append(IfAddrs(nil), nonIfs...)
  381. for _, addr := range ipIfs {
  382. ipAddr := ToIPAddr(addr.SockAddr)
  383. if ipAddr == nil {
  384. continue
  385. }
  386. port := strconv.FormatInt(int64((*ipAddr).IPPort()), 10)
  387. if re.MatchString(port) {
  388. matchedIfs = append(matchedIfs, addr)
  389. } else {
  390. excludedIfs = append(excludedIfs, addr)
  391. }
  392. }
  393. return matchedIfs, excludedIfs, nil
  394. }
  395. // IfByRFC returns a list of matched and non-matched IfAddrs that contain the
  396. // relevant RFC-specified traits.
  397. func IfByRFC(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  398. inputRFC, err := strconv.ParseUint(selectorParam, 10, 64)
  399. if err != nil {
  400. return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to parse RFC number %q: %v", selectorParam, err)
  401. }
  402. matchedIfAddrs := make(IfAddrs, 0, len(ifAddrs))
  403. remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
  404. rfcNetMap := KnownRFCs()
  405. rfcNets, ok := rfcNetMap[uint(inputRFC)]
  406. if !ok {
  407. return nil, nil, fmt.Errorf("unsupported RFC %d", inputRFC)
  408. }
  409. for _, ifAddr := range ifAddrs {
  410. var contained bool
  411. for _, rfcNet := range rfcNets {
  412. if rfcNet.Contains(ifAddr.SockAddr) {
  413. matchedIfAddrs = append(matchedIfAddrs, ifAddr)
  414. contained = true
  415. break
  416. }
  417. }
  418. if !contained {
  419. remainingIfAddrs = append(remainingIfAddrs, ifAddr)
  420. }
  421. }
  422. return matchedIfAddrs, remainingIfAddrs, nil
  423. }
  424. // IfByRFCs returns a list of matched and non-matched IfAddrs that contain the
  425. // relevant RFC-specified traits. Multiple RFCs can be specified and separated
  426. // by the `|` symbol. No protection is taken to ensure an IfAddr does not end
  427. // up in both the included and excluded list.
  428. func IfByRFCs(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  429. var includedIfs, excludedIfs IfAddrs
  430. for _, rfcStr := range strings.Split(selectorParam, "|") {
  431. includedRFCIfs, excludedRFCIfs, err := IfByRFC(rfcStr, ifAddrs)
  432. if err != nil {
  433. return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to lookup RFC number %q: %v", rfcStr, err)
  434. }
  435. includedIfs = append(includedIfs, includedRFCIfs...)
  436. excludedIfs = append(excludedIfs, excludedRFCIfs...)
  437. }
  438. return includedIfs, excludedIfs, nil
  439. }
  440. // IfByMaskSize returns a list of matched and non-matched IfAddrs that have the
  441. // matching mask size.
  442. func IfByMaskSize(selectorParam string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) {
  443. maskSize, err := strconv.ParseUint(selectorParam, 10, 64)
  444. if err != nil {
  445. return IfAddrs{}, IfAddrs{}, fmt.Errorf("invalid exclude size argument (%q): %v", selectorParam, err)
  446. }
  447. ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP)
  448. matchedIfs = make(IfAddrs, 0, len(ipIfs))
  449. excludedIfs = append(IfAddrs(nil), nonIfs...)
  450. for _, addr := range ipIfs {
  451. ipAddr := ToIPAddr(addr.SockAddr)
  452. if ipAddr == nil {
  453. return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to filter mask sizes on non-IP type %s: %v", addr.SockAddr.Type().String(), addr.SockAddr.String())
  454. }
  455. switch {
  456. case (*ipAddr).Type()&TypeIPv4 != 0 && maskSize > 32:
  457. return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv4 address: %d", maskSize)
  458. case (*ipAddr).Type()&TypeIPv6 != 0 && maskSize > 128:
  459. return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv6 address: %d", maskSize)
  460. }
  461. if (*ipAddr).Maskbits() == int(maskSize) {
  462. matchedIfs = append(matchedIfs, addr)
  463. } else {
  464. excludedIfs = append(excludedIfs, addr)
  465. }
  466. }
  467. return matchedIfs, excludedIfs, nil
  468. }
  469. // IfByType returns a list of matching and non-matching IfAddr that match the
  470. // specified type. For instance:
  471. //
  472. // include "type" "IPv4,IPv6"
  473. //
  474. // will include any IfAddrs that is either an IPv4 or IPv6 address. Any
  475. // addresses on those interfaces that don't match will be included in the
  476. // remainder results.
  477. func IfByType(inputTypes string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  478. matchingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
  479. remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
  480. ifTypes := strings.Split(strings.ToLower(inputTypes), "|")
  481. for _, ifType := range ifTypes {
  482. switch ifType {
  483. case "ip", "ipv4", "ipv6", "unix":
  484. // Valid types
  485. default:
  486. return nil, nil, fmt.Errorf("unsupported type %q %q", ifType, inputTypes)
  487. }
  488. }
  489. for _, ifAddr := range ifAddrs {
  490. for _, ifType := range ifTypes {
  491. var matched bool
  492. switch {
  493. case ifType == "ip" && ifAddr.SockAddr.Type()&TypeIP != 0:
  494. matched = true
  495. case ifType == "ipv4" && ifAddr.SockAddr.Type()&TypeIPv4 != 0:
  496. matched = true
  497. case ifType == "ipv6" && ifAddr.SockAddr.Type()&TypeIPv6 != 0:
  498. matched = true
  499. case ifType == "unix" && ifAddr.SockAddr.Type()&TypeUnix != 0:
  500. matched = true
  501. }
  502. if matched {
  503. matchingIfAddrs = append(matchingIfAddrs, ifAddr)
  504. } else {
  505. remainingIfAddrs = append(remainingIfAddrs, ifAddr)
  506. }
  507. }
  508. }
  509. return matchingIfAddrs, remainingIfAddrs, nil
  510. }
  511. // IfByFlag returns a list of matching and non-matching IfAddrs that match the
  512. // specified type. For instance:
  513. //
  514. // include "flag" "up,broadcast"
  515. //
  516. // will include any IfAddrs that have both the "up" and "broadcast" flags set.
  517. // Any addresses on those interfaces that don't match will be omitted from the
  518. // results.
  519. func IfByFlag(inputFlags string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
  520. matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
  521. excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
  522. var wantForwardable,
  523. wantGlobalUnicast,
  524. wantInterfaceLocalMulticast,
  525. wantLinkLocalMulticast,
  526. wantLinkLocalUnicast,
  527. wantLoopback,
  528. wantMulticast,
  529. wantUnspecified bool
  530. var ifFlags net.Flags
  531. var checkFlags, checkAttrs bool
  532. for _, flagName := range strings.Split(strings.ToLower(inputFlags), "|") {
  533. switch flagName {
  534. case "broadcast":
  535. checkFlags = true
  536. ifFlags = ifFlags | net.FlagBroadcast
  537. case "down":
  538. checkFlags = true
  539. ifFlags = (ifFlags &^ net.FlagUp)
  540. case "forwardable":
  541. checkAttrs = true
  542. wantForwardable = true
  543. case "global unicast":
  544. checkAttrs = true
  545. wantGlobalUnicast = true
  546. case "interface-local multicast":
  547. checkAttrs = true
  548. wantInterfaceLocalMulticast = true
  549. case "link-local multicast":
  550. checkAttrs = true
  551. wantLinkLocalMulticast = true
  552. case "link-local unicast":
  553. checkAttrs = true
  554. wantLinkLocalUnicast = true
  555. case "loopback":
  556. checkAttrs = true
  557. checkFlags = true
  558. ifFlags = ifFlags | net.FlagLoopback
  559. wantLoopback = true
  560. case "multicast":
  561. checkAttrs = true
  562. checkFlags = true
  563. ifFlags = ifFlags | net.FlagMulticast
  564. wantMulticast = true
  565. case "point-to-point":
  566. checkFlags = true
  567. ifFlags = ifFlags | net.FlagPointToPoint
  568. case "unspecified":
  569. checkAttrs = true
  570. wantUnspecified = true
  571. case "up":
  572. checkFlags = true
  573. ifFlags = ifFlags | net.FlagUp
  574. default:
  575. return nil, nil, fmt.Errorf("Unknown interface flag: %+q", flagName)
  576. }
  577. }
  578. for _, ifAddr := range ifAddrs {
  579. var matched bool
  580. if checkFlags && ifAddr.Interface.Flags&ifFlags == ifFlags {
  581. matched = true
  582. }
  583. if checkAttrs {
  584. if ip := ToIPAddr(ifAddr.SockAddr); ip != nil {
  585. netIP := (*ip).NetIP()
  586. switch {
  587. case wantGlobalUnicast && netIP.IsGlobalUnicast():
  588. matched = true
  589. case wantInterfaceLocalMulticast && netIP.IsInterfaceLocalMulticast():
  590. matched = true
  591. case wantLinkLocalMulticast && netIP.IsLinkLocalMulticast():
  592. matched = true
  593. case wantLinkLocalUnicast && netIP.IsLinkLocalUnicast():
  594. matched = true
  595. case wantLoopback && netIP.IsLoopback():
  596. matched = true
  597. case wantMulticast && netIP.IsMulticast():
  598. matched = true
  599. case wantUnspecified && netIP.IsUnspecified():
  600. matched = true
  601. case wantForwardable && !IsRFC(ForwardingBlacklist, ifAddr.SockAddr):
  602. matched = true
  603. }
  604. }
  605. }
  606. if matched {
  607. matchedAddrs = append(matchedAddrs, ifAddr)
  608. } else {
  609. excludedAddrs = append(excludedAddrs, ifAddr)
  610. }
  611. }
  612. return matchedAddrs, excludedAddrs, nil
  613. }
  614. // IfByNetwork returns an IfAddrs that are equal to or included within the
  615. // network passed in by selector.
  616. func IfByNetwork(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, IfAddrs, error) {
  617. var includedIfs, excludedIfs IfAddrs
  618. for _, netStr := range strings.Split(selectorParam, "|") {
  619. netAddr, err := NewIPAddr(netStr)
  620. if err != nil {
  621. return nil, nil, fmt.Errorf("unable to create an IP address from %+q: %v", netStr, err)
  622. }
  623. for _, ifAddr := range inputIfAddrs {
  624. if netAddr.Contains(ifAddr.SockAddr) {
  625. includedIfs = append(includedIfs, ifAddr)
  626. } else {
  627. excludedIfs = append(excludedIfs, ifAddr)
  628. }
  629. }
  630. }
  631. return includedIfs, excludedIfs, nil
  632. }
  633. // IfAddrMath will return a new IfAddr struct with a mutated value.
  634. func IfAddrMath(operation, value string, inputIfAddr IfAddr) (IfAddr, error) {
  635. // Regexp used to enforce the sign being a required part of the grammar for
  636. // some values.
  637. signRe := signRE.Copy()
  638. switch strings.ToLower(operation) {
  639. case "address":
  640. // "address" operates on the IP address and is allowed to overflow or
  641. // underflow networks, however it will wrap along the underlying address's
  642. // underlying type.
  643. if !signRe.MatchString(value) {
  644. return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation)
  645. }
  646. switch sockType := inputIfAddr.SockAddr.Type(); sockType {
  647. case TypeIPv4:
  648. // 33 == Accept any uint32 value
  649. // TODO(seanc@): Add the ability to parse hex
  650. i, err := strconv.ParseInt(value, 10, 33)
  651. if err != nil {
  652. return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
  653. }
  654. ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
  655. ipv4Uint32 := uint32(ipv4.Address)
  656. ipv4Uint32 += uint32(i)
  657. return IfAddr{
  658. SockAddr: IPv4Addr{
  659. Address: IPv4Address(ipv4Uint32),
  660. Mask: ipv4.Mask,
  661. },
  662. Interface: inputIfAddr.Interface,
  663. }, nil
  664. case TypeIPv6:
  665. // 64 == Accept any int32 value
  666. // TODO(seanc@): Add the ability to parse hex. Also parse a bignum int.
  667. i, err := strconv.ParseInt(value, 10, 64)
  668. if err != nil {
  669. return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
  670. }
  671. ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
  672. ipv6BigIntA := new(big.Int)
  673. ipv6BigIntA.Set(ipv6.Address)
  674. ipv6BigIntB := big.NewInt(i)
  675. ipv6Addr := ipv6BigIntA.Add(ipv6BigIntA, ipv6BigIntB)
  676. ipv6Addr.And(ipv6Addr, ipv6HostMask)
  677. return IfAddr{
  678. SockAddr: IPv6Addr{
  679. Address: IPv6Address(ipv6Addr),
  680. Mask: ipv6.Mask,
  681. },
  682. Interface: inputIfAddr.Interface,
  683. }, nil
  684. default:
  685. return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
  686. }
  687. case "network":
  688. // "network" operates on the network address. Positive values start at the
  689. // network address and negative values wrap at the network address, which
  690. // means a "-1" value on a network will be the broadcast address after
  691. // wrapping is applied.
  692. if !signRe.MatchString(value) {
  693. return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation)
  694. }
  695. switch sockType := inputIfAddr.SockAddr.Type(); sockType {
  696. case TypeIPv4:
  697. // 33 == Accept any uint32 value
  698. // TODO(seanc@): Add the ability to parse hex
  699. i, err := strconv.ParseInt(value, 10, 33)
  700. if err != nil {
  701. return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
  702. }
  703. ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
  704. ipv4Uint32 := uint32(ipv4.NetworkAddress())
  705. // Wrap along network mask boundaries. EZ-mode wrapping made possible by
  706. // use of int64 vs a uint.
  707. var wrappedMask int64
  708. if i >= 0 {
  709. wrappedMask = i
  710. } else {
  711. wrappedMask = 1 + i + int64(^uint32(ipv4.Mask))
  712. }
  713. ipv4Uint32 = ipv4Uint32 + (uint32(wrappedMask) &^ uint32(ipv4.Mask))
  714. return IfAddr{
  715. SockAddr: IPv4Addr{
  716. Address: IPv4Address(ipv4Uint32),
  717. Mask: ipv4.Mask,
  718. },
  719. Interface: inputIfAddr.Interface,
  720. }, nil
  721. case TypeIPv6:
  722. // 64 == Accept any int32 value
  723. // TODO(seanc@): Add the ability to parse hex. Also parse a bignum int.
  724. i, err := strconv.ParseInt(value, 10, 64)
  725. if err != nil {
  726. return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
  727. }
  728. ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
  729. ipv6BigInt := new(big.Int)
  730. ipv6BigInt.Set(ipv6.NetworkAddress())
  731. mask := new(big.Int)
  732. mask.Set(ipv6.Mask)
  733. if i > 0 {
  734. wrappedMask := new(big.Int)
  735. wrappedMask.SetInt64(i)
  736. wrappedMask.AndNot(wrappedMask, mask)
  737. ipv6BigInt.Add(ipv6BigInt, wrappedMask)
  738. } else {
  739. // Mask off any bits that exceed the network size. Subtract the
  740. // wrappedMask from the last usable - 1
  741. wrappedMask := new(big.Int)
  742. wrappedMask.SetInt64(-1 * i)
  743. wrappedMask.Sub(wrappedMask, big.NewInt(1))
  744. wrappedMask.AndNot(wrappedMask, mask)
  745. lastUsable := new(big.Int)
  746. lastUsable.Set(ipv6.LastUsable().(IPv6Addr).Address)
  747. ipv6BigInt = lastUsable.Sub(lastUsable, wrappedMask)
  748. }
  749. return IfAddr{
  750. SockAddr: IPv6Addr{
  751. Address: IPv6Address(ipv6BigInt),
  752. Mask: ipv6.Mask,
  753. },
  754. Interface: inputIfAddr.Interface,
  755. }, nil
  756. default:
  757. return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
  758. }
  759. case "mask":
  760. // "mask" operates on the IP address and returns the IP address on
  761. // which the given integer mask has been applied. If the applied mask
  762. // corresponds to a larger network than the mask of the IP address,
  763. // the latter will be replaced by the former.
  764. switch sockType := inputIfAddr.SockAddr.Type(); sockType {
  765. case TypeIPv4:
  766. i, err := strconv.ParseUint(value, 10, 32)
  767. if err != nil {
  768. return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
  769. }
  770. if i > 32 {
  771. return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv4 addresses must be between 0 and 32", operation)
  772. }
  773. ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
  774. ipv4Mask := net.CIDRMask(int(i), 32)
  775. ipv4MaskUint32 := binary.BigEndian.Uint32(ipv4Mask)
  776. maskedIpv4 := ipv4.NetIP().Mask(ipv4Mask)
  777. maskedIpv4Uint32 := binary.BigEndian.Uint32(maskedIpv4)
  778. maskedIpv4MaskUint32 := uint32(ipv4.Mask)
  779. if ipv4MaskUint32 < maskedIpv4MaskUint32 {
  780. maskedIpv4MaskUint32 = ipv4MaskUint32
  781. }
  782. return IfAddr{
  783. SockAddr: IPv4Addr{
  784. Address: IPv4Address(maskedIpv4Uint32),
  785. Mask: IPv4Mask(maskedIpv4MaskUint32),
  786. },
  787. Interface: inputIfAddr.Interface,
  788. }, nil
  789. case TypeIPv6:
  790. i, err := strconv.ParseUint(value, 10, 32)
  791. if err != nil {
  792. return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
  793. }
  794. if i > 128 {
  795. return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv6 addresses must be between 0 and 64", operation)
  796. }
  797. ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
  798. ipv6Mask := net.CIDRMask(int(i), 128)
  799. ipv6MaskBigInt := new(big.Int)
  800. ipv6MaskBigInt.SetBytes(ipv6Mask)
  801. maskedIpv6 := ipv6.NetIP().Mask(ipv6Mask)
  802. maskedIpv6BigInt := new(big.Int)
  803. maskedIpv6BigInt.SetBytes(maskedIpv6)
  804. maskedIpv6MaskBigInt := new(big.Int)
  805. maskedIpv6MaskBigInt.Set(ipv6.Mask)
  806. if ipv6MaskBigInt.Cmp(maskedIpv6MaskBigInt) == -1 {
  807. maskedIpv6MaskBigInt = ipv6MaskBigInt
  808. }
  809. return IfAddr{
  810. SockAddr: IPv6Addr{
  811. Address: IPv6Address(maskedIpv6BigInt),
  812. Mask: IPv6Mask(maskedIpv6MaskBigInt),
  813. },
  814. Interface: inputIfAddr.Interface,
  815. }, nil
  816. default:
  817. return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
  818. }
  819. default:
  820. return IfAddr{}, fmt.Errorf("unsupported math operation: %q", operation)
  821. }
  822. }
  823. // IfAddrsMath will apply an IfAddrMath operation each IfAddr struct. Any
  824. // failure will result in zero results.
  825. func IfAddrsMath(operation, value string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  826. outputAddrs := make(IfAddrs, 0, len(inputIfAddrs))
  827. for _, ifAddr := range inputIfAddrs {
  828. result, err := IfAddrMath(operation, value, ifAddr)
  829. if err != nil {
  830. return IfAddrs{}, fmt.Errorf("unable to perform an IPMath operation on %s: %v", ifAddr, err)
  831. }
  832. outputAddrs = append(outputAddrs, result)
  833. }
  834. return outputAddrs, nil
  835. }
  836. // IncludeIfs returns an IfAddrs based on the passed in selector.
  837. func IncludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  838. var includedIfs IfAddrs
  839. var err error
  840. switch strings.ToLower(selectorName) {
  841. case "address":
  842. includedIfs, _, err = IfByAddress(selectorParam, inputIfAddrs)
  843. case "flag", "flags":
  844. includedIfs, _, err = IfByFlag(selectorParam, inputIfAddrs)
  845. case "name":
  846. includedIfs, _, err = IfByName(selectorParam, inputIfAddrs)
  847. case "network":
  848. includedIfs, _, err = IfByNetwork(selectorParam, inputIfAddrs)
  849. case "port":
  850. includedIfs, _, err = IfByPort(selectorParam, inputIfAddrs)
  851. case "rfc", "rfcs":
  852. includedIfs, _, err = IfByRFCs(selectorParam, inputIfAddrs)
  853. case "size":
  854. includedIfs, _, err = IfByMaskSize(selectorParam, inputIfAddrs)
  855. case "type":
  856. includedIfs, _, err = IfByType(selectorParam, inputIfAddrs)
  857. default:
  858. return IfAddrs{}, fmt.Errorf("invalid include selector %q", selectorName)
  859. }
  860. if err != nil {
  861. return IfAddrs{}, err
  862. }
  863. return includedIfs, nil
  864. }
  865. // ExcludeIfs returns an IfAddrs based on the passed in selector.
  866. func ExcludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  867. var excludedIfs IfAddrs
  868. var err error
  869. switch strings.ToLower(selectorName) {
  870. case "address":
  871. _, excludedIfs, err = IfByAddress(selectorParam, inputIfAddrs)
  872. case "flag", "flags":
  873. _, excludedIfs, err = IfByFlag(selectorParam, inputIfAddrs)
  874. case "name":
  875. _, excludedIfs, err = IfByName(selectorParam, inputIfAddrs)
  876. case "network":
  877. _, excludedIfs, err = IfByNetwork(selectorParam, inputIfAddrs)
  878. case "port":
  879. _, excludedIfs, err = IfByPort(selectorParam, inputIfAddrs)
  880. case "rfc", "rfcs":
  881. _, excludedIfs, err = IfByRFCs(selectorParam, inputIfAddrs)
  882. case "size":
  883. _, excludedIfs, err = IfByMaskSize(selectorParam, inputIfAddrs)
  884. case "type":
  885. _, excludedIfs, err = IfByType(selectorParam, inputIfAddrs)
  886. default:
  887. return IfAddrs{}, fmt.Errorf("invalid exclude selector %q", selectorName)
  888. }
  889. if err != nil {
  890. return IfAddrs{}, err
  891. }
  892. return excludedIfs, nil
  893. }
  894. // SortIfBy returns an IfAddrs sorted based on the passed in selector. Multiple
  895. // sort clauses can be passed in as a comma delimited list without whitespace.
  896. func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  897. sortedIfs := append(IfAddrs(nil), inputIfAddrs...)
  898. clauses := strings.Split(selectorParam, ",")
  899. sortFuncs := make([]CmpIfAddrFunc, len(clauses))
  900. for i, clause := range clauses {
  901. switch strings.TrimSpace(strings.ToLower(clause)) {
  902. case "+address", "address":
  903. // The "address" selector returns an array of IfAddrs
  904. // ordered by the network address. IfAddrs that are not
  905. // comparable will be at the end of the list and in a
  906. // non-deterministic order.
  907. sortFuncs[i] = AscIfAddress
  908. case "-address":
  909. sortFuncs[i] = DescIfAddress
  910. case "+default", "default":
  911. sortFuncs[i] = AscIfDefault
  912. case "-default":
  913. sortFuncs[i] = DescIfDefault
  914. case "+name", "name":
  915. // The "name" selector returns an array of IfAddrs
  916. // ordered by the interface name.
  917. sortFuncs[i] = AscIfName
  918. case "-name":
  919. sortFuncs[i] = DescIfName
  920. case "+port", "port":
  921. // The "port" selector returns an array of IfAddrs
  922. // ordered by the port, if included in the IfAddr.
  923. // IfAddrs that are not comparable will be at the end of
  924. // the list and in a non-deterministic order.
  925. sortFuncs[i] = AscIfPort
  926. case "-port":
  927. sortFuncs[i] = DescIfPort
  928. case "+private", "private":
  929. // The "private" selector returns an array of IfAddrs
  930. // ordered by private addresses first. IfAddrs that are
  931. // not comparable will be at the end of the list and in
  932. // a non-deterministic order.
  933. sortFuncs[i] = AscIfPrivate
  934. case "-private":
  935. sortFuncs[i] = DescIfPrivate
  936. case "+size", "size":
  937. // The "size" selector returns an array of IfAddrs
  938. // ordered by the size of the network mask, smaller mask
  939. // (larger number of hosts per network) to largest
  940. // (e.g. a /24 sorts before a /32).
  941. sortFuncs[i] = AscIfNetworkSize
  942. case "-size":
  943. sortFuncs[i] = DescIfNetworkSize
  944. case "+type", "type":
  945. // The "type" selector returns an array of IfAddrs
  946. // ordered by the type of the IfAddr. The sort order is
  947. // Unix, IPv4, then IPv6.
  948. sortFuncs[i] = AscIfType
  949. case "-type":
  950. sortFuncs[i] = DescIfType
  951. default:
  952. // Return an empty list for invalid sort types.
  953. return IfAddrs{}, fmt.Errorf("unknown sort type: %q", clause)
  954. }
  955. }
  956. OrderedIfAddrBy(sortFuncs...).Sort(sortedIfs)
  957. return sortedIfs, nil
  958. }
  959. // UniqueIfAddrsBy creates a unique set of IfAddrs based on the matching
  960. // selector. UniqueIfAddrsBy assumes the input has already been sorted.
  961. func UniqueIfAddrsBy(selectorName string, inputIfAddrs IfAddrs) (IfAddrs, error) {
  962. attrName := strings.ToLower(selectorName)
  963. ifs := make(IfAddrs, 0, len(inputIfAddrs))
  964. var lastMatch string
  965. for _, ifAddr := range inputIfAddrs {
  966. var out string
  967. switch attrName {
  968. case "address":
  969. out = ifAddr.SockAddr.String()
  970. case "name":
  971. out = ifAddr.Name
  972. default:
  973. return nil, fmt.Errorf("unsupported unique constraint %+q", selectorName)
  974. }
  975. switch {
  976. case lastMatch == "", lastMatch != out:
  977. lastMatch = out
  978. ifs = append(ifs, ifAddr)
  979. case lastMatch == out:
  980. continue
  981. }
  982. }
  983. return ifs, nil
  984. }
  985. // JoinIfAddrs joins an IfAddrs and returns a string
  986. func JoinIfAddrs(selectorName string, joinStr string, inputIfAddrs IfAddrs) (string, error) {
  987. outputs := make([]string, 0, len(inputIfAddrs))
  988. attrName := AttrName(strings.ToLower(selectorName))
  989. for _, ifAddr := range inputIfAddrs {
  990. var attrVal string
  991. var err error
  992. attrVal, err = ifAddr.Attr(attrName)
  993. if err != nil {
  994. return "", err
  995. }
  996. outputs = append(outputs, attrVal)
  997. }
  998. return strings.Join(outputs, joinStr), nil
  999. }
  1000. // LimitIfAddrs returns a slice of IfAddrs based on the specified limit.
  1001. func LimitIfAddrs(lim uint, in IfAddrs) (IfAddrs, error) {
  1002. // Clamp the limit to the length of the array
  1003. if int(lim) > len(in) {
  1004. lim = uint(len(in))
  1005. }
  1006. return in[0:lim], nil
  1007. }
  1008. // OffsetIfAddrs returns a slice of IfAddrs based on the specified offset.
  1009. func OffsetIfAddrs(off int, in IfAddrs) (IfAddrs, error) {
  1010. var end bool
  1011. if off < 0 {
  1012. end = true
  1013. off = off * -1
  1014. }
  1015. if off > len(in) {
  1016. 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))
  1017. }
  1018. if end {
  1019. return in[len(in)-off:], nil
  1020. }
  1021. return in[off:], nil
  1022. }
  1023. func (ifAddr IfAddr) String() string {
  1024. return fmt.Sprintf("%s %v", ifAddr.SockAddr, ifAddr.Interface)
  1025. }
  1026. // parseDefaultIfNameFromRoute parses standard route(8)'s output for the *BSDs
  1027. // and Solaris.
  1028. func parseDefaultIfNameFromRoute(routeOut string) (string, error) {
  1029. lines := strings.Split(routeOut, "\n")
  1030. for _, line := range lines {
  1031. kvs := strings.SplitN(line, ":", 2)
  1032. if len(kvs) != 2 {
  1033. continue
  1034. }
  1035. if strings.TrimSpace(kvs[0]) == "interface" {
  1036. ifName := strings.TrimSpace(kvs[1])
  1037. return ifName, nil
  1038. }
  1039. }
  1040. return "", errors.New("No default interface found")
  1041. }
  1042. // parseDefaultIfNameFromIPCmd parses the default interface from ip(8) for
  1043. // Linux.
  1044. func parseDefaultIfNameFromIPCmd(routeOut string) (string, error) {
  1045. parsedLines := parseIfNameFromIPCmd(routeOut)
  1046. for _, parsedLine := range parsedLines {
  1047. if parsedLine[0] == "default" &&
  1048. parsedLine[1] == "via" &&
  1049. parsedLine[3] == "dev" {
  1050. ifName := strings.TrimSpace(parsedLine[4])
  1051. return ifName, nil
  1052. }
  1053. }
  1054. return "", errors.New("No default interface found")
  1055. }
  1056. // parseDefaultIfNameFromIPCmdAndroid parses the default interface from ip(8) for
  1057. // Android.
  1058. func parseDefaultIfNameFromIPCmdAndroid(routeOut string) (string, error) {
  1059. parsedLines := parseIfNameFromIPCmd(routeOut)
  1060. if (len(parsedLines) > 0) {
  1061. ifName := strings.TrimSpace(parsedLines[0][4])
  1062. return ifName, nil
  1063. }
  1064. return "", errors.New("No default interface found")
  1065. }
  1066. // parseIfNameFromIPCmd parses interfaces from ip(8) for
  1067. // Linux.
  1068. func parseIfNameFromIPCmd(routeOut string) [][]string {
  1069. lines := strings.Split(routeOut, "\n")
  1070. re := whitespaceRE.Copy()
  1071. parsedLines := make([][]string, 0, len(lines))
  1072. for _, line := range lines {
  1073. kvs := re.Split(line, -1)
  1074. if len(kvs) < 5 {
  1075. continue
  1076. }
  1077. parsedLines = append(parsedLines, kvs)
  1078. }
  1079. return parsedLines
  1080. }
  1081. // parseDefaultIfNameWindows parses the default interface from `netstat -rn` and
  1082. // `ipconfig` on Windows.
  1083. func parseDefaultIfNameWindows(routeOut, ipconfigOut string) (string, error) {
  1084. defaultIPAddr, err := parseDefaultIPAddrWindowsRoute(routeOut)
  1085. if err != nil {
  1086. return "", err
  1087. }
  1088. ifName, err := parseDefaultIfNameWindowsIPConfig(defaultIPAddr, ipconfigOut)
  1089. if err != nil {
  1090. return "", err
  1091. }
  1092. return ifName, nil
  1093. }
  1094. // parseDefaultIPAddrWindowsRoute parses the IP address on the default interface
  1095. // `netstat -rn`.
  1096. //
  1097. // NOTES(sean): Only IPv4 addresses are parsed at this time. If you have an
  1098. // IPv6 connected host, submit an issue on github.com/hashicorp/go-sockaddr with
  1099. // the output from `netstat -rn`, `ipconfig`, and version of Windows to see IPv6
  1100. // support added.
  1101. func parseDefaultIPAddrWindowsRoute(routeOut string) (string, error) {
  1102. lines := strings.Split(routeOut, "\n")
  1103. re := whitespaceRE.Copy()
  1104. for _, line := range lines {
  1105. kvs := re.Split(strings.TrimSpace(line), -1)
  1106. if len(kvs) < 3 {
  1107. continue
  1108. }
  1109. if kvs[0] == "0.0.0.0" && kvs[1] == "0.0.0.0" {
  1110. defaultIPAddr := strings.TrimSpace(kvs[3])
  1111. return defaultIPAddr, nil
  1112. }
  1113. }
  1114. return "", errors.New("No IP on default interface found")
  1115. }
  1116. // parseDefaultIfNameWindowsIPConfig parses the output of `ipconfig` to find the
  1117. // interface name forwarding traffic to the default gateway.
  1118. func parseDefaultIfNameWindowsIPConfig(defaultIPAddr, routeOut string) (string, error) {
  1119. lines := strings.Split(routeOut, "\n")
  1120. ifNameRe := ifNameRE.Copy()
  1121. ipAddrRe := ipAddrRE.Copy()
  1122. var ifName string
  1123. for _, line := range lines {
  1124. switch ifNameMatches := ifNameRe.FindStringSubmatch(line); {
  1125. case len(ifNameMatches) > 1:
  1126. ifName = ifNameMatches[1]
  1127. continue
  1128. }
  1129. switch ipAddrMatches := ipAddrRe.FindStringSubmatch(line); {
  1130. case len(ipAddrMatches) > 1 && ipAddrMatches[1] == defaultIPAddr:
  1131. return ifName, nil
  1132. }
  1133. }
  1134. return "", errors.New("No default interface found with matching IP")
  1135. }