github.com/haraldrudell/parl@v0.4.176/pnet/destination.go (about) 1 /* 2 © 2020–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package pnet 7 8 import ( 9 "net/netip" 10 "strconv" 11 "strings" 12 13 "github.com/haraldrudell/parl/perrors" 14 ) 15 16 // Destination represents a selector for routing, ie. an IPv4 or IPv6 address with zone 17 // and prefix. 18 // go1.18 introduced [netip.Prefix] for this purpose 19 // see Linux: ip route add. 20 // [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ] [ table TABLE_ID ] [ vrf NAME ] 21 // [ proto RTPROTO ] [ type TYPE ] [ scope SCOPE ] 22 // contains IP, Zone and Mask 23 type Destination struct { 24 netip.Prefix 25 } 26 27 // NewDestination instantiates Destination. 28 // addr is IPv4 address or IPv6 address with Zone. 29 // prefix is number of bits actually used 0…32 for IPv4, 0…128 for IPv6 30 func NewDestination(prefix netip.Prefix) (d *Destination) { 31 return &Destination{Prefix: prefix} 32 } 33 34 func (d Destination) IsValid() (err error) { 35 if !d.Prefix.IsValid() { 36 err = perrors.ErrorfPF("invalid prefix: %#v", d.Prefix) 37 return 38 } 39 return 40 } 41 42 // Key is a string suitable as a key in a map 43 func (d Destination) Key() (key netip.Prefix) { 44 return d.Prefix 45 } 46 47 // IsDefaultRoute returns whether Destination is a default route: 48 // - IPv4: 0/0 or 0.0.0.0/0 49 // - IPv6: :: 50 func (d Destination) IsDefaultRoute() (isDefault bool) { 51 var addr = d.Addr() 52 if !addr.IsValid() || d.Bits() != 0 { 53 return // address not valid or not /0 54 } 55 isDefault = addr.IsUnspecified() 56 57 return 58 } 59 60 // "1.2.3.4/24" or "2000::/3" 61 // - abbreviate IPv4: "127.0.0.0/8" → "127/8" 62 // - IPv4 default route: "0.0.0.0/0" → "0/0" 63 // - IPv6 default route stays "::/0" 64 func (d Destination) String() (s string) { 65 66 // abbreviate IPv4: 0.0.0.0/0 → 0/0 127.0.0.0/8 → 127/8 67 if d.Prefix.Addr().Is4() { 68 ipv4 := d.Prefix.Addr().String() 69 for strings.HasSuffix(ipv4, ".0") { 70 ipv4 = strings.TrimSuffix(ipv4, ".0") 71 } 72 return ipv4 + "/" + strconv.Itoa(d.Bits()) 73 } 74 return d.Prefix.String() 75 }