File: input.go

package info (click to toggle)
golang-github-farsightsec-go-nmsg 0.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 500 kB
  • sloc: sh: 21; makefile: 3
file content (147 lines) | stat: -rw-r--r-- 4,407 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * Copyright (c) 2017 by Farsight Security, Inc.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

package nmsg

/*
#cgo pkg-config: libnmsg
#cgo LDFLAGS: -lnmsg
#include <stdlib.h>
#include <nmsg.h>

extern nmsg_res inputCallback(nmsg_message_t *msg, void *user);

nmsg_res input_callback(nmsg_message_t *msg, void *user) {
        return inputCallback(msg, user);
}
*/
import "C"
import (
	"io"
	"net"
	"os"
	"unsafe"
)

// An Input is a source of NMSG payloads (Messages).
type Input interface {
	// Read returns a Message or nil, and an error if any.
	Read() (*Message, error)

	// SetFilterMsgtype instructs the input to discard all Messages
	// not of the given vendor id and msgtype, specified by number.
	SetFilterMsgtype(vendor, msgtype uint32)

	// SetFilterMsgtypeByname instructs the input to discard all Messages
	// not of the given vendor id and msgtype, specified by name.
	SetFilterMsgtypeByname(vendor, msgtype string)

	// SetFilterSource instructs the input to discard all Messages not
	// from the supplied source.
	SetFilterSource(source uint32)

	// SetFilterOperator instructs the input to discard all Messages not
	// from the supplied operator.
	SetFilterOperator(operator uint32)

	// SetFilterGroup instructs the input to discard all Messages not
	// in the supplied group.
	SetFilterGroup(group uint32)
}

// NmsgInput is an Input managed by libnmsg. It satisfies
// the Input interface, and has
type nmsgInput struct {
	file  *os.File
	input C.nmsg_input_t
}

func (i *nmsgInput) Read() (*Message, error) {
	var msg C.nmsg_message_t
	res := C.nmsg_input_read(i.input, &msg)
	if res == C.nmsg_res_success {
		return messageFromC(msg), nil
	}
	return nil, nmsgError(res)
}

func (i *nmsgInput) SetFilterMsgtype(vid, msgtype uint32) {
	C.nmsg_input_set_filter_msgtype(i.input, C.uint(vid), C.uint(msgtype))
}

func (i *nmsgInput) SetFilterMsgtypeByname(vendor, msgtype string) {
	cname := C.CString(vendor)
	ctype := C.CString(msgtype)
	C.nmsg_input_set_filter_msgtype_byname(i.input, cname, ctype)
	C.free(unsafe.Pointer(cname))
	C.free(unsafe.Pointer(ctype))
}

func (i *nmsgInput) SetFilterSource(source uint32) {
	C.nmsg_input_set_filter_source(i.input, C.uint(source))
}

func (i *nmsgInput) SetFilterOperator(operator uint32) {
	C.nmsg_input_set_filter_operator(i.input, C.uint(operator))
}

func (i *nmsgInput) SetFilterGroup(group uint32) {
	C.nmsg_input_set_filter_group(i.input, C.uint(group))
}

// NewInput creates a new Input from an io.Reader.
// Currently, the reader must be a *net.UDPConn or a *os.File
func NewInput(r io.Reader) Input {
	switch r := r.(type) {
	case *net.UDPConn:
		f, err := r.File()
		if err != nil {
			return nil
		}
		return &nmsgInput{f, C.nmsg_input_open_sock(C.int(f.Fd()))}
	case *os.File:
		return &nmsgInput{r, C.nmsg_input_open_file(C.int(r.Fd()))}
	default:
		return nil
		// return &containerReader{Reader: r}
	}
}

// NewCallbackInput creates an NmsgInput which calls the supplied InputFunc.
func NewCallbackInput(i InputFunc) Input {
	return &nmsgInput{
		file:  nil,
		input: C.nmsg_input_open_callback(C.nmsg_cb_message_read(C.input_callback), registerInput(i)),
	}
}

// An InputFunc is a function with the same signature as Input.Read(), usable
// directly as an Input.
//
// When used directly as an Input, only the Read() method is implemented. All
// others are no-ops. If the functionality of the other methods is desired,
// the InputFunc can be passed to NewCallbackInput.
type InputFunc func() (*Message, error)

// Read calls the underlying function to return the next message.
func (i InputFunc) Read() (*Message, error) { return i() }

// SetFilterMsgtype satisfies the Input interface with a no-op
func (i InputFunc) SetFilterMsgtype(vendor, msgtype uint32) {}

// SetFilterMsgtypeByname satisfies the Input interface with a no-op
func (i InputFunc) SetFilterMsgtypeByname(vendor, msgtype string) {}

// SetFilterSource satisfies the Input interface with a no-op
func (i InputFunc) SetFilterSource(source uint32) {}

// SetFilterOperator satisfies the Input interface with a no-op
func (i InputFunc) SetFilterOperator(operator uint32) {}

// SetFilterGroup satisfies the Input interface with a no-op
func (i InputFunc) SetFilterGroup(group uint32) {}