1package sockaddr 2 3import ( 4 "encoding/binary" 5 "fmt" 6 "net" 7 "regexp" 8 "strconv" 9 "strings" 10) 11 12type ( 13 // IPv4Address is a named type representing an IPv4 address. 14 IPv4Address uint32 15 16 // IPv4Network is a named type representing an IPv4 network. 17 IPv4Network uint32 18 19 // IPv4Mask is a named type representing an IPv4 network mask. 20 IPv4Mask uint32 21) 22 23// IPv4HostMask is a constant represents a /32 IPv4 Address 24// (i.e. 255.255.255.255). 25const IPv4HostMask = IPv4Mask(0xffffffff) 26 27// ipv4AddrAttrMap is a map of the IPv4Addr type-specific attributes. 28var ipv4AddrAttrMap map[AttrName]func(IPv4Addr) string 29var ipv4AddrAttrs []AttrName 30var trailingHexNetmaskRE *regexp.Regexp 31 32// IPv4Addr implements a convenience wrapper around the union of Go's 33// built-in net.IP and net.IPNet types. In UNIX-speak, IPv4Addr implements 34// `sockaddr` when the the address family is set to AF_INET 35// (i.e. `sockaddr_in`). 36type IPv4Addr struct { 37 IPAddr 38 Address IPv4Address 39 Mask IPv4Mask 40 Port IPPort 41} 42 43func init() { 44 ipv4AddrInit() 45 trailingHexNetmaskRE = regexp.MustCompile(`/([0f]{8})$`) 46} 47 48// NewIPv4Addr creates an IPv4Addr from a string. String can be in the form 49// of either an IPv4:port (e.g. `1.2.3.4:80`, in which case the mask is 50// assumed to be a `/32`), an IPv4 address (e.g. `1.2.3.4`, also with a `/32` 51// mask), or an IPv4 CIDR (e.g. `1.2.3.4/24`, which has its IP port 52// initialized to zero). ipv4Str can not be a hostname. 53// 54// NOTE: Many net.*() routines will initialize and return an IPv6 address. 55// To create uint32 values from net.IP, always test to make sure the address 56// returned can be converted to a 4 byte array using To4(). 57func NewIPv4Addr(ipv4Str string) (IPv4Addr, error) { 58 // Strip off any bogus hex-encoded netmasks that will be mis-parsed by Go. In 59 // particular, clients with the Barracuda VPN client will see something like: 60 // `192.168.3.51/00ffffff` as their IP address. 61 trailingHexNetmaskRe := trailingHexNetmaskRE.Copy() 62 if match := trailingHexNetmaskRe.FindStringIndex(ipv4Str); match != nil { 63 ipv4Str = ipv4Str[:match[0]] 64 } 65 66 // Parse as an IPv4 CIDR 67 ipAddr, network, err := net.ParseCIDR(ipv4Str) 68 if err == nil { 69 ipv4 := ipAddr.To4() 70 if ipv4 == nil { 71 return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address", ipv4Str) 72 } 73 74 // If we see an IPv6 netmask, convert it to an IPv4 mask. 75 netmaskSepPos := strings.LastIndexByte(ipv4Str, '/') 76 if netmaskSepPos != -1 && netmaskSepPos+1 < len(ipv4Str) { 77 netMask, err := strconv.ParseUint(ipv4Str[netmaskSepPos+1:], 10, 8) 78 if err != nil { 79 return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: unable to parse CIDR netmask: %v", ipv4Str, err) 80 } else if netMask > 128 { 81 return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: invalid CIDR netmask", ipv4Str) 82 } 83 84 if netMask >= 96 { 85 // Convert the IPv6 netmask to an IPv4 netmask 86 network.Mask = net.CIDRMask(int(netMask-96), IPv4len*8) 87 } 88 } 89 ipv4Addr := IPv4Addr{ 90 Address: IPv4Address(binary.BigEndian.Uint32(ipv4)), 91 Mask: IPv4Mask(binary.BigEndian.Uint32(network.Mask)), 92 } 93 return ipv4Addr, nil 94 } 95 96 // Attempt to parse ipv4Str as a /32 host with a port number. 97 tcpAddr, err := net.ResolveTCPAddr("tcp4", ipv4Str) 98 if err == nil { 99 ipv4 := tcpAddr.IP.To4() 100 if ipv4 == nil { 101 return IPv4Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv4 address", ipv4Str) 102 } 103 104 ipv4Uint32 := binary.BigEndian.Uint32(ipv4) 105 ipv4Addr := IPv4Addr{ 106 Address: IPv4Address(ipv4Uint32), 107 Mask: IPv4HostMask, 108 Port: IPPort(tcpAddr.Port), 109 } 110 111 return ipv4Addr, nil 112 } 113 114 // Parse as a naked IPv4 address 115 ip := net.ParseIP(ipv4Str) 116 if ip != nil { 117 ipv4 := ip.To4() 118 if ipv4 == nil { 119 return IPv4Addr{}, fmt.Errorf("Unable to string convert %+q to an IPv4 address", ipv4Str) 120 } 121 122 ipv4Uint32 := binary.BigEndian.Uint32(ipv4) 123 ipv4Addr := IPv4Addr{ 124 Address: IPv4Address(ipv4Uint32), 125 Mask: IPv4HostMask, 126 } 127 return ipv4Addr, nil 128 } 129 130 return IPv4Addr{}, fmt.Errorf("Unable to parse %+q to an IPv4 address: %v", ipv4Str, err) 131} 132 133// AddressBinString returns a string with the IPv4Addr's Address represented 134// as a sequence of '0' and '1' characters. This method is useful for 135// debugging or by operators who want to inspect an address. 136func (ipv4 IPv4Addr) AddressBinString() string { 137 return fmt.Sprintf("%032s", strconv.FormatUint(uint64(ipv4.Address), 2)) 138} 139 140// AddressHexString returns a string with the IPv4Addr address represented as 141// a sequence of hex characters. This method is useful for debugging or by 142// operators who want to inspect an address. 143func (ipv4 IPv4Addr) AddressHexString() string { 144 return fmt.Sprintf("%08s", strconv.FormatUint(uint64(ipv4.Address), 16)) 145} 146 147// Broadcast is an IPv4Addr-only method that returns the broadcast address of 148// the network. 149// 150// NOTE: IPv6 only supports multicast, so this method only exists for 151// IPv4Addr. 152func (ipv4 IPv4Addr) Broadcast() IPAddr { 153 // Nothing should listen on a broadcast address. 154 return IPv4Addr{ 155 Address: IPv4Address(ipv4.BroadcastAddress()), 156 Mask: IPv4HostMask, 157 } 158} 159 160// BroadcastAddress returns a IPv4Network of the IPv4Addr's broadcast 161// address. 162func (ipv4 IPv4Addr) BroadcastAddress() IPv4Network { 163 return IPv4Network(uint32(ipv4.Address)&uint32(ipv4.Mask) | ^uint32(ipv4.Mask)) 164} 165 166// CmpAddress follows the Cmp() standard protocol and returns: 167// 168// - -1 If the receiver should sort first because its address is lower than arg 169// - 0 if the SockAddr arg is equal to the receiving IPv4Addr or the argument is 170// of a different type. 171// - 1 If the argument should sort first. 172func (ipv4 IPv4Addr) CmpAddress(sa SockAddr) int { 173 ipv4b, ok := sa.(IPv4Addr) 174 if !ok { 175 return sortDeferDecision 176 } 177 178 switch { 179 case ipv4.Address == ipv4b.Address: 180 return sortDeferDecision 181 case ipv4.Address < ipv4b.Address: 182 return sortReceiverBeforeArg 183 default: 184 return sortArgBeforeReceiver 185 } 186} 187 188// CmpPort follows the Cmp() standard protocol and returns: 189// 190// - -1 If the receiver should sort first because its port is lower than arg 191// - 0 if the SockAddr arg's port number is equal to the receiving IPv4Addr, 192// regardless of type. 193// - 1 If the argument should sort first. 194func (ipv4 IPv4Addr) CmpPort(sa SockAddr) int { 195 var saPort IPPort 196 switch v := sa.(type) { 197 case IPv4Addr: 198 saPort = v.Port 199 case IPv6Addr: 200 saPort = v.Port 201 default: 202 return sortDeferDecision 203 } 204 205 switch { 206 case ipv4.Port == saPort: 207 return sortDeferDecision 208 case ipv4.Port < saPort: 209 return sortReceiverBeforeArg 210 default: 211 return sortArgBeforeReceiver 212 } 213} 214 215// CmpRFC follows the Cmp() standard protocol and returns: 216// 217// - -1 If the receiver should sort first because it belongs to the RFC and its 218// arg does not 219// - 0 if the receiver and arg both belong to the same RFC or neither do. 220// - 1 If the arg belongs to the RFC but receiver does not. 221func (ipv4 IPv4Addr) CmpRFC(rfcNum uint, sa SockAddr) int { 222 recvInRFC := IsRFC(rfcNum, ipv4) 223 ipv4b, ok := sa.(IPv4Addr) 224 if !ok { 225 // If the receiver is part of the desired RFC and the SockAddr 226 // argument is not, return -1 so that the receiver sorts before 227 // the non-IPv4 SockAddr. Conversely, if the receiver is not 228 // part of the RFC, punt on sorting and leave it for the next 229 // sorter. 230 if recvInRFC { 231 return sortReceiverBeforeArg 232 } else { 233 return sortDeferDecision 234 } 235 } 236 237 argInRFC := IsRFC(rfcNum, ipv4b) 238 switch { 239 case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC): 240 // If a and b both belong to the RFC, or neither belong to 241 // rfcNum, defer sorting to the next sorter. 242 return sortDeferDecision 243 case recvInRFC && !argInRFC: 244 return sortReceiverBeforeArg 245 default: 246 return sortArgBeforeReceiver 247 } 248} 249 250// Contains returns true if the SockAddr is contained within the receiver. 251func (ipv4 IPv4Addr) Contains(sa SockAddr) bool { 252 ipv4b, ok := sa.(IPv4Addr) 253 if !ok { 254 return false 255 } 256 257 return ipv4.ContainsNetwork(ipv4b) 258} 259 260// ContainsAddress returns true if the IPv4Address is contained within the 261// receiver. 262func (ipv4 IPv4Addr) ContainsAddress(x IPv4Address) bool { 263 return IPv4Address(ipv4.NetworkAddress()) <= x && 264 IPv4Address(ipv4.BroadcastAddress()) >= x 265} 266 267// ContainsNetwork returns true if the network from IPv4Addr is contained 268// within the receiver. 269func (ipv4 IPv4Addr) ContainsNetwork(x IPv4Addr) bool { 270 return ipv4.NetworkAddress() <= x.NetworkAddress() && 271 ipv4.BroadcastAddress() >= x.BroadcastAddress() 272} 273 274// DialPacketArgs returns the arguments required to be passed to 275// net.DialUDP(). If the Mask of ipv4 is not a /32 or the Port is 0, 276// DialPacketArgs() will fail. See Host() to create an IPv4Addr with its 277// mask set to /32. 278func (ipv4 IPv4Addr) DialPacketArgs() (network, dialArgs string) { 279 if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 { 280 return "udp4", "" 281 } 282 return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) 283} 284 285// DialStreamArgs returns the arguments required to be passed to 286// net.DialTCP(). If the Mask of ipv4 is not a /32 or the Port is 0, 287// DialStreamArgs() will fail. See Host() to create an IPv4Addr with its 288// mask set to /32. 289func (ipv4 IPv4Addr) DialStreamArgs() (network, dialArgs string) { 290 if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 { 291 return "tcp4", "" 292 } 293 return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) 294} 295 296// Equal returns true if a SockAddr is equal to the receiving IPv4Addr. 297func (ipv4 IPv4Addr) Equal(sa SockAddr) bool { 298 ipv4b, ok := sa.(IPv4Addr) 299 if !ok { 300 return false 301 } 302 303 if ipv4.Port != ipv4b.Port { 304 return false 305 } 306 307 if ipv4.Address != ipv4b.Address { 308 return false 309 } 310 311 if ipv4.NetIPNet().String() != ipv4b.NetIPNet().String() { 312 return false 313 } 314 315 return true 316} 317 318// FirstUsable returns an IPv4Addr set to the first address following the 319// network prefix. The first usable address in a network is normally the 320// gateway and should not be used except by devices forwarding packets 321// between two administratively distinct networks (i.e. a router). This 322// function does not discriminate against first usable vs "first address that 323// should be used." For example, FirstUsable() on "192.168.1.10/24" would 324// return the address "192.168.1.1/24". 325func (ipv4 IPv4Addr) FirstUsable() IPAddr { 326 addr := ipv4.NetworkAddress() 327 328 // If /32, return the address itself. If /31 assume a point-to-point 329 // link and return the lower address. 330 if ipv4.Maskbits() < 31 { 331 addr++ 332 } 333 334 return IPv4Addr{ 335 Address: IPv4Address(addr), 336 Mask: IPv4HostMask, 337 } 338} 339 340// Host returns a copy of ipv4 with its mask set to /32 so that it can be 341// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or 342// ListenStreamArgs(). 343func (ipv4 IPv4Addr) Host() IPAddr { 344 // Nothing should listen on a broadcast address. 345 return IPv4Addr{ 346 Address: ipv4.Address, 347 Mask: IPv4HostMask, 348 Port: ipv4.Port, 349 } 350} 351 352// IPPort returns the Port number attached to the IPv4Addr 353func (ipv4 IPv4Addr) IPPort() IPPort { 354 return ipv4.Port 355} 356 357// LastUsable returns the last address before the broadcast address in a 358// given network. 359func (ipv4 IPv4Addr) LastUsable() IPAddr { 360 addr := ipv4.BroadcastAddress() 361 362 // If /32, return the address itself. If /31 assume a point-to-point 363 // link and return the upper address. 364 if ipv4.Maskbits() < 31 { 365 addr-- 366 } 367 368 return IPv4Addr{ 369 Address: IPv4Address(addr), 370 Mask: IPv4HostMask, 371 } 372} 373 374// ListenPacketArgs returns the arguments required to be passed to 375// net.ListenUDP(). If the Mask of ipv4 is not a /32, ListenPacketArgs() 376// will fail. See Host() to create an IPv4Addr with its mask set to /32. 377func (ipv4 IPv4Addr) ListenPacketArgs() (network, listenArgs string) { 378 if ipv4.Mask != IPv4HostMask { 379 return "udp4", "" 380 } 381 return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) 382} 383 384// ListenStreamArgs returns the arguments required to be passed to 385// net.ListenTCP(). If the Mask of ipv4 is not a /32, ListenStreamArgs() 386// will fail. See Host() to create an IPv4Addr with its mask set to /32. 387func (ipv4 IPv4Addr) ListenStreamArgs() (network, listenArgs string) { 388 if ipv4.Mask != IPv4HostMask { 389 return "tcp4", "" 390 } 391 return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) 392} 393 394// Maskbits returns the number of network mask bits in a given IPv4Addr. For 395// example, the Maskbits() of "192.168.1.1/24" would return 24. 396func (ipv4 IPv4Addr) Maskbits() int { 397 mask := make(net.IPMask, IPv4len) 398 binary.BigEndian.PutUint32(mask, uint32(ipv4.Mask)) 399 maskOnes, _ := mask.Size() 400 return maskOnes 401} 402 403// MustIPv4Addr is a helper method that must return an IPv4Addr or panic on 404// invalid input. 405func MustIPv4Addr(addr string) IPv4Addr { 406 ipv4, err := NewIPv4Addr(addr) 407 if err != nil { 408 panic(fmt.Sprintf("Unable to create an IPv4Addr from %+q: %v", addr, err)) 409 } 410 return ipv4 411} 412 413// NetIP returns the address as a net.IP (address is always presized to 414// IPv4). 415func (ipv4 IPv4Addr) NetIP() *net.IP { 416 x := make(net.IP, IPv4len) 417 binary.BigEndian.PutUint32(x, uint32(ipv4.Address)) 418 return &x 419} 420 421// NetIPMask create a new net.IPMask from the IPv4Addr. 422func (ipv4 IPv4Addr) NetIPMask() *net.IPMask { 423 ipv4Mask := net.IPMask{} 424 ipv4Mask = make(net.IPMask, IPv4len) 425 binary.BigEndian.PutUint32(ipv4Mask, uint32(ipv4.Mask)) 426 return &ipv4Mask 427} 428 429// NetIPNet create a new net.IPNet from the IPv4Addr. 430func (ipv4 IPv4Addr) NetIPNet() *net.IPNet { 431 ipv4net := &net.IPNet{} 432 ipv4net.IP = make(net.IP, IPv4len) 433 binary.BigEndian.PutUint32(ipv4net.IP, uint32(ipv4.NetworkAddress())) 434 ipv4net.Mask = *ipv4.NetIPMask() 435 return ipv4net 436} 437 438// Network returns the network prefix or network address for a given network. 439func (ipv4 IPv4Addr) Network() IPAddr { 440 return IPv4Addr{ 441 Address: IPv4Address(ipv4.NetworkAddress()), 442 Mask: ipv4.Mask, 443 } 444} 445 446// NetworkAddress returns an IPv4Network of the IPv4Addr's network address. 447func (ipv4 IPv4Addr) NetworkAddress() IPv4Network { 448 return IPv4Network(uint32(ipv4.Address) & uint32(ipv4.Mask)) 449} 450 451// Octets returns a slice of the four octets in an IPv4Addr's Address. The 452// order of the bytes is big endian. 453func (ipv4 IPv4Addr) Octets() []int { 454 return []int{ 455 int(ipv4.Address >> 24), 456 int((ipv4.Address >> 16) & 0xff), 457 int((ipv4.Address >> 8) & 0xff), 458 int(ipv4.Address & 0xff), 459 } 460} 461 462// String returns a string representation of the IPv4Addr 463func (ipv4 IPv4Addr) String() string { 464 if ipv4.Port != 0 { 465 return fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) 466 } 467 468 if ipv4.Maskbits() == 32 { 469 return ipv4.NetIP().String() 470 } 471 472 return fmt.Sprintf("%s/%d", ipv4.NetIP().String(), ipv4.Maskbits()) 473} 474 475// Type is used as a type switch and returns TypeIPv4 476func (IPv4Addr) Type() SockAddrType { 477 return TypeIPv4 478} 479 480// IPv4AddrAttr returns a string representation of an attribute for the given 481// IPv4Addr. 482func IPv4AddrAttr(ipv4 IPv4Addr, selector AttrName) string { 483 fn, found := ipv4AddrAttrMap[selector] 484 if !found { 485 return "" 486 } 487 488 return fn(ipv4) 489} 490 491// IPv4Attrs returns a list of attributes supported by the IPv4Addr type 492func IPv4Attrs() []AttrName { 493 return ipv4AddrAttrs 494} 495 496// ipv4AddrInit is called once at init() 497func ipv4AddrInit() { 498 // Sorted for human readability 499 ipv4AddrAttrs = []AttrName{ 500 "size", // Same position as in IPv6 for output consistency 501 "broadcast", 502 "uint32", 503 } 504 505 ipv4AddrAttrMap = map[AttrName]func(ipv4 IPv4Addr) string{ 506 "broadcast": func(ipv4 IPv4Addr) string { 507 return ipv4.Broadcast().String() 508 }, 509 "size": func(ipv4 IPv4Addr) string { 510 return fmt.Sprintf("%d", 1<<uint(IPv4len*8-ipv4.Maskbits())) 511 }, 512 "uint32": func(ipv4 IPv4Addr) string { 513 return fmt.Sprintf("%d", uint32(ipv4.Address)) 514 }, 515 } 516} 517