Implement the Writer interface + io.CopyBuffer

nosocat
Jean-Louis Huynen 2019-01-11 16:15:55 +01:00
parent 066f29e8d1
commit 3d5feca4e7
1 changed files with 42 additions and 84 deletions

View File

@ -39,10 +39,10 @@ type (
// A d4 writer implements the io.Writer Interface by implementing Write() and Close() // A d4 writer implements the io.Writer Interface by implementing Write() and Close()
// it accepts an io.Writer as sink // it accepts an io.Writer as sink
d4Writer struct { d4Writer struct {
w io.Writer w io.Writer
key []byte key []byte
d4header []byte fb []byte
payload []byte pb []byte
} }
d4S struct { d4S struct {
@ -122,7 +122,7 @@ func main() {
if d4loadConfig(d4p) == true { if d4loadConfig(d4p) == true {
if d4.dst.initHeader(d4p) == true { if d4.dst.initHeader(d4p) == true {
d4transfer(d4p) io.CopyBuffer(&d4.dst, d4.src, d4.dst.pb)
} }
} }
} }
@ -202,6 +202,10 @@ func d4checkConfig(d4 *d4S) bool {
f.Close() f.Close()
} }
// Create the copy buffer
(*d4).dst.fb = make([]byte, HDR_SIZE+(*d4).conf.snaplen)
(*d4).dst.pb = make([]byte, (*d4).conf.snaplen)
return true return true
} }
@ -214,107 +218,61 @@ func generateUUIDv4() []byte {
return []byte(uuid[:]) return []byte(uuid[:])
} }
func d4transfer(d4 *d4S) {
src := (*d4).src
dst := (*d4).dst
buf := make([]byte, (*d4).conf.snaplen)
varybuf := make([]byte, 0)
for {
// Take a slice of snaplen
nread, err := src.Read(buf)
if err != nil {
// if EOF, we just wait for more data
if err != io.EOF {
log.Fatal(err)
} else if (*d4).debug {
os.Exit(0)
}
}
// And push it into the d4writer -> sink chain
switch {
case uint32(nread) == (*d4).conf.snaplen:
dst.Write(buf)
case nread > 0 && uint32(nread) < (*d4).conf.snaplen:
varybuf = append(buf[:nread])
dst.Write(varybuf)
}
}
}
func (d4w *d4Writer) Write(bs []byte) (int, error) { func (d4w *d4Writer) Write(bs []byte) (int, error) {
d4w.updateHeader(bs) // bs is pb
d4w.payload = bs // zero out moving parts of the frame
d4w.updateHMAC() copy(d4w.fb[18:62], make([]byte, 44))
copy(d4w.fb[62:], make([]byte, 62+len(bs)))
// update headers
d4w.updateHeader(len(bs))
// Copy payload after the header
copy(d4w.fb[62:62+len(bs)], bs)
// Now that the packet is complete, compute hmac
d4w.updateHMAC(len(bs))
// Eventually write binary in the sink // Eventually write binary in the sink
binary.Write(d4w.w, binary.LittleEndian, append(d4w.d4header, d4w.payload...)) err := binary.Write(d4w.w, binary.LittleEndian, d4w.fb[:62+len(bs)])
if err != nil {
log.Fatal(err)
}
return len(bs), nil return len(bs), nil
} }
// TODO write go idiomatic err return values // TODO write go idiomatic err return values
func (d4w *d4Writer) updateHeader(bs []byte) bool { func (d4w *d4Writer) updateHeader(lenbs int) bool {
// zero out moving parts
copy(d4w.d4header[18:], make([]byte, 44))
timeUnix := time.Now().Unix() timeUnix := time.Now().Unix()
ps := 18 binary.LittleEndian.PutUint64(d4w.fb[18:26], uint64(timeUnix))
pe := ps + TIMESTAMP_SIZE binary.LittleEndian.PutUint32(d4w.fb[58:62], uint32(lenbs))
binary.LittleEndian.PutUint64(d4w.d4header[ps:pe], uint64(timeUnix))
// hmac is set to zero during hmac operations, so leave it alone
// still, we move the pointers
ps = pe
pe = ps + HMAC_SIZE
ps = pe
pe = ps + 4
// Set payload size
binary.LittleEndian.PutUint32(d4w.d4header[ps:pe], uint32(len(bs)))
return true return true
} }
func (d4w *d4Writer) updateHMAC() bool { func (d4w *d4Writer) updateHMAC(ps int) bool {
h := hmac.New(sha256.New, d4w.key) h := hmac.New(sha256.New, d4w.key)
// version h.Write(d4w.fb[0:1])
h.Write(d4w.d4header[0:1]) h.Write(d4w.fb[1:2])
// type h.Write(d4w.fb[2:18])
h.Write(d4w.d4header[1:2]) h.Write(d4w.fb[18:26])
// uuid
h.Write(d4w.d4header[2:18])
// timestamp
h.Write(d4w.d4header[18:26])
// hmac (0)
h.Write(make([]byte, 32)) h.Write(make([]byte, 32))
// size h.Write(d4w.fb[58:62])
h.Write(d4w.d4header[58:]) h.Write(d4w.fb[62 : 62+ps])
// payload copy(d4w.fb[26:58], h.Sum(nil))
h.Write(d4w.payload)
// final hmac
copy(d4w.d4header[26:58], h.Sum(nil))
return true return true
} }
func (d4w *d4Writer) initHeader(d4 *d4S) bool { func (d4w *d4Writer) initHeader(d4 *d4S) bool {
// zero out the header // zero out the header
d4w.d4header = make([]byte, HDR_SIZE) copy(d4w.fb[:HDR_SIZE], make([]byte, HDR_SIZE))
// put version a type into the header // put version a type into the header
d4w.d4header[0] = (*d4).conf.version d4w.fb[0] = (*d4).conf.version
d4w.d4header[1] = (*d4).conf.ttype d4w.fb[1] = (*d4).conf.ttype
// put uuid into the header // put uuid into the header
ps := 2 copy(d4w.fb[2:18], (*d4).conf.uuid)
pe := ps + UUID_SIZE
copy(d4w.d4header[ps:pe], (*d4).conf.uuid)
// timestamp // timestamp
timeUnix := time.Now().UnixNano() timeUnix := time.Now().UnixNano()
ps = pe binary.LittleEndian.PutUint64(d4w.fb[18:26], uint64(timeUnix))
pe = ps + TIMESTAMP_SIZE
binary.LittleEndian.PutUint64(d4w.d4header[ps:pe], uint64(timeUnix))
// hmac is set to zero during hmac operations, so leave it alone // hmac is set to zero during hmac operations, so leave it alone
// still, we move the pointers
ps = pe
pe = ps + HMAC_SIZE
ps = pe
pe = ps + 4
// init size of payload at 0 // init size of payload at 0
binary.LittleEndian.PutUint32(d4w.d4header[ps:pe], uint32(0)) binary.LittleEndian.PutUint32(d4w.fb[58:62], uint32(0))
infof(fmt.Sprintf("Initialized a %d bytes header:\n", len(d4w.d4header))) infof(fmt.Sprintf("Initialized a %d bytes header:\n", HDR_SIZE))
infof(fmt.Sprintf("%b\n", d4w.d4header)) infof(fmt.Sprintf("%b\n", d4w.fb[:HDR_SIZE]))
return true return true
} }