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