github.com/crowdsecurity/crowdsec@v1.6.1/pkg/types/ip.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"math"
     7  	"net"
     8  	"strings"
     9  )
    10  
    11  // LastAddress returns the last address of a network
    12  func LastAddress(n net.IPNet) net.IP {
    13  	// get the last address by ORing the hostmask and the IP
    14  	ip := n.IP.To4()
    15  	if ip == nil {
    16  		// IPv6
    17  		ip = n.IP
    18  		return net.IP{
    19  			ip[0] | ^n.Mask[0], ip[1] | ^n.Mask[1], ip[2] | ^n.Mask[2],
    20  			ip[3] | ^n.Mask[3], ip[4] | ^n.Mask[4], ip[5] | ^n.Mask[5],
    21  			ip[6] | ^n.Mask[6], ip[7] | ^n.Mask[7], ip[8] | ^n.Mask[8],
    22  			ip[9] | ^n.Mask[9], ip[10] | ^n.Mask[10], ip[11] | ^n.Mask[11],
    23  			ip[12] | ^n.Mask[12], ip[13] | ^n.Mask[13], ip[14] | ^n.Mask[14],
    24  			ip[15] | ^n.Mask[15]}
    25  	}
    26  
    27  	return net.IPv4(
    28  		ip[0]|^n.Mask[0],
    29  		ip[1]|^n.Mask[1],
    30  		ip[2]|^n.Mask[2],
    31  		ip[3]|^n.Mask[3])
    32  }
    33  
    34  /*returns a range for any ip or range*/
    35  func Addr2Ints(anyIP string) (int, int64, int64, int64, int64, error) {
    36  	if strings.Contains(anyIP, "/") {
    37  		_, net, err := net.ParseCIDR(anyIP)
    38  		if err != nil {
    39  			return -1, 0, 0, 0, 0, fmt.Errorf("while parsing range %s: %w", anyIP, err)
    40  		}
    41  		return Range2Ints(*net)
    42  	}
    43  
    44  	ip := net.ParseIP(anyIP)
    45  	if ip == nil {
    46  		return -1, 0, 0, 0, 0, fmt.Errorf("invalid address")
    47  	}
    48  
    49  	sz, start, end, err := IP2Ints(ip)
    50  	if err != nil {
    51  		return -1, 0, 0, 0, 0, fmt.Errorf("while parsing ip %s: %w", anyIP, err)
    52  	}
    53  
    54  	return sz, start, end, start, end, nil
    55  }
    56  
    57  /*size (16|4), nw_start, suffix_start, nw_end, suffix_end, error*/
    58  func Range2Ints(network net.IPNet) (int, int64, int64, int64, int64, error) {
    59  
    60  	szStart, nwStart, sfxStart, err := IP2Ints(network.IP)
    61  	if err != nil {
    62  		return -1, 0, 0, 0, 0, fmt.Errorf("converting first ip in range: %w", err)
    63  	}
    64  	lastAddr := LastAddress(network)
    65  	szEnd, nwEnd, sfxEnd, err := IP2Ints(lastAddr)
    66  	if err != nil {
    67  		return -1, 0, 0, 0, 0, fmt.Errorf("transforming last address of range: %w", err)
    68  	}
    69  	if szEnd != szStart {
    70  		return -1, 0, 0, 0, 0, fmt.Errorf("inconsistent size for range first(%d) and last(%d) ip", szStart, szEnd)
    71  	}
    72  	return szStart, nwStart, sfxStart, nwEnd, sfxEnd, nil
    73  }
    74  
    75  func uint2int(u uint64) int64 {
    76  	var ret int64
    77  	if u == math.MaxInt64 {
    78  		ret = 0
    79  	} else if u == math.MaxUint64 {
    80  		ret = math.MaxInt64
    81  	} else if u > math.MaxInt64 {
    82  		u -= math.MaxInt64
    83  		ret = int64(u)
    84  	} else {
    85  		ret = int64(u)
    86  		ret -= math.MaxInt64
    87  	}
    88  	return ret
    89  }
    90  
    91  /*size (16|4), network, suffix, error*/
    92  func IP2Ints(pip net.IP) (int, int64, int64, error) {
    93  	var ip_nw, ip_sfx uint64
    94  
    95  	pip4 := pip.To4()
    96  	pip16 := pip.To16()
    97  
    98  	if pip4 != nil {
    99  		ip_nw32 := binary.BigEndian.Uint32(pip4)
   100  
   101  		return 4, uint2int(uint64(ip_nw32)), uint2int(ip_sfx), nil
   102  	} else if pip16 != nil {
   103  		ip_nw = binary.BigEndian.Uint64(pip16[0:8])
   104  		ip_sfx = binary.BigEndian.Uint64(pip16[8:16])
   105  		return 16, uint2int(ip_nw), uint2int(ip_sfx), nil
   106  	} else {
   107  		return -1, 0, 0, fmt.Errorf("unexpected len %d for %s", len(pip), pip)
   108  	}
   109  }