package util
import (
"crypto/rand"
"encoding/base32"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcapgo"
log "github.com/sirupsen/logrus"
"hash/adler32"
"io/ioutil"
"net"
"os"
"strconv"
"strings"
"time"
)
// WritePcap writes the provided data to a given pcap file
func WritePcap ( file string , data [ ] byte ) {
f , err := os . Create ( file )
if err != nil {
log . Errorf ( "Error writing pcap file %s" , file )
}
defer f . Close ( )
r , err := pcapgo . NewNgWriter ( f , layers . LinkTypeEthernet )
if err != nil {
log . Errorf ( "Error writing pcap file %s" , file )
}
defer r . Flush ( )
ci := gopacket . CaptureInfo {
Timestamp : time . Now ( ) ,
CaptureLength : len ( data ) ,
Length : len ( data ) ,
}
err = r . WritePacket ( ci , data )
}
// WriteBinary writes the provided data to a given binary file
func WriteBinary ( file string , data [ ] byte ) {
if err := ioutil . WriteFile ( file , data , 0644 ) ; err != nil {
log . Errorf ( "Error writing binary file %s" , file )
}
}
func WritePIDFile ( filename string ) {
if filename == "" {
return
}
if err := ioutil . WriteFile ( filename , [ ] byte ( strconv . Itoa ( os . Getpid ( ) ) + "\n" ) , 0644 ) ; err != nil {
log . Errorf ( "Error writing PID file %s" , filename )
}
}
func GenerateMac ( customMAC string ) net . HardwareAddr {
if customMAC != "" {
ret , _ := net . ParseMAC ( customMAC )
return ret
}
buf := make ( [ ] byte , 6 )
var mac net . HardwareAddr
if _ , err := rand . Read ( buf ) ; err != nil {
log . Error ( "Error generating random mac" )
ret , _ := net . ParseMAC ( "52:54:00:12:34:aa" )
return ret
}
// Set local bit, ensure unicast address
buf [ 0 ] = ( buf [ 0 ] | 2 ) & 0xfe
mac = append ( mac , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] , buf [ 3 ] , buf [ 4 ] , buf [ 5 ] )
return mac
}
func GenerateXID ( ) [ ] byte {
buf := make ( [ ] byte , 4 )
if _ , err := rand . Read ( buf ) ; err != nil {
log . Error ( "Error generating random xid" )
return [ ] byte { 36 , 23 , 250 , 224 } // chosen by fair dice roll
// guaranteed to be random --> https://xkcd.com/221/
}
return buf
}
func GenerateUId ( path string ) string {
adl := adler32 . Checksum ( [ ] byte ( path ) )
byt := make ( [ ] byte , 4 )
for i := uint32 ( 0 ) ; i < 4 ; i ++ {
byt [ i ] = byte ( ( adl >> ( 8 * i ) ) & 0xff )
}
b32 := base32 . StdEncoding . EncodeToString ( byt )
return strings . ReplaceAll ( b32 , "=" , "" )
}
// If is a helper type to form expressive ternary expressions being the
// concatenation of a type conversion and a method call such as:
//
// i := If(cond).Int(a, b)
//
// For details, see https://stackoverflow.com/a/59375088/1705598
type If bool
// If returns a if c is true, b otherwise.
func ( c If ) If ( a , b interface { } ) interface { } {
if c {
return a
}
return b
}
// MAC returns a if c is true, b otherwise.
func ( c If ) MAC ( a , b net . HardwareAddr ) net . HardwareAddr {
if c {
return a
}
return b
}
// IP returns a if c is true, b otherwise.
func ( c If ) IP ( a , b net . IP ) net . IP {
if c {
return a
}
return b
}