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