Codebase list golang-github-farsightsec-go-nmsg / upstream/0.0_git20190917.04d2174
New upstream version 0.0~git20190917.04d2174 Sascha Steinbiss 3 years ago
58 changed file(s) with 6160 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 Copyright 2017,2018 Farsight Security, Inc.
1
2 This Source Code Form is subject to the terms of the Mozilla Public
3 License, v. 2.0. If a copy of the MPL was not distributed with this
4 file, You can obtain one at http://mozilla.org/MPL/2.0/.
0 Mozilla Public License Version 2.0
1 ==================================
2
3 1. Definitions
4 --------------
5
6 1.1. "Contributor"
7 means each individual or legal entity that creates, contributes to
8 the creation of, or owns Covered Software.
9
10 1.2. "Contributor Version"
11 means the combination of the Contributions of others (if any) used
12 by a Contributor and that particular Contributor's Contribution.
13
14 1.3. "Contribution"
15 means Covered Software of a particular Contributor.
16
17 1.4. "Covered Software"
18 means Source Code Form to which the initial Contributor has attached
19 the notice in Exhibit A, the Executable Form of such Source Code
20 Form, and Modifications of such Source Code Form, in each case
21 including portions thereof.
22
23 1.5. "Incompatible With Secondary Licenses"
24 means
25
26 (a) that the initial Contributor has attached the notice described
27 in Exhibit B to the Covered Software; or
28
29 (b) that the Covered Software was made available under the terms of
30 version 1.1 or earlier of the License, but not also under the
31 terms of a Secondary License.
32
33 1.6. "Executable Form"
34 means any form of the work other than Source Code Form.
35
36 1.7. "Larger Work"
37 means a work that combines Covered Software with other material, in
38 a separate file or files, that is not Covered Software.
39
40 1.8. "License"
41 means this document.
42
43 1.9. "Licensable"
44 means having the right to grant, to the maximum extent possible,
45 whether at the time of the initial grant or subsequently, any and
46 all of the rights conveyed by this License.
47
48 1.10. "Modifications"
49 means any of the following:
50
51 (a) any file in Source Code Form that results from an addition to,
52 deletion from, or modification of the contents of Covered
53 Software; or
54
55 (b) any new file in Source Code Form that contains any Covered
56 Software.
57
58 1.11. "Patent Claims" of a Contributor
59 means any patent claim(s), including without limitation, method,
60 process, and apparatus claims, in any patent Licensable by such
61 Contributor that would be infringed, but for the grant of the
62 License, by the making, using, selling, offering for sale, having
63 made, import, or transfer of either its Contributions or its
64 Contributor Version.
65
66 1.12. "Secondary License"
67 means either the GNU General Public License, Version 2.0, the GNU
68 Lesser General Public License, Version 2.1, the GNU Affero General
69 Public License, Version 3.0, or any later versions of those
70 licenses.
71
72 1.13. "Source Code Form"
73 means the form of the work preferred for making modifications.
74
75 1.14. "You" (or "Your")
76 means an individual or a legal entity exercising rights under this
77 License. For legal entities, "You" includes any entity that
78 controls, is controlled by, or is under common control with You. For
79 purposes of this definition, "control" means (a) the power, direct
80 or indirect, to cause the direction or management of such entity,
81 whether by contract or otherwise, or (b) ownership of more than
82 fifty percent (50%) of the outstanding shares or beneficial
83 ownership of such entity.
84
85 2. License Grants and Conditions
86 --------------------------------
87
88 2.1. Grants
89
90 Each Contributor hereby grants You a world-wide, royalty-free,
91 non-exclusive license:
92
93 (a) under intellectual property rights (other than patent or trademark)
94 Licensable by such Contributor to use, reproduce, make available,
95 modify, display, perform, distribute, and otherwise exploit its
96 Contributions, either on an unmodified basis, with Modifications, or
97 as part of a Larger Work; and
98
99 (b) under Patent Claims of such Contributor to make, use, sell, offer
100 for sale, have made, import, and otherwise transfer either its
101 Contributions or its Contributor Version.
102
103 2.2. Effective Date
104
105 The licenses granted in Section 2.1 with respect to any Contribution
106 become effective for each Contribution on the date the Contributor first
107 distributes such Contribution.
108
109 2.3. Limitations on Grant Scope
110
111 The licenses granted in this Section 2 are the only rights granted under
112 this License. No additional rights or licenses will be implied from the
113 distribution or licensing of Covered Software under this License.
114 Notwithstanding Section 2.1(b) above, no patent license is granted by a
115 Contributor:
116
117 (a) for any code that a Contributor has removed from Covered Software;
118 or
119
120 (b) for infringements caused by: (i) Your and any other third party's
121 modifications of Covered Software, or (ii) the combination of its
122 Contributions with other software (except as part of its Contributor
123 Version); or
124
125 (c) under Patent Claims infringed by Covered Software in the absence of
126 its Contributions.
127
128 This License does not grant any rights in the trademarks, service marks,
129 or logos of any Contributor (except as may be necessary to comply with
130 the notice requirements in Section 3.4).
131
132 2.4. Subsequent Licenses
133
134 No Contributor makes additional grants as a result of Your choice to
135 distribute the Covered Software under a subsequent version of this
136 License (see Section 10.2) or under the terms of a Secondary License (if
137 permitted under the terms of Section 3.3).
138
139 2.5. Representation
140
141 Each Contributor represents that the Contributor believes its
142 Contributions are its original creation(s) or it has sufficient rights
143 to grant the rights to its Contributions conveyed by this License.
144
145 2.6. Fair Use
146
147 This License is not intended to limit any rights You have under
148 applicable copyright doctrines of fair use, fair dealing, or other
149 equivalents.
150
151 2.7. Conditions
152
153 Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
154 in Section 2.1.
155
156 3. Responsibilities
157 -------------------
158
159 3.1. Distribution of Source Form
160
161 All distribution of Covered Software in Source Code Form, including any
162 Modifications that You create or to which You contribute, must be under
163 the terms of this License. You must inform recipients that the Source
164 Code Form of the Covered Software is governed by the terms of this
165 License, and how they can obtain a copy of this License. You may not
166 attempt to alter or restrict the recipients' rights in the Source Code
167 Form.
168
169 3.2. Distribution of Executable Form
170
171 If You distribute Covered Software in Executable Form then:
172
173 (a) such Covered Software must also be made available in Source Code
174 Form, as described in Section 3.1, and You must inform recipients of
175 the Executable Form how they can obtain a copy of such Source Code
176 Form by reasonable means in a timely manner, at a charge no more
177 than the cost of distribution to the recipient; and
178
179 (b) You may distribute such Executable Form under the terms of this
180 License, or sublicense it under different terms, provided that the
181 license for the Executable Form does not attempt to limit or alter
182 the recipients' rights in the Source Code Form under this License.
183
184 3.3. Distribution of a Larger Work
185
186 You may create and distribute a Larger Work under terms of Your choice,
187 provided that You also comply with the requirements of this License for
188 the Covered Software. If the Larger Work is a combination of Covered
189 Software with a work governed by one or more Secondary Licenses, and the
190 Covered Software is not Incompatible With Secondary Licenses, this
191 License permits You to additionally distribute such Covered Software
192 under the terms of such Secondary License(s), so that the recipient of
193 the Larger Work may, at their option, further distribute the Covered
194 Software under the terms of either this License or such Secondary
195 License(s).
196
197 3.4. Notices
198
199 You may not remove or alter the substance of any license notices
200 (including copyright notices, patent notices, disclaimers of warranty,
201 or limitations of liability) contained within the Source Code Form of
202 the Covered Software, except that You may alter any license notices to
203 the extent required to remedy known factual inaccuracies.
204
205 3.5. Application of Additional Terms
206
207 You may choose to offer, and to charge a fee for, warranty, support,
208 indemnity or liability obligations to one or more recipients of Covered
209 Software. However, You may do so only on Your own behalf, and not on
210 behalf of any Contributor. You must make it absolutely clear that any
211 such warranty, support, indemnity, or liability obligation is offered by
212 You alone, and You hereby agree to indemnify every Contributor for any
213 liability incurred by such Contributor as a result of warranty, support,
214 indemnity or liability terms You offer. You may include additional
215 disclaimers of warranty and limitations of liability specific to any
216 jurisdiction.
217
218 4. Inability to Comply Due to Statute or Regulation
219 ---------------------------------------------------
220
221 If it is impossible for You to comply with any of the terms of this
222 License with respect to some or all of the Covered Software due to
223 statute, judicial order, or regulation then You must: (a) comply with
224 the terms of this License to the maximum extent possible; and (b)
225 describe the limitations and the code they affect. Such description must
226 be placed in a text file included with all distributions of the Covered
227 Software under this License. Except to the extent prohibited by statute
228 or regulation, such description must be sufficiently detailed for a
229 recipient of ordinary skill to be able to understand it.
230
231 5. Termination
232 --------------
233
234 5.1. The rights granted under this License will terminate automatically
235 if You fail to comply with any of its terms. However, if You become
236 compliant, then the rights granted under this License from a particular
237 Contributor are reinstated (a) provisionally, unless and until such
238 Contributor explicitly and finally terminates Your grants, and (b) on an
239 ongoing basis, if such Contributor fails to notify You of the
240 non-compliance by some reasonable means prior to 60 days after You have
241 come back into compliance. Moreover, Your grants from a particular
242 Contributor are reinstated on an ongoing basis if such Contributor
243 notifies You of the non-compliance by some reasonable means, this is the
244 first time You have received notice of non-compliance with this License
245 from such Contributor, and You become compliant prior to 30 days after
246 Your receipt of the notice.
247
248 5.2. If You initiate litigation against any entity by asserting a patent
249 infringement claim (excluding declaratory judgment actions,
250 counter-claims, and cross-claims) alleging that a Contributor Version
251 directly or indirectly infringes any patent, then the rights granted to
252 You by any and all Contributors for the Covered Software under Section
253 2.1 of this License shall terminate.
254
255 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
256 end user license agreements (excluding distributors and resellers) which
257 have been validly granted by You or Your distributors under this License
258 prior to termination shall survive termination.
259
260 ************************************************************************
261 * *
262 * 6. Disclaimer of Warranty *
263 * ------------------------- *
264 * *
265 * Covered Software is provided under this License on an "as is" *
266 * basis, without warranty of any kind, either expressed, implied, or *
267 * statutory, including, without limitation, warranties that the *
268 * Covered Software is free of defects, merchantable, fit for a *
269 * particular purpose or non-infringing. The entire risk as to the *
270 * quality and performance of the Covered Software is with You. *
271 * Should any Covered Software prove defective in any respect, You *
272 * (not any Contributor) assume the cost of any necessary servicing, *
273 * repair, or correction. This disclaimer of warranty constitutes an *
274 * essential part of this License. No use of any Covered Software is *
275 * authorized under this License except under this disclaimer. *
276 * *
277 ************************************************************************
278
279 ************************************************************************
280 * *
281 * 7. Limitation of Liability *
282 * -------------------------- *
283 * *
284 * Under no circumstances and under no legal theory, whether tort *
285 * (including negligence), contract, or otherwise, shall any *
286 * Contributor, or anyone who distributes Covered Software as *
287 * permitted above, be liable to You for any direct, indirect, *
288 * special, incidental, or consequential damages of any character *
289 * including, without limitation, damages for lost profits, loss of *
290 * goodwill, work stoppage, computer failure or malfunction, or any *
291 * and all other commercial damages or losses, even if such party *
292 * shall have been informed of the possibility of such damages. This *
293 * limitation of liability shall not apply to liability for death or *
294 * personal injury resulting from such party's negligence to the *
295 * extent applicable law prohibits such limitation. Some *
296 * jurisdictions do not allow the exclusion or limitation of *
297 * incidental or consequential damages, so this exclusion and *
298 * limitation may not apply to You. *
299 * *
300 ************************************************************************
301
302 8. Litigation
303 -------------
304
305 Any litigation relating to this License may be brought only in the
306 courts of a jurisdiction where the defendant maintains its principal
307 place of business and such litigation shall be governed by laws of that
308 jurisdiction, without reference to its conflict-of-law provisions.
309 Nothing in this Section shall prevent a party's ability to bring
310 cross-claims or counter-claims.
311
312 9. Miscellaneous
313 ----------------
314
315 This License represents the complete agreement concerning the subject
316 matter hereof. If any provision of this License is held to be
317 unenforceable, such provision shall be reformed only to the extent
318 necessary to make it enforceable. Any law or regulation which provides
319 that the language of a contract shall be construed against the drafter
320 shall not be used to construe this License against a Contributor.
321
322 10. Versions of the License
323 ---------------------------
324
325 10.1. New Versions
326
327 Mozilla Foundation is the license steward. Except as provided in Section
328 10.3, no one other than the license steward has the right to modify or
329 publish new versions of this License. Each version will be given a
330 distinguishing version number.
331
332 10.2. Effect of New Versions
333
334 You may distribute the Covered Software under the terms of the version
335 of the License under which You originally received the Covered Software,
336 or under the terms of any subsequent version published by the license
337 steward.
338
339 10.3. Modified Versions
340
341 If you create software not governed by this License, and you want to
342 create a new license for such software, you may create and use a
343 modified version of this License if you rename the license and remove
344 any references to the name of the license steward (except to note that
345 such modified license differs from this License).
346
347 10.4. Distributing Source Code Form that is Incompatible With Secondary
348 Licenses
349
350 If You choose to distribute Source Code Form that is Incompatible With
351 Secondary Licenses under the terms of this version of the License, the
352 notice described in Exhibit B of this License must be attached.
353
354 Exhibit A - Source Code Form License Notice
355 -------------------------------------------
356
357 This Source Code Form is subject to the terms of the Mozilla Public
358 License, v. 2.0. If a copy of the MPL was not distributed with this
359 file, You can obtain one at http://mozilla.org/MPL/2.0/.
360
361 If it is not possible or desirable to put the notice in a particular
362 file, then You may include the notice in a location (such as a LICENSE
363 file in a relevant directory) where a recipient would be likely to look
364 for such a notice.
365
366 You may add additional accurate notices of copyright ownership.
367
368 Exhibit B - "Incompatible With Secondary Licenses" Notice
369 ---------------------------------------------------------
370
371 This Source Code Form is "Incompatible With Secondary Licenses", as
372 defined by the Mozilla Public License, v. 2.0.
0 # Pure Golang NMSG Library
1
2 `go-nmsg` is a pure go implementation of the NMSG container and payload
3 format used by the C (nmsg)[https://github.com/farsightsec/nmsg] toolkit
4 and library.
5
6 ## Synopsis
7
8 import "github.com/farsightsec/go-nmsg"
9 import "github.com/farsightsec/go-nmsg/nmsg_base"
10
11 var r io.Reader
12 var w io.Writer
13 ...
14 input := nmsg.NewInput(r, mtu)
15 output := nmsg.BufferedOutput(w)
16 output.SetMaxSize(nmsg.MaxContainerSize, 0)
17
18 for {
19 payload, err := inp.Recv()
20 if err != nil {
21 if nmsg.IsDataError(err) {
22 continue
23 }
24 break
25 }
26 message := payload.Message()
27
28 switch message.(type) {
29 case *nmsg_base.Dnstap:
30 // process dnstap
31 // write copy to output
32 output.Send(payload)
33 }
34 }
35
36 output.Close()
37
38
39 ## Requirements
40
41 `go-nmsg` requires the following open source libraries:
42
43 "github.com/golang/protobuf/proto"
44 "github.com/dnstap/golang-dnstap"
45
46 ## Limitations
47
48 `go-nmsg` can pack and unpack the protobuf structure of an NMSG payload,
49 and the protobuf structure of the data contained in the payload. It does
50 not implement the full functionality of the C libnmsg message
51 modules, such as:
52
53 * Advanced field types (e.g., a protobuf []byte as an IP address)
54 * Generated fields
55 * Formatting of fields for presentation and JSON output
56
57 Applications needing such functionality in go should use the
58 `cgo-nmsg` package included in this distribution under:
59
60 "github.com/farsightsec/go-nmsg/cgo-nmsg"
0 # Golang bindings for NMSG
1
2 `cgo-nmsg` provides Golang bindings to the C libnmsg library.
3
4 The NMSG network message encapsulation library format is an efficient
5 encoding of typed, structured data into payloads which are packed into
6 containers which can be transmitted over the network or stored to disk.
7 For more information, see https://github.com/farsightsec/nmsg/.
8
9 A pure but limited Golang NMSG library is available with `go-nmsg`.
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <nmsg.h>
14 #include <stdlib.h>
15 */
16 import "C"
17 import (
18 "fmt"
19 "runtime"
20 "sync"
21 "unsafe"
22 )
23
24 type outCbEntry struct {
25 index int
26 Output
27 }
28
29 type inCbEntry struct {
30 index int
31 Input
32 }
33
34 var cbm sync.Mutex
35 var outCbTable []Output
36 var inCbTable []Input
37
38 // The C library may not hold a pointer to a Go variable, but we
39 // need to store enough context in the callback user data to find
40 // the go object which registered the callback. We solve this by
41 // allocating memory on the C side (with C.malloc, C.calloc) and
42 // storing a value in that memory which we can use to look up the
43 // Go value on the Go side.
44 //
45 // The approach we take here is to have a package-global list of
46 // Output and Input, and store the index in the list as a C.int
47 // in C-allocated memory. The location of this memory is returned
48 // as an unsafe.Pointer suitable for passing to the (void *user)
49 // argument of libnmsg callback registration functions.
50
51 func registerOutput(o Output) unsafe.Pointer {
52 cbm.Lock()
53 defer cbm.Unlock()
54 idx := len(outCbTable)
55 outCbTable = append(outCbTable, o)
56 idxptr := C.calloc(C.size_t(1), C.size_t(unsafe.Sizeof(C.int(1))))
57 *(*C.int)(idxptr) = C.int(idx)
58 return idxptr
59 }
60
61 func registerInput(i Input) unsafe.Pointer {
62 cbm.Lock()
63 defer cbm.Unlock()
64 idx := len(inCbTable)
65 inCbTable = append(inCbTable, i)
66 idxptr := C.calloc(C.size_t(1), C.size_t(unsafe.Sizeof(C.int(1))))
67 *(*C.int)(idxptr) = C.int(idx)
68 return idxptr
69 }
70
71 //export outputCallback
72 func outputCallback(msg C.nmsg_message_t, user unsafe.Pointer) {
73 idx := int(*(*C.int)(user))
74 if idx < len(outCbTable) {
75 o := outCbTable[idx]
76 o.Write(messageFromC(msg))
77 return
78 }
79 panic(fmt.Sprintf("outputCallback: invalid index %d", idx))
80 }
81
82 //export inputCallback
83 func inputCallback(msg, user unsafe.Pointer) C.nmsg_res {
84 idx := int(*(*C.int)(user))
85 if idx < len(inCbTable) {
86 i := inCbTable[idx]
87 for {
88 m, err := i.Read()
89
90 if ErrorRetry(err) {
91 continue
92 }
93 if err != nil {
94 *(*C.nmsg_message_t)(msg) = nil
95 if e, ok := err.(nmsgResError); ok {
96 return C.nmsg_res(e)
97 }
98 return C.nmsg_res_failure
99 }
100 runtime.SetFinalizer(m, nil)
101 *(*C.nmsg_message_t)(msg) = m.message
102 return C.nmsg_res_success
103 }
104 }
105 panic(fmt.Sprintf("inputCallback: invalid index %d", idx))
106 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <nmsg.h>
14 #include <stdlib.h>
15 */
16 import "C"
17 import (
18 "crypto/rand"
19 "encoding/binary"
20 "io"
21 "runtime"
22 "sync"
23 "unsafe"
24 )
25
26 // A Container is a collection of NMSG payloads with a target size.
27 type Container struct {
28 config ContainerConfig
29 sequenceID uint64
30 sequenceNumber uint32
31 container C.nmsg_container_t
32 }
33
34 // ContainerConfig contains
35 type ContainerConfig struct {
36 Compress bool
37 Sequence bool
38 Size int
39 }
40
41 // NewContainer creates a container with the given target size.
42 func NewContainer(conf *ContainerConfig) *Container {
43 c := &Container{config: *conf, container: C.nmsg_container_init(C.size_t(conf.Size))}
44 runtime.SetFinalizer(c, func(c *Container) {
45 C.nmsg_container_destroy(&c.container)
46 })
47 if conf.Sequence {
48 C.nmsg_container_set_sequence(c.container, C.bool(true))
49 binary.Read(rand.Reader, binary.BigEndian, &c.sequenceID)
50 }
51 return c
52 }
53
54 // ErrorFull returns true if the container is full. If the Container Add()
55 // method returns such an error, the message will need to be added to the
56 // next container.
57 func ErrorFull(err error) bool {
58 t, ok := err.(nmsgResError)
59 return ok && t == nmsgResError(C.nmsg_res_container_full)
60 }
61
62 // ErrorOverfull returns true if the container contains a single payload
63 // and its size is greater than the target size.
64 func ErrorOverfull(err error) bool {
65 t, ok := err.(nmsgResError)
66 return ok && t == nmsgResError(C.nmsg_res_container_overfull)
67 }
68
69 // Add adds the supplied Message to the Container.
70 func (c *Container) Add(m *Message) error {
71 return nmsgError(C.nmsg_container_add(c.container, m.message))
72 }
73
74 // Bytes returns the serialized container and resets the container.
75 func (c *Container) Bytes() []byte {
76 var pbuf *C.uint8_t
77 var pbufLen C.size_t
78 res := C.nmsg_container_serialize(c.container,
79 &pbuf, &pbufLen,
80 C.bool(true),
81 C.bool(c.config.Compress),
82 C.uint32_t(c.sequenceNumber),
83 C.uint64_t(c.sequenceID),
84 )
85 defer C.free(unsafe.Pointer(pbuf))
86 if err := nmsgError(res); err != nil {
87 return nil
88 }
89 c.sequenceID++
90 C.nmsg_container_destroy(&c.container)
91 c.container = C.nmsg_container_init(C.size_t(c.config.Size))
92 if c.config.Sequence {
93 C.nmsg_container_set_sequence(c.container, C.bool(true))
94 }
95
96 return C.GoBytes(unsafe.Pointer(pbuf), C.int(pbufLen))
97 }
98
99 // UnpackContainer returns the messages the container contains.
100 func UnpackContainer(b []byte) ([]*Message, error) {
101 var msgarray *C.nmsg_message_t
102 var nmsgs C.size_t
103
104 res := C.nmsg_container_deserialize(
105 (*C.uint8_t)(unsafe.Pointer(&b[0])),
106 C.size_t(len(b)),
107 &msgarray,
108 &nmsgs)
109 if err := nmsgError(res); err != nil {
110 return nil, err
111 }
112 msgs := make([]*Message, 0, int(nmsgs))
113 p := unsafe.Pointer(msgarray)
114 for i := 0; i < int(nmsgs); i++ {
115 mp := unsafe.Pointer(uintptr(p) + uintptr(i)*unsafe.Sizeof(*msgarray))
116 msgs = append(msgs, messageFromC(*(*C.nmsg_message_t)(mp)))
117 }
118
119 C.free(unsafe.Pointer(msgarray))
120 return msgs, nil
121 }
122
123 // A ContainerOutput writes containers to a generic io.Writer. No fragmentation
124 // of oversize containers is performed.
125 type containerOutput struct {
126 mu sync.Mutex
127 w io.Writer
128 c *Container
129 rate *Rate
130 buffered bool
131 empty bool
132 filtervendor uint32
133 filtermsgtype uint32
134 source uint32
135 operator uint32
136 group uint32
137 }
138
139 // NewContainerOutput creates a ContainerOutput writing to the supplied
140 // io.Writer with the given buffer size.
141 func newContainerOutput(w io.Writer, size int) *containerOutput {
142 return &containerOutput{
143 c: NewContainer(&ContainerConfig{
144 Size: size,
145 Sequence: true,
146 }),
147 buffered: true,
148 empty: true,
149 w: w,
150 }
151 }
152
153 func (co *containerOutput) Write(m *Message) error {
154 for {
155 vid, msgtype := m.GetMsgtype()
156 if co.filtervendor > 0 && co.filtervendor != vid {
157 return nil
158 }
159 if co.filtermsgtype > 0 && co.filtermsgtype != msgtype {
160 return nil
161 }
162 if co.source > 0 {
163 m.SetSource(co.source)
164 }
165 if co.operator > 0 {
166 m.SetOperator(co.operator)
167 }
168 if co.group > 0 {
169 m.SetGroup(co.group)
170 }
171
172 co.mu.Lock()
173 err := co.c.Add(m)
174 if co.buffered && err == nil {
175 co.empty = false
176 co.mu.Unlock()
177 return nil
178 }
179 _, werr := co.w.Write(co.c.Bytes())
180 co.empty = true
181 r := co.rate
182 co.mu.Unlock()
183 if r != nil {
184 r.Sleep()
185 }
186 if werr == nil && ErrorFull(err) {
187 continue
188 }
189 return werr
190 }
191 }
192
193 // SetFilterMsgtype instructs the output to only accept Messages
194 // with the given vendor and messagetype, specified by id.
195 func (co *containerOutput) SetFilterMsgtype(vendor, msgtype uint32) {
196 co.filtervendor = vendor
197 co.filtermsgtype = msgtype
198 }
199
200 // SetFilterMsgtypeByname instructs the output to only accept Messages
201 // with the given vendor and messagetype, specified by name.
202 func (co *containerOutput) SetFilterMsgtypeByname(vendor, msgtype string) {
203 cvendor := C.CString(vendor)
204 cmsgtype := C.CString(msgtype)
205 defer C.free(unsafe.Pointer(cvendor))
206 defer C.free(unsafe.Pointer(cmsgtype))
207 cvid := C.nmsg_msgmod_vname_to_vid(cvendor)
208 co.filtervendor = uint32(cvid)
209 co.filtermsgtype = uint32(C.nmsg_msgmod_mname_to_msgtype(cvid, cmsgtype))
210 }
211
212 func (co *containerOutput) SetRate(r *Rate) {
213 co.mu.Lock()
214 co.rate = r
215 co.mu.Unlock()
216 }
217
218 func (co *containerOutput) SetSource(source uint32) {
219 co.source = source
220 }
221
222 func (co *containerOutput) SetOperator(op uint32) {
223 co.operator = op
224 }
225
226 func (co *containerOutput) SetGroup(group uint32) {
227 co.group = group
228 }
229
230 // Flush writes any buffered output to the underlying writer.
231 func (co *containerOutput) Flush() error {
232 co.mu.Lock()
233 written := false
234 defer func() {
235 r := co.rate
236 co.mu.Unlock()
237 if written && r != nil {
238 r.Sleep()
239 }
240 }()
241 if !co.empty {
242 _, werr := co.w.Write(co.c.Bytes())
243 co.empty = true
244 written = true
245 return werr
246 }
247 return nil
248 }
249
250 // SetBuffered controls whether the ContainerOutput collects
251 // multiple messages into a container (buffered == true, the
252 // default), or sends a container per message (buffered == false).
253 func (co *containerOutput) SetBuffered(buffered bool) {
254 co.buffered = buffered
255 }
256
257 // SetCompression controls whether the containers are compressed
258 // before sending.
259 func (co *containerOutput) SetCompression(compress bool) {
260 co.c.config.Compress = compress
261 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <nmsg.h>
14 */
15 import "C"
16
17 // NmsgError encapsulates an error condition
18 type nmsgResError C.nmsg_res
19
20 func (n nmsgResError) Error() string {
21 return C.GoString(C.nmsg_res_lookup(uint32(n)))
22 }
23
24 func nmsgError(res C.nmsg_res) error {
25 if res == C.nmsg_res_success {
26 return nil
27 }
28 return nmsgResError(res)
29 }
30
31 // ErrorRetry returns true if the error indicates that the nmsg
32 // operation should be retried.
33 func ErrorRetry(err error) bool {
34 if ne, ok := err.(nmsgResError); ok {
35 return ne == nmsgResError(C.nmsg_res_again)
36 }
37 return false
38 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <stdlib.h>
14 #include <nmsg.h>
15
16 extern nmsg_res inputCallback(nmsg_message_t *msg, void *user);
17
18 nmsg_res input_callback(nmsg_message_t *msg, void *user) {
19 return inputCallback(msg, user);
20 }
21 */
22 import "C"
23 import (
24 "io"
25 "net"
26 "os"
27 "unsafe"
28 )
29
30 // An Input is a source of NMSG payloads (Messages).
31 type Input interface {
32 // Read returns a Message or nil, and an error if any.
33 Read() (*Message, error)
34
35 // SetFilterMsgtype instructs the input to discard all Messages
36 // not of the given vendor id and msgtype, specified by number.
37 SetFilterMsgtype(vendor, msgtype uint32)
38
39 // SetFilterMsgtypeByname instructs the input to discard all Messages
40 // not of the given vendor id and msgtype, specified by name.
41 SetFilterMsgtypeByname(vendor, msgtype string)
42
43 // SetFilterSource instructs the input to discard all Messages not
44 // from the supplied source.
45 SetFilterSource(source uint32)
46
47 // SetFilterOperator instructs the input to discard all Messages not
48 // from the supplied operator.
49 SetFilterOperator(operator uint32)
50
51 // SetFilterGroup instructs the input to discard all Messages not
52 // in the supplied group.
53 SetFilterGroup(group uint32)
54 }
55
56 // NmsgInput is an Input managed by libnmsg. It satisfies
57 // the Input interface, and has
58 type nmsgInput struct {
59 file *os.File
60 input C.nmsg_input_t
61 }
62
63 func (i *nmsgInput) Read() (*Message, error) {
64 var msg C.nmsg_message_t
65 res := C.nmsg_input_read(i.input, &msg)
66 if res == C.nmsg_res_success {
67 return messageFromC(msg), nil
68 }
69 return nil, nmsgError(res)
70 }
71
72 func (i *nmsgInput) SetFilterMsgtype(vid, msgtype uint32) {
73 C.nmsg_input_set_filter_msgtype(i.input, C.uint(vid), C.uint(msgtype))
74 }
75
76 func (i *nmsgInput) SetFilterMsgtypeByname(vendor, msgtype string) {
77 cname := C.CString(vendor)
78 ctype := C.CString(msgtype)
79 C.nmsg_input_set_filter_msgtype_byname(i.input, cname, ctype)
80 C.free(unsafe.Pointer(cname))
81 C.free(unsafe.Pointer(ctype))
82 }
83
84 func (i *nmsgInput) SetFilterSource(source uint32) {
85 C.nmsg_input_set_filter_source(i.input, C.uint(source))
86 }
87
88 func (i *nmsgInput) SetFilterOperator(operator uint32) {
89 C.nmsg_input_set_filter_operator(i.input, C.uint(operator))
90 }
91
92 func (i *nmsgInput) SetFilterGroup(group uint32) {
93 C.nmsg_input_set_filter_group(i.input, C.uint(group))
94 }
95
96 // NewInput creates a new Input from an io.Reader.
97 // Currently, the reader must be a *net.UDPConn or a *os.File
98 func NewInput(r io.Reader) Input {
99 switch r := r.(type) {
100 case *net.UDPConn:
101 f, err := r.File()
102 if err != nil {
103 return nil
104 }
105 return &nmsgInput{f, C.nmsg_input_open_sock(C.int(f.Fd()))}
106 case *os.File:
107 return &nmsgInput{r, C.nmsg_input_open_file(C.int(r.Fd()))}
108 default:
109 return nil
110 // return &containerReader{Reader: r}
111 }
112 }
113
114 // NewCallbackInput creates an NmsgInput which calls the supplied InputFunc.
115 func NewCallbackInput(i InputFunc) Input {
116 return &nmsgInput{
117 file: nil,
118 input: C.nmsg_input_open_callback(C.nmsg_cb_message_read(C.input_callback), registerInput(i)),
119 }
120 }
121
122 // An InputFunc is a function with the same signature as Input.Read(), usable
123 // directly as an Input.
124 //
125 // When used directly as an Input, only the Read() method is implemented. All
126 // others are no-ops. If the functionality of the other methods is desired,
127 // the InputFunc can be passed to NewCallbackInput.
128 type InputFunc func() (*Message, error)
129
130 // Read calls the underlying function to return the next message.
131 func (i InputFunc) Read() (*Message, error) { return i() }
132
133 // SetFilterMsgtype satisfies the Input interface with a no-op
134 func (i InputFunc) SetFilterMsgtype(vendor, msgtype uint32) {}
135
136 // SetFilterMsgtypeByname satisfies the Input interface with a no-op
137 func (i InputFunc) SetFilterMsgtypeByname(vendor, msgtype string) {}
138
139 // SetFilterSource satisfies the Input interface with a no-op
140 func (i InputFunc) SetFilterSource(source uint32) {}
141
142 // SetFilterOperator satisfies the Input interface with a no-op
143 func (i InputFunc) SetFilterOperator(operator uint32) {}
144
145 // SetFilterGroup satisfies the Input interface with a no-op
146 func (i InputFunc) SetFilterGroup(group uint32) {}
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <stdlib.h>
14 #include <nmsg.h>
15 */
16 import "C"
17 import "unsafe"
18
19 // IO is a handle to a libnmsg io loop connecting one or more Inputs
20 // with one ore more Outputs.
21 type IO struct {
22 nmsgIO C.nmsg_io_t
23 }
24
25 // NewIO creates and returns a new IO
26 func NewIO() *IO {
27 io := C.nmsg_io_init()
28 if io != nil {
29 return &IO{io}
30 }
31 return nil
32 }
33
34 // AddInputChannel opens an NMSG channel and adds it as an Input to the
35 // IO.
36 func (io *IO) AddInputChannel(channel string) error {
37 cchan := C.CString(channel)
38 res := C.nmsg_io_add_input_channel(io.nmsgIO, cchan, nil)
39 C.free(unsafe.Pointer(cchan))
40 return nmsgError(res)
41 }
42
43 // AddInputSockSpec opens one or more sockets based on the sockspec
44 // (add/port ,or addr/lowport..highport) and adds it to the IO
45 // as an input.
46 func (io *IO) AddInputSockSpec(sockspec string) error {
47 css := C.CString(sockspec)
48 res := C.nmsg_io_add_input_sockspec(io.nmsgIO, css, nil)
49 C.free(unsafe.Pointer(css))
50 return nmsgError(res)
51 }
52
53 // AddInput adds a separately created Input to the IO as an input.
54 func (io *IO) AddInput(i Input) error {
55 ni, ok := i.(*nmsgInput)
56 if !ok {
57 ni = NewCallbackInput(i.Read).(*nmsgInput)
58 }
59 return nmsgError(C.nmsg_io_add_input(io.nmsgIO, ni.input, nil))
60 }
61
62 // AddOutput adds a separately created Output to the IO as an output.
63 func (io *IO) AddOutput(o Output) error {
64 nout, ok := o.(*nmsgOutput)
65 if !ok {
66 nout = NewCallbackOutput(o.Write).(*nmsgOutput)
67 }
68 return nmsgError(C.nmsg_io_add_output(io.nmsgIO, nout.output, nil))
69 }
70
71 // SetMirrored controls whether the IO mirrors output to all outputs
72 // (mirrored = true) or stripes its output across all outputs.
73 func (io *IO) SetMirrored(mirrored bool) {
74 if mirrored {
75 C.nmsg_io_set_output_mode(io.nmsgIO, C.nmsg_io_output_mode_mirror)
76 return
77 }
78 C.nmsg_io_set_output_mode(io.nmsgIO, C.nmsg_io_output_mode_stripe)
79 }
80
81 // SetDebug sets the debug print level of the underlying io.
82 // Larger numbers are more verbose.
83 func (io *IO) SetDebug(debug int) {
84 C.nmsg_io_set_debug(io.nmsgIO, C.int(debug))
85 }
86
87 // Run starts the IO loop, returning when it is finished or broken
88 // with Break()
89 func (io *IO) Run() error {
90 return nmsgError(C.nmsg_io_loop(io.nmsgIO))
91 }
92
93 // Break stops the IO main loop.
94 func (io *IO) Break() {
95 C.nmsg_io_breakloop(io.nmsgIO)
96 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <stdlib.h>
14 #include <nmsg.h>
15
16 const char *endline="\n";
17 unsigned flag_repeated = NMSG_MSGMOD_FIELD_REPEATED;
18 */
19 import "C"
20 import (
21 "fmt"
22 "net"
23 "runtime"
24 "unsafe"
25 )
26
27 // MessageMod something something
28 type MessageMod struct {
29 nmsgMsgMod C.nmsg_msgmod_t
30 }
31
32 // MessageModLookupByName something something
33 func MessageModLookupByName(vname, mname string) *MessageMod {
34 vstr := C.CString(vname)
35 mstr := C.CString(mname)
36 defer C.free(unsafe.Pointer(vstr))
37 defer C.free(unsafe.Pointer(mstr))
38 return &MessageMod{C.nmsg_msgmod_lookup_byname(vstr, mstr)}
39 }
40
41 // MessageModLookup something something
42 func MessageModLookup(v, m uint32) *MessageMod {
43 return &MessageMod{C.nmsg_msgmod_lookup(C.uint(v), C.uint(m))}
44 }
45
46 // A Message is a unit of NMSG data.
47 type Message struct {
48 message C.nmsg_message_t
49 }
50
51 // NewMessage initializes a message of a type given by
52 // the supplied MessageMod
53 func NewMessage(mod *MessageMod) *Message {
54 return messageFromC(C.nmsg_message_init(mod.nmsgMsgMod))
55 }
56
57 // NewMessageFromPayload encapsulates a byte buffer in a payload with
58 // the supplied vendor and message type.
59 func NewMessageFromPayload(payload []byte, vendor uint32, msgtype uint32) *Message {
60 Csiz := C.size_t(len(payload))
61 // C.CString allocates a buffer to hold the copy of payload
62 // built by string. This buffer is passed to nmsg_message_from_raw_payload,
63 // which takes ownership of the buffer. It will be freed when
64 // nmsg_message_destroy() is called by the Message finalizer.
65 Cbuf := unsafe.Pointer(C.CString(string(payload)))
66 return messageFromC(C.nmsg_message_from_raw_payload(
67 C.unsigned(vendor), C.unsigned(msgtype),
68 (*C.uint8_t)(Cbuf), Csiz, nil))
69 }
70
71 func messageDestroy(m *Message) {
72 C.nmsg_message_destroy(&m.message)
73 }
74
75 // GetMsgtype returns the vendor and payload type of the message.
76 func (msg *Message) GetMsgtype() (vendor, msgtype uint32) {
77 vendor = uint32(C.nmsg_message_get_vid(msg.message))
78 msgtype = uint32(C.nmsg_message_get_msgtype(msg.message))
79 return
80 }
81
82 // Source returns the source id of the message, or zero if the source id
83 // is not set.
84 func (msg *Message) Source() uint32 {
85 return uint32(C.nmsg_message_get_source(msg.message))
86 }
87
88 // SetSource sets the source id of the message.
89 func (msg *Message) SetSource(source uint32) {
90 C.nmsg_message_set_source(msg.message, C.uint32_t(source))
91 }
92
93 // Operator returns the operator id of the message, or zero if the operator id
94 // is not set.
95 func (msg *Message) Operator() uint32 {
96 return uint32(C.nmsg_message_get_operator(msg.message))
97 }
98
99 // SetOperator sets the operator id of the message.
100 func (msg *Message) SetOperator(operator uint32) {
101 C.nmsg_message_set_operator(msg.message, C.uint32_t(operator))
102 }
103
104 // Group returns the group id of the message, or zero if the group id
105 // is not set.
106 func (msg *Message) Group() uint32 {
107 return uint32(C.nmsg_message_get_group(msg.message))
108 }
109
110 // SetGroup sets the group id of the message.
111 func (msg *Message) SetGroup(group uint32) {
112 C.nmsg_message_set_group(msg.message, C.uint32_t(group))
113 }
114
115 func messageFromC(message C.nmsg_message_t) *Message {
116 msg := &Message{message}
117 runtime.SetFinalizer(msg, messageDestroy)
118 return msg
119 }
120
121 // MarshalJSON formats a JSON representation of the Message
122 func (msg *Message) MarshalJSON() ([]byte, error) {
123 var jsonCstr *C.char
124 err := nmsgError(C.nmsg_message_to_json(msg.message, &jsonCstr))
125 defer C.free(unsafe.Pointer(jsonCstr))
126 if err != nil {
127 return nil, err
128 }
129 return []byte(C.GoString(jsonCstr)), nil
130 }
131
132 // UnmarshalJSON parses a JSON representation of the Message
133 func (msg *Message) UnmarshalJSON(b []byte) error {
134 jsonCstr := C.CString(string(b))
135 defer C.free(unsafe.Pointer(jsonCstr))
136 return nmsgError(C.nmsg_message_from_json(jsonCstr, &msg.message))
137 }
138
139 // MarshalText converts a Message to presentation format.
140 func (msg *Message) MarshalText() ([]byte, error) {
141 var presCstr *C.char
142 err := nmsgError(C.nmsg_message_to_pres(msg.message, &presCstr, C.endline))
143 defer C.free(unsafe.Pointer(presCstr))
144 if err != nil {
145 return nil, err
146 }
147 return []byte(C.GoString(presCstr)), nil
148 }
149
150 // Enum contains both the numeric Value and the string Description of
151 // an enumerated NMSG field value.
152 type Enum struct {
153 Value uint32
154 Description string
155 }
156
157 type fieldValue struct {
158 typ C.nmsg_msgmod_field_type
159 buf unsafe.Pointer
160 size C.int
161 }
162
163 func (msg *Message) getFieldValue(name string, idx int) (fv fieldValue, err error) {
164 var Csize C.size_t
165
166 Cname := C.CString(name)
167 defer C.free(unsafe.Pointer(Cname))
168
169 Cidx := C.uint(uint(idx))
170
171 res := C.nmsg_message_get_field_type(msg.message, Cname, &fv.typ)
172 if err = nmsgError(res); err != nil {
173 return
174 }
175
176 res = C.nmsg_message_get_field(msg.message, Cname, Cidx, &fv.buf, &Csize)
177 if err = nmsgError(res); err != nil {
178 return
179 }
180
181 fv.size = C.int(Csize)
182 return
183 }
184
185 func (msg *Message) setFieldValue(name string, idx int, buf unsafe.Pointer, size int) error {
186 Cname := C.CString(name)
187 defer C.free(unsafe.Pointer(Cname))
188
189 Cidx := C.uint(uint(idx))
190 Csize := C.size_t(size)
191 return nmsgError(C.nmsg_message_set_field(msg.message, Cname, Cidx,
192 (*C.uint8_t)(buf), Csize))
193 }
194
195 // GetUintField retrieves the named field of a unsigned int type from a Message.
196 // If the field has an enumerated type, the numeric value is retrieved.
197 func (msg *Message) GetUintField(name string, idx int) (uint64, error) {
198 fv, err := msg.getFieldValue(name, idx)
199 if err != nil {
200 return 0, err
201 }
202
203 switch fv.typ {
204 case C.nmsg_msgmod_ft_uint16:
205 return uint64(*(*uint16)(fv.buf)), nil
206 case C.nmsg_msgmod_ft_uint32:
207 fallthrough
208 case C.nmsg_msgmod_ft_enum:
209 return uint64(*(*uint32)(fv.buf)), nil
210 case C.nmsg_msgmod_ft_uint64:
211 return *(*uint64)(fv.buf), nil
212 default:
213 return 0, fmt.Errorf("Field %s not of uint type", name)
214 }
215
216 }
217
218 // SetUintField sets the value of a field of type uint16, uint32, or uint64.
219 // The bitsize parameter specifies which type, and must be 16, 32, or 64
220 func (msg *Message) SetUintField(name string, idx, bitsize int, val uint64) error {
221 switch bitsize {
222 case 16:
223 v := uint16(val)
224 return msg.setFieldValue(name, idx, unsafe.Pointer(&v), bitsize)
225 case 32:
226 v := uint32(val)
227 return msg.setFieldValue(name, idx, unsafe.Pointer(&v), bitsize)
228 case 64:
229 v := uint64(val)
230 return msg.setFieldValue(name, idx, unsafe.Pointer(&v), bitsize)
231 default:
232 return fmt.Errorf("Invalid bitsize %d", bitsize)
233 }
234 }
235
236 // GetIntField retrieves the value of a named field of integer type from
237 // a Message.
238 func (msg *Message) GetIntField(name string, idx int) (int64, error) {
239 fv, err := msg.getFieldValue(name, idx)
240 if err != nil {
241 return 0, err
242 }
243
244 switch fv.typ {
245 case C.nmsg_msgmod_ft_int16:
246 return int64(*(*int16)(fv.buf)), nil
247 case C.nmsg_msgmod_ft_int32:
248 return int64(*(*int32)(fv.buf)), nil
249 case C.nmsg_msgmod_ft_int64:
250 return *(*int64)(fv.buf), nil
251 default:
252 return 0, fmt.Errorf("Field %s not of int type", name)
253 }
254 }
255
256 // SetIntField sets the value of an int16, int32, or int64 field in the message.
257 // The bitsize field specifies which size, and must by 16, 32, or 64
258 func (msg *Message) SetIntField(name string, idx, bitsize int, val int64) error {
259 switch bitsize {
260 case 16:
261 v := int16(val)
262 return msg.setFieldValue(name, idx, unsafe.Pointer(&v), bitsize)
263 case 32:
264 v := int32(val)
265 return msg.setFieldValue(name, idx, unsafe.Pointer(&v), bitsize)
266 case 64:
267 v := int64(val)
268 return msg.setFieldValue(name, idx, unsafe.Pointer(&v), bitsize)
269 default:
270 return fmt.Errorf("Invalid bitsize %d", bitsize)
271 }
272 }
273
274 // GetBytesField retrieves a field of type bytes from a Message.
275 func (msg *Message) GetBytesField(name string, idx int) ([]byte, error) {
276 fv, err := msg.getFieldValue(name, idx)
277 if err != nil {
278 return nil, err
279 }
280 if fv.typ != C.nmsg_msgmod_ft_bytes {
281 return nil, fmt.Errorf("Field %s not of bytes type", name)
282 }
283 return C.GoBytes(fv.buf, fv.size), nil
284 }
285
286 // SetBytesField sets the value of a bytes field in a Message
287 func (msg *Message) SetBytesField(name string, idx int, val []byte) error {
288 Cbuf := unsafe.Pointer(&val[0])
289 return msg.setFieldValue(name, idx, Cbuf, len(val))
290 }
291
292 // GetStringField retrieves the value of a string field in a Message
293 func (msg *Message) GetStringField(name string, idx int) (string, error) {
294 fv, err := msg.getFieldValue(name, idx)
295 if err != nil {
296 return "", err
297 }
298 return C.GoStringN((*C.char)(fv.buf), fv.size), nil
299 }
300
301 // SetStringField sets the value of a string field in a Message
302 func (msg *Message) SetStringField(name string, idx int, val string) error {
303 b := []byte(val)
304 Cbuf := unsafe.Pointer(&b[0])
305 return msg.setFieldValue(name, idx, Cbuf, len(val))
306 }
307
308 // GetIPField retrieves the value of an IP field in a Message
309 func (msg *Message) GetIPField(name string, idx int) (net.IP, error) {
310 fv, err := msg.getFieldValue(name, idx)
311 if err != nil {
312 return nil, err
313 }
314 if fv.typ != C.nmsg_msgmod_ft_ip {
315 return nil, fmt.Errorf("Field %s not of iptype", name)
316 }
317 return net.IP(C.GoBytes(fv.buf, fv.size)), nil
318 }
319
320 // SetIPField sets the value of an IP field in a Message
321 func (msg *Message) SetIPField(name string, idx int, val net.IP) error {
322 Cbuf := unsafe.Pointer(&val[0])
323 return msg.setFieldValue(name, idx, Cbuf, len(val))
324 }
325
326 // GetDoubleField retrieves the value of a double field in a Message
327 func (msg *Message) GetDoubleField(name string, idx int) (float64, error) {
328 fv, err := msg.getFieldValue(name, idx)
329 if err != nil {
330 return 0, err
331 }
332 if fv.typ != C.nmsg_msgmod_ft_double {
333 return 0, fmt.Errorf("Field %s is not of double type", name)
334 }
335 return *(*float64)(fv.buf), nil
336 }
337
338 // SetDoubleField sets the value of a double field in a Message
339 func (msg *Message) SetDoubleField(name string, idx int, val float64) error {
340 Cbuf := unsafe.Pointer(&val)
341 return msg.setFieldValue(name, idx, Cbuf, 8)
342 }
343
344 // GetEnumField returns the string description of a Message field
345 // with an enumerated type.
346 func (msg *Message) GetEnumField(name string, idx int) (string, error) {
347 enumValue, err := msg.GetUintField(name, idx)
348 if err != nil {
349 return "", err
350 }
351
352 Cname := C.CString(name)
353 defer C.free(unsafe.Pointer(Cname))
354 var Ename *C.char
355 res := C.nmsg_message_enum_value_to_name(
356 msg.message, Cname, C.unsigned(enumValue),
357 &Ename,
358 )
359 if err = nmsgError(res); err != nil {
360 return "", err
361 }
362 return C.GoString(Ename), nil
363 }
364
365 // SetEnumField sets the value of the named Message field to the value
366 // corresponding to the supplied description.
367 func (msg *Message) SetEnumField(name string, idx int, vname string) error {
368 Cname := C.CString(name)
369 defer C.free(unsafe.Pointer(Cname))
370 Cvname := C.CString(vname)
371 defer C.free(unsafe.Pointer(Cvname))
372
373 var v C.uint
374 res := C.nmsg_message_enum_name_to_value(msg.message, Cname, Cvname, &v)
375 if err := nmsgError(res); err != nil {
376 return err
377 }
378 return msg.SetUintField(name, idx, 32, uint64(v))
379 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <nmsg.h>
14
15 int nmsg_wbufsiz_min = NMSG_WBUFSZ_MIN;
16 int nmsg_wbufsiz_max = NMSG_WBUFSZ_MAX;
17 int nmsg_wbufsiz_ether = NMSG_WBUFSZ_ETHER;
18 int nmsg_wbufsiz_jumbo = NMSG_WBUFSZ_JUMBO;
19 */
20 import "C"
21
22 func init() {
23 if C.nmsg_init() != C.nmsg_res_success {
24 panic("failed to initialize nmsg library")
25 }
26 }
27
28 // Buffer Size constants from libnmsg
29 var (
30 BufferSizeMax = int(C.nmsg_wbufsiz_max)
31 BufferSizeMin = int(C.nmsg_wbufsiz_min)
32 BufferSizeEther = int(C.nmsg_wbufsiz_ether)
33 BufferSizeJumbo = int(C.nmsg_wbufsiz_jumbo)
34 )
35
36 // SetDebug sets the debug print level for the nmsg library.
37 // Debugging messages are sent to stderr. Higher debug values
38 // increase verbosity.
39 func SetDebug(debug int) {
40 C.nmsg_set_debug(C.int(debug))
41 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <stdlib.h>
14 #include <nmsg.h>
15
16 extern void outputCallback(nmsg_message_t, void *);
17
18 void output_callback(nmsg_message_t msg, void *user) {
19 outputCallback(msg, user);
20 }
21 */
22 import "C"
23 import (
24 "io"
25 "net"
26 "os"
27 "unsafe"
28 )
29
30 // An Output is a destination for NMSG data (Messages)
31 type Output interface {
32 // Write sends the supplied message to the Output.
33 Write(*Message) error
34
35 // SetBuffered controls whether the output buffers Messages into containers
36 // before sending them. NmsgOutputs are buffered by default, but low volume
37 // sources may choose to turn this off to reduce latency.
38 SetBuffered(bool)
39
40 // SetCompression controls whether the output compresses
41 // the container data prior to sending.
42 SetCompression(bool)
43
44 // Flush writes any buffered data to the Output.
45 Flush() error
46
47 // SetFilterMsgtype instructs the output to discard all Messages
48 // not of the supplied vendor and type, specified by number.
49 SetFilterMsgtype(vendor, msgtype uint32)
50
51 // SetFilterMsgtypeByname instructs the output to discard all Messages
52 // not of the supplied vendor and type, specified by name.
53 SetFilterMsgtypeByname(vendor, msgtype string)
54
55 // SetRate sets an output rate limit. The rate is specified
56 // in containers per second, and is checked every freq pauses.
57 // The freq parameter should be about 10-15% of the rate.
58 SetRate(rate *Rate)
59
60 // SetSource instructs the output to set the source parameter
61 // of all outbound messages to the supplied value.
62 SetSource(source uint32)
63
64 // SetOperator instructs the output to set the operator parameter
65 // of all outbound messages to the supplied value.
66 SetOperator(group uint32)
67
68 // SetGroup instructs the output to set the group parameter
69 // of all outbound messages to the supplied value.
70 SetGroup(group uint32)
71 }
72
73 // An NmsgOutput is an output managed by the nmsg library.
74 type nmsgOutput struct {
75 file *os.File
76 rate *Rate
77 output C.nmsg_output_t
78 }
79
80 func (o *nmsgOutput) Write(m *Message) error {
81 return nmsgError(C.nmsg_output_write(o.output, m.message))
82 }
83
84 func (o *nmsgOutput) SetBuffered(buffered bool) {
85 C.nmsg_output_set_buffered(o.output, C.bool(buffered))
86 }
87
88 func (o *nmsgOutput) SetFilterMsgtype(vid, msgtype uint32) {
89 C.nmsg_output_set_filter_msgtype(o.output, C.uint(vid), C.uint(msgtype))
90 }
91
92 func (o *nmsgOutput) SetFilterMsgtypeByname(vendor, msgtype string) {
93 cname := C.CString(vendor)
94 ctype := C.CString(msgtype)
95 C.nmsg_output_set_filter_msgtype_byname(o.output, cname, ctype)
96 C.free(unsafe.Pointer(cname))
97 C.free(unsafe.Pointer(ctype))
98 }
99
100 func (o *nmsgOutput) SetRate(r *Rate) {
101 if r == nil {
102 C.nmsg_output_set_rate(o.output, nil)
103 } else {
104 C.nmsg_output_set_rate(o.output, r.rate)
105 }
106 // keep a reference to avoid calling the finalizer
107 o.rate = r
108 }
109
110 func (o *nmsgOutput) SetSource(source uint32) {
111 C.nmsg_output_set_source(o.output, C.uint(source))
112 }
113
114 func (o *nmsgOutput) SetOperator(operator uint32) {
115 C.nmsg_output_set_operator(o.output, C.uint(operator))
116 }
117
118 func (o *nmsgOutput) SetGroup(group uint32) {
119 C.nmsg_output_set_group(o.output, C.uint(group))
120 }
121
122 func (o *nmsgOutput) SetCompression(compress bool) {
123 C.nmsg_output_set_zlibout(o.output, C.bool(compress))
124 }
125
126 func (o *nmsgOutput) Flush() error {
127 return nmsgError(C.nmsg_output_flush(o.output))
128 }
129
130 // NewOutput creates an output writing to w, with target
131 // container size of bufsiz. The Writer currently must be a
132 // *os.File or *net.UDPConn.
133 func NewOutput(w io.Writer, bufsiz int) Output {
134 switch w := w.(type) {
135 case *net.UDPConn:
136 f, err := w.File()
137 if err != nil {
138 return nil
139 }
140 return &nmsgOutput{f, nil, C.nmsg_output_open_sock(C.int(f.Fd()), C.size_t(bufsiz))}
141 case *os.File:
142 return &nmsgOutput{w, nil, C.nmsg_output_open_file(C.int(w.Fd()), C.size_t(bufsiz))}
143 default:
144 return newContainerOutput(w, bufsiz)
145 }
146 }
147
148 // NewCallbackOutput creates an NmsgOutput which calls o.Send()
149 // on every message.
150 func NewCallbackOutput(o OutputFunc) Output {
151 return &nmsgOutput{
152 file: nil,
153 output: C.nmsg_output_open_callback(C.nmsg_cb_message(C.output_callback), registerOutput(o)),
154 }
155 }
156
157 // An OutputFunc is a function with the same signature as Output.Write, usable
158 // directly as an Output.
159 //
160 // When used directly as an Output, only the Write() method is defined. All others
161 // are no-ops.
162 type OutputFunc func(*Message) error
163
164 // Write calls the underlying function with the supplied message
165 func (o OutputFunc) Write(m *Message) error { return o(m) }
166
167 // Flush satisfies the Output interface with a no-op
168 func (o OutputFunc) Flush() error { return nil }
169
170 // SetBuffered satisfies the Output interface with a no-op
171 func (o OutputFunc) SetBuffered(bool) {}
172
173 // SetCompression satisfies the Output interface with a no-op
174 func (o OutputFunc) SetCompression(bool) {}
175
176 // SetFilterMsgtype satisfies the Output interface with a no-op
177 func (o OutputFunc) SetFilterMsgtype(vendor, msgtype uint32) {}
178
179 // SetFilterMsgtypeByname satisfies the Output interface with a no-op
180 func (o OutputFunc) SetFilterMsgtypeByname(vendor, msgtype string) {}
181
182 // SetRate satisfies the Output interface with a no-op
183 func (o OutputFunc) SetRate(r *Rate) {}
184
185 // SetSource satisfies the Output interface with a no-op
186 func (o OutputFunc) SetSource(source uint32) {}
187
188 // SetOperator satisfies the Output interface with a no-op
189 func (o OutputFunc) SetOperator(group uint32) {}
190
191 // SetGroup satisfies the Output interface with a no-op
192 func (o OutputFunc) SetGroup(group uint32) {}
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 /*
11 #cgo pkg-config: libnmsg
12 #cgo LDFLAGS: -lnmsg
13 #include <nmsg.h>
14 #include <stdlib.h>
15 */
16 import "C"
17 import "runtime"
18
19 // A Rate provides Rate limiting across one or more outputs.
20 type Rate struct{ rate C.nmsg_rate_t }
21
22 // NewRate initializes and returns a rate context. The rate parameter
23 // specifies the target rate of packets (containers and fragments) sent
24 // on all outputs using the Rate. The freq parameter specifies how often
25 // (in packets) to check the rate limit.
26 func NewRate(rate, freq uint) *Rate {
27 r := &Rate{C.nmsg_rate_init(C.uint(rate), C.uint(freq))}
28 runtime.SetFinalizer(r, func(r *Rate) {
29 C.nmsg_rate_destroy(&r.rate)
30 })
31 return r
32 }
33
34 // Sleep pauses for an appropriate amount of time to maintain the given
35 // output rate.
36 func (r *Rate) Sleep() {
37 C.nmsg_rate_sleep(r.rate)
38 }
0 // +build libxs
1
2 /*
3 * Copyright (c) 2017 by Farsight Security, Inc.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10 package nmsg
11
12 /*
13 #cgo pkg-config: libnmsg libxs
14 #cgo LDFLAGS: -lnmsg -lxs
15 #include <stdlib.h>
16 #include <nmsg.h>
17 #include <xs/xs.h>
18 */
19 import "C"
20 import "unsafe"
21
22 var xsContext unsafe.Pointer
23
24 func init() {
25 xsContext = C.xs_init()
26 }
27
28 // NewXSInput opens an Input reading from the given XS endpoint.
29 func NewXSInput(xep string) Input {
30 cxep := C.CString(xep)
31 defer C.free(unsafe.Pointer(cxep))
32 inp := C.nmsg_input_open_xs_endpoint(xsContext, cxep)
33 if inp == nil {
34 return nil
35 }
36 return &nmsgInput{input: inp}
37 }
38
39 // NewXSOutput creates an output writing to the given XS endpoint.
40 func NewXSOutput(xep string, bufsiz int) Output {
41 cxep := C.CString(xep)
42 defer C.free(unsafe.Pointer(cxep))
43 outp := C.nmsg_output_open_xs_endpoint(xsContext, cxep, C.size_t(bufsiz))
44 if outp == nil {
45 return nil
46 }
47 return &nmsgOutput{output: outp}
48 }
0 /*
1 * Copyright (c) 2017,2018 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 import (
11 "bytes"
12 "encoding/binary"
13 "errors"
14 "fmt"
15 "io"
16 "math/rand"
17
18 "github.com/golang/protobuf/proto"
19 )
20
21 const (
22 nmsgVersion = 2
23 nmsgFlagZlib = 1
24 nmsgFlagFragment = 2
25 headerSize = 10
26 )
27
28 var (
29 nmsgMagic = [4]byte{'N', 'M', 'S', 'G'}
30 errBadMagic = errors.New("Bad NMSG Magic Number")
31 u32max uint32 = (1 << 31)
32 containerOverhead = 10
33 fragmentOverhead = 10 + 4 + proto.Size(
34 &NmsgFragment{
35 Id: &u32max,
36 Current: &u32max,
37 Last: &u32max,
38 Crc: &u32max,
39 })
40 )
41
42 type containerHeader struct {
43 Magic [4]byte
44 Flags, Version byte
45 Length uint32
46 }
47
48 // isCompressed() and isFragmented() are helper functions for readability.
49 func (h *containerHeader) isCompressed() bool {
50 return h.Flags&nmsgFlagZlib != 0
51 }
52
53 func (h *containerHeader) isFragmented() bool {
54 return h.Flags&nmsgFlagFragment != 0
55 }
56
57 // A Container encapsulates an Nmsg envelope, and maintains metadata for
58 // sizing containers as payloads are added.
59 type Container struct {
60 // Maximum size of a container. AddPayload attempts to keep the container
61 // under this size.
62 maxSize int
63 // Maximum size of fragment or container. Any containers larger than this
64 // will be fragmented by WriteTo.
65 writeSize int
66 // If true, compress container contents before writing.
67 compress bool
68 // If true, container was populated from compressed data
69 // This is primarily used in fragment reassembly to detect whether the
70 // fragmented data was compressed prior to fragmentation.
71 isCompressed bool
72 // If nonzero, an estimate of the effectiveness of compression, expressed
73 // as compressedSize / uncompressedSize. Default: 0.5
74 compressionRatio float32
75 // The current estimated size of the serialized data, before compression
76 size int
77 Nmsg
78 *NmsgFragment
79 }
80
81 // NewContainer creates a new empty NMSG container.
82 func NewContainer() *Container {
83 c := &Container{size: containerOverhead}
84 c.SetMaxSize(0, 0)
85 return c
86 }
87
88 // SetMaxSize sets the maximum size (including Marshaling overhead,
89 // container header, and anticipated compression ratio) of a container.
90 // AddPayload attempts to keep the container within this size.
91 //
92 // writeSize specifies the maximum size of containers or fragments.
93 // Containers larger than writeSize will be written as fragments instead
94 // of single containers.
95 //
96 // A writeSize value of 0 is treated as equal to size.
97 func (c *Container) SetMaxSize(size, writeSize int) {
98 if size < MinContainerSize {
99 size = MinContainerSize
100 }
101 if size > MaxContainerSize {
102 size = MaxContainerSize
103 }
104 if writeSize < size {
105 writeSize = size
106 }
107 c.maxSize = size
108 c.writeSize = writeSize
109 }
110
111 // SetCompression instructs WriteTo to write containers with compressed
112 // (if true) or uncompressed (if false) contents.
113 func (c *Container) SetCompression(compress bool) {
114 c.compress = compress
115 }
116
117 // SetCompressionRatio sets an estimated compression ratio for the data.
118 // The default value is 2.0
119 func (c *Container) SetCompressionRatio(ratio float32) {
120 c.compressionRatio = ratio
121 }
122
123 // SetSequenced sets or unsets sequencing on the container stream.
124 // The sequence number is updated every time WriteTo() is called.
125 func (c *Container) SetSequenced(sequenced bool) {
126 if sequenced {
127 seqid := uint64(rand.Uint32()) << 32
128 seqid |= uint64(rand.Uint32())
129 c.Nmsg.SequenceId = proto.Uint64(seqid)
130 c.Nmsg.Sequence = proto.Uint32(0)
131 } else {
132 c.Nmsg.SequenceId = nil
133 c.Nmsg.Sequence = nil
134 }
135 }
136
137 // AddPayload adds the supplied NmsgPayload to the Container if possible.
138 //
139 // The return value 'full' is true if the container is full and needs to
140 // be emptied with WriteTo().
141 //
142 // The return value 'ok' is true if the payload was successfully added to
143 // the container, otherwise, AddPayload() must be called again after WriteTo().
144 //
145 // Both ok and full may be true if the payload is larger than the container's
146 // MaxSize, or if the container is full after adding the payload.
147 func (c *Container) AddPayload(p *NmsgPayload) (ok, full bool) {
148 limit := c.maxSize
149 if c.compress {
150 if c.compressionRatio > 0 {
151 limit = int(float32(limit) * c.compressionRatio)
152 } else {
153 limit *= 2
154 }
155 }
156 ps := p.payloadSize()
157 if c.size+ps >= limit {
158 full = true
159 }
160
161 if !full || c.size == containerOverhead || c.size+ps == limit {
162 ok = true
163 c.size += ps
164 c.Nmsg.Payloads = append(c.Nmsg.Payloads, p)
165 c.Nmsg.PayloadCrcs = append(c.Nmsg.PayloadCrcs, nmsgCRC(p.Payload))
166 }
167
168 return
169 }
170
171 // Reset discards payloads and crcs from the Container
172 func (c *Container) Reset() {
173 c.Nmsg.Payloads = c.Nmsg.Payloads[:0]
174 c.Nmsg.PayloadCrcs = c.Nmsg.PayloadCrcs[:0]
175 c.NmsgFragment = nil
176 }
177
178 // WriteTo writes the Container to Writer w. If the
179 // container requires fragmentation, it will call
180 // w.Write() multiple times.
181 func (c *Container) WriteTo(w io.Writer) (int64, error) {
182 var buf bytes.Buffer
183
184 header := containerHeader{
185 Magic: nmsgMagic,
186 Version: nmsgVersion,
187 }
188
189 defer c.Reset()
190
191 b, err := proto.Marshal(&c.Nmsg)
192 if err != nil {
193 return 0, err
194 }
195
196 if c.compress {
197 b, err = zbufDeflate(b)
198 if err != nil {
199 return 0, err
200 }
201 header.Flags |= nmsgFlagZlib
202 }
203
204 header.Length = uint32(len(b))
205 if c.Nmsg.Sequence != nil {
206 *c.Nmsg.Sequence++
207 }
208 c.size = containerOverhead
209
210 if len(b)+containerOverhead > c.writeSize {
211 return c.writeFragments(w, b)
212 }
213
214 if err = binary.Write(&buf, binary.BigEndian, &header); err != nil {
215 return 0, err
216 }
217
218 if _, err = buf.Write(b); err != nil {
219 return 0, err
220 }
221
222 return buf.WriteTo(w)
223 }
224
225 func (c *Container) writeFragments(w io.Writer, b []byte) (int64, error) {
226 header := containerHeader{
227 Magic: nmsgMagic,
228 Version: nmsgVersion,
229 Flags: nmsgFlagFragment,
230 }
231
232 if c.compress {
233 header.Flags |= nmsgFlagZlib
234 }
235
236 fragSize := c.writeSize - fragmentOverhead
237 lastFrag := len(b) / fragSize
238 fragID := rand.Uint32()
239
240 nf := NmsgFragment{
241 Id: proto.Uint32(fragID),
242 Current: proto.Uint32(uint32(0)),
243 Last: proto.Uint32(uint32(lastFrag)),
244 Crc: proto.Uint32(nmsgCRC(b)),
245 }
246
247 var written int64
248 for i := 0; i <= lastFrag; i++ {
249 var buf bytes.Buffer
250
251 fblen := len(b)
252 if fblen > fragSize {
253 fblen = fragSize
254 }
255
256 *nf.Current = uint32(i)
257 nf.Fragment = b[:fblen]
258 b = b[fblen:]
259
260 fbytes, err := proto.Marshal(&nf)
261 if err != nil {
262 return written, err
263 }
264
265 header.Length = uint32(len(fbytes))
266 if err = binary.Write(&buf, binary.BigEndian, header); err != nil {
267 return written, err
268 }
269
270 if _, err = buf.Write(fbytes); err != nil {
271 return written, err
272 }
273
274 n, err := buf.WriteTo(w)
275 if err != nil {
276 return written, err
277 }
278 written += n
279 }
280 return written, nil
281 }
282
283 // ReadFrom Reads a Container from the given io.Reader. It returns the
284 // number of container bytes read on success.
285 func (c *Container) ReadFrom(r io.Reader) (n int64, err error) {
286 /*
287 * The bytes.Buffer Grow() method may panic with ErrTooLarge.
288 * We catch this panic (and any other error panic()s and return
289 * an error.
290 */
291 defer func() {
292 if r := recover(); r != nil {
293 var ok bool
294 if err, ok = r.(error); !ok {
295 err = fmt.Errorf("nmsg.Container ReadFrom: panic %v", r)
296 }
297 }
298 }()
299 var buf bytes.Buffer
300 var h containerHeader
301 if n, err = io.CopyN(&buf, r, headerSize); err != nil {
302 return n, err
303 }
304
305 err = binary.Read(&buf, binary.BigEndian, &h)
306 if err != nil {
307 return n, &dataError{err}
308 }
309 if h.Magic != nmsgMagic {
310 return 0, &dataError{errBadMagic}
311 }
312
313 buf.Grow(int(h.Length))
314 if n, err = io.CopyN(&buf, r, int64(h.Length)); err != nil {
315 return int64(buf.Len()), err
316 }
317
318 // err = c.fromBytesHeader(buf.Bytes(), &h)
319 err = c.fromNmsgBytes(buf.Bytes(), h.isCompressed(), h.isFragmented())
320 if err != nil {
321 err = &dataError{err}
322 }
323 return int64(buf.Len()), err
324 }
325
326 // FromBytes parses the given buffer as an NMSG container and stores
327 // the result in the receiver *Container.
328 func (c *Container) FromBytes(b []byte) error {
329 var h containerHeader
330 buf := bytes.NewBuffer(b)
331 err := binary.Read(buf, binary.BigEndian, &h)
332 if err != nil {
333 return err
334 }
335 if h.Magic != nmsgMagic {
336 return errBadMagic
337 }
338
339 return c.fromNmsgBytes(buf.Bytes(), h.isCompressed(), h.isFragmented())
340 }
341
342 // fromNmsgBytes parses the contents (b) of an NMSG container, according to
343 // whether the container contents are compressed, fragmented, or both.
344 func (c *Container) fromNmsgBytes(b []byte, compressed, fragmented bool) error {
345 var err error
346 cbytes := b
347 c.isCompressed = compressed
348 if compressed {
349 cbytes, err = zbufInflate(b)
350 if err != nil {
351 return err
352 }
353 }
354
355 if fragmented {
356 c.NmsgFragment = &NmsgFragment{}
357 return proto.Unmarshal(cbytes, c.NmsgFragment)
358 }
359
360 c.NmsgFragment = nil
361 return proto.Unmarshal(cbytes, &c.Nmsg)
362 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg_test
9
10 // These tests verify container compatibility between C libnmsg (wrapped in
11 // cgo-nmsg) and go-nmsg, both with and without compression.
12
13 import (
14 "bytes"
15 "log"
16 "testing"
17
18 cnmsg "github.com/farsightsec/go-nmsg/cgo-nmsg"
19 "github.com/farsightsec/go-nmsg"
20 "github.com/farsightsec/go-nmsg/nmsg_base"
21 )
22
23 func compare(a, b []byte) bool {
24 if len(a) != len(b) {
25 return false
26 }
27 for i := range a {
28 if a[i] != b[i] {
29 return false
30 }
31 }
32 return true
33 }
34
35 func TestContainerGoCgoUnpack(t *testing.T) {
36 b := new(bytes.Buffer)
37 c := nmsg.NewContainer()
38 c.SetMaxSize(nmsg.MinContainerSize, nmsg.MinContainerSize)
39 c.AddPayload(testGoMessage(100))
40 c.WriteTo(b)
41
42 m, err := cnmsg.UnpackContainer(b.Bytes())
43 if err != nil {
44 t.Fatal(err)
45 }
46
47 if len(m) != 1 {
48 t.Fatalf("message count mismatch %d != 1", len(m))
49 }
50
51 if checkCgoMessage(m[0], 100) {
52 return
53 }
54
55 t.Error("payload mismatch")
56 }
57
58 func TestContainerGoCgoUnpackCompress(t *testing.T) {
59 b := new(bytes.Buffer)
60 c := nmsg.NewContainer()
61 c.SetCompression(true)
62 c.SetMaxSize(nmsg.MinContainerSize, nmsg.MinContainerSize)
63 c.AddPayload(testGoMessage(100))
64 c.WriteTo(b)
65
66 byt := b.Bytes()
67
68 m, err := cnmsg.UnpackContainer(byt)
69 if err != nil {
70 t.Fatal(err)
71 }
72
73 if len(m) != 1 {
74 t.Fatalf("message count mismatch %d != 1", len(m))
75 }
76
77 if checkCgoMessage(m[0], 100) {
78 return
79 }
80
81 t.Error("payload mismatch")
82 }
83
84 func testCgoMessage(size int) *cnmsg.Message {
85 mod := cnmsg.MessageModLookupByName("base", "encode")
86 if mod == nil {
87 log.Fatal("module not found")
88 }
89 msg := cnmsg.NewMessage(mod)
90 if err := msg.SetEnumField("type", 0, "TEXT"); err != nil {
91 log.Fatal(err)
92 }
93
94 if err := msg.SetBytesField("payload", 0, make([]byte, size)); err != nil {
95 log.Fatal(err)
96 }
97 return msg
98 }
99
100 func checkCgoMessage(m *cnmsg.Message, size int) bool {
101 b, err := m.GetBytesField("payload", 0)
102 if err != nil {
103 return false
104 }
105 return compare(b, make([]byte, size))
106 }
107
108 func testGoMessage(size int) *nmsg.NmsgPayload {
109 m := new(nmsg_base.Encode)
110 m.Payload = make([]byte, size)
111 m.Type = nmsg_base.EncodeType_TEXT.Enum()
112 p, err := nmsg.Payload(m)
113 if err != nil {
114 log.Fatal(err)
115 }
116 return p
117 }
118
119 func checkGoMessage(m nmsg.Message, size int) bool {
120 enc, ok := m.(*nmsg_base.Encode)
121
122 if !ok {
123 log.Printf("type mismatch: %T != *nmsg_base.Encode", m)
124 return false
125 }
126 return compare(enc.GetPayload(), make([]byte, size))
127 }
128
129 func TestContainerCgoGoUnpack(t *testing.T) {
130 c := cnmsg.NewContainer(&cnmsg.ContainerConfig{
131 Size: cnmsg.BufferSizeMin,
132 })
133 c.Add(testCgoMessage(100))
134
135 i := nmsg.NewInput(bytes.NewReader(c.Bytes()), cnmsg.BufferSizeMin)
136 p, err := i.Recv()
137 if err != nil {
138 t.Fatal(err)
139 }
140
141 m, err := p.Message()
142 if err != nil {
143 t.Fatal(err)
144 }
145
146 if checkGoMessage(m, 100) {
147 return
148 }
149
150 t.Error("payload mismatch")
151 }
152
153 func TestContainerCgoGoUnpackCompress(t *testing.T) {
154 c := cnmsg.NewContainer(&cnmsg.ContainerConfig{
155 Size: cnmsg.BufferSizeMin,
156 Compress: true,
157 })
158 c.Add(testCgoMessage(100))
159
160 byt := c.Bytes()
161 i := nmsg.NewInput(bytes.NewReader(byt), cnmsg.BufferSizeMin)
162 p, err := i.Recv()
163 if err != nil {
164 t.Fatal(err)
165 }
166
167 m, err := p.Message()
168 if err != nil {
169 t.Fatal(err)
170 }
171
172 if checkGoMessage(m, 100) {
173 return
174 }
175
176 t.Error("payload mismatch")
177 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 // The nmsg C library renders checksums in network byte order before presenting
11 // them to the protobuf-c library as uint32 values. While Go's encoding/binary
12 // library can format and parse uint32 values as BigEndian or LittleEndian byte
13 // arrays, this is not sufficient to calculate an integer that will represent
14 // a BigEndian (network) byte array in the host's native byte order. This
15 // requires determining the host's byte order, a task which Go's type system
16 // makes cumbersome.
17 //
18 // This file uses the "unsafe" package to defeat Go's type system for the
19 // purposes of determining whether the package is running on a BigEndian or
20 // LittleEndian machine, and uses this information to implement htonl.
21
22 import (
23 "encoding/binary"
24 "unsafe"
25 )
26
27 var hostEndian binary.ByteOrder
28
29 func init() {
30 n := uint32(1)
31 b := *(*[4]byte)(unsafe.Pointer(&n))
32 if b[0] == 1 {
33 hostEndian = binary.LittleEndian
34 } else {
35 hostEndian = binary.BigEndian
36 }
37 }
38
39 func htonl(n uint32) uint32 {
40 var buf [4]byte
41 hostEndian.PutUint32(buf[:], n)
42 return binary.BigEndian.Uint32(buf[:])
43 }
0 /*
1 * Copyright (c) 2017,2018 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 import (
11 "bufio"
12 "fmt"
13 "io"
14 "time"
15 )
16
17 // An Input is a source of NMSG Payloads.
18 type Input interface {
19 // Recv() returns the next Nmsg Payload from the input,
20 // blocking if none is available.
21 Recv() (*NmsgPayload, error)
22 // Stats() returns interface statistics
23 Stats() *InputStatistics
24 }
25
26 // InputStatistics holds useful metrics for input performance.
27 type InputStatistics struct {
28 // Count of total container received, including fragments
29 InputContainers uint64
30 // Count of total bytes received and processed
31 InputBytes uint64
32 // Count of containers marked lost by sequence tracking
33 LostContainers uint64
34 // Count of fragment containers received
35 InputFragments uint64
36 // Count of fragments expired from cache
37 ExpiredFragments uint64
38 // Count of containers dropped due to incomplete fragments
39 PartialContainers uint64
40 }
41
42 type dataError struct{ error }
43
44 func (d *dataError) Error() string { return d.error.Error() }
45
46 // IsDataError returns true of the supplied error is an error unpacking
47 // or decoding the NMSG data rather than an I/O error with the input.
48 func IsDataError(err error) bool {
49 _, ok := err.(*dataError)
50 return ok
51 }
52
53 type input struct {
54 r io.Reader
55 n Nmsg
56 fcache *fragCache
57 scache *seqCache
58 stats InputStatistics
59 }
60
61 func (i *input) Stats() *InputStatistics {
62 res := &InputStatistics{}
63 *res = i.stats
64 return res
65 }
66
67 // NewInput constructs an input from the supplied Reader.
68 // The size parameter sizes the input buffer, and should
69 // be greater than the maximum anticipated container size
70 // for datagram inputs.
71 func NewInput(r io.Reader, size int) Input {
72 return &input{
73 r: bufio.NewReaderSize(r, size),
74 n: Nmsg{},
75 fcache: newFragmentCache(2 * time.Minute),
76 scache: newSequenceCache(2 * time.Minute),
77 }
78 }
79
80 type checksumError struct {
81 calc, wire uint32
82 }
83
84 func (c *checksumError) Error() string {
85 return fmt.Sprintf("checksum mismatch: %x != %x", c.calc, c.wire)
86 }
87
88 func (i *input) Recv() (*NmsgPayload, error) {
89 for len(i.n.Payloads) == 0 {
90 var c Container
91 n, err := c.ReadFrom(i.r)
92 if err != nil {
93 return nil, err
94 }
95 if n == 0 {
96 return nil, io.EOF
97 }
98
99 i.stats.InputBytes += uint64(n)
100
101 if c.NmsgFragment != nil {
102 i.stats.InputFragments++
103 var b []byte
104 if b = i.fcache.Insert(c.NmsgFragment); b == nil {
105 continue
106 }
107 err = c.fromNmsgBytes(b, c.isCompressed, false)
108 if err != nil {
109 return nil, &dataError{err}
110 }
111 }
112
113 i.stats.InputContainers++
114 i.stats.LostContainers += uint64(i.scache.Update(&c.Nmsg))
115 i.scache.Expire()
116 i.n = c.Nmsg
117 }
118 ccount, fcount := i.fcache.Expire()
119 i.stats.PartialContainers += uint64(ccount)
120 i.stats.ExpiredFragments += uint64(fcount)
121 p := i.n.Payloads[0]
122 i.n.Payloads = i.n.Payloads[1:]
123
124 var err error
125 if len(i.n.PayloadCrcs) > 0 {
126 wire := i.n.PayloadCrcs[0]
127 calc := nmsgCRC(p.Payload)
128 if wire != calc {
129 err = &dataError{&checksumError{calc, wire}}
130 }
131 i.n.PayloadCrcs = i.n.PayloadCrcs[1:]
132 }
133
134 return p, err
135 }
0 /*
1 * Copyright (c) 2018 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 // NMSG Fragment Cache.
11
12 import (
13 "bytes"
14 "container/list"
15 "sort"
16 "time"
17 )
18
19 type fragCacheEntry struct {
20 lastUsed time.Time
21 id uint32
22 frags fragList
23 }
24
25 // fragList implements sort.Interface to support sorting fragments on
26 // their "Current" field prior to reassembly.
27 type fragList []*NmsgFragment
28
29 func (fl fragList) Len() int { return len(fl) }
30 func (fl fragList) Less(i, j int) bool { return fl[i].GetCurrent() < fl[j].GetCurrent() }
31 func (fl fragList) Swap(i, j int) { fl[i], fl[j] = fl[j], fl[i] }
32
33 type fragCache struct {
34 expiry time.Duration
35 idmap map[uint32]*list.Element
36 lru *list.List
37 }
38
39 func newFragmentCache(expiry time.Duration) *fragCache {
40 return &fragCache{
41 expiry: expiry,
42 idmap: make(map[uint32]*list.Element),
43 lru: list.New(),
44 }
45 }
46
47 // Expire too-old entries from the fragment cache, returning the number
48 // of incomplete containers and fragments dropped.
49 func (fc *fragCache) Expire() (containers, frags int) {
50 for fc.lru.Len() > 0 {
51 lruent := fc.lru.Front()
52 ent := lruent.Value.(*fragCacheEntry)
53 if time.Since(ent.lastUsed) <= fc.expiry {
54 break
55 }
56 containers++
57 frags += len(ent.frags)
58 fc.lru.Remove(lruent)
59 delete(fc.idmap, ent.id)
60 }
61 return
62 }
63
64 // Inserts a fragment into the cache. If the fragment completes a fragmented
65 // container, Insert returns the reassembled container body. Otherwise, returns
66 // nil.
67 func (fc *fragCache) Insert(f *NmsgFragment) []byte {
68 id := f.GetId()
69 lruent, ok := fc.idmap[id]
70 if !ok {
71 fc.idmap[id] = fc.lru.PushBack(
72 &fragCacheEntry{
73 lastUsed: time.Now(),
74 id: id,
75 frags: fragList{f},
76 })
77 return nil
78 }
79
80 ent := lruent.Value.(*fragCacheEntry)
81 for i := range ent.frags {
82 if ent.frags[i].GetCurrent() == f.GetCurrent() {
83 /* duplicate fragment */
84 return nil
85 }
86 }
87 ent.frags = append(ent.frags, f)
88 if ent.frags.Len() <= int(f.GetLast()) {
89 ent.lastUsed = time.Now()
90 fc.lru.MoveToBack(lruent)
91 return nil
92 }
93 fc.lru.Remove(lruent)
94 delete(fc.idmap, id)
95
96 /* sort and reassemble fragments */
97 sort.Sort(ent.frags)
98 var b bytes.Buffer
99 for i := range ent.frags {
100 b.Write(ent.frags[i].GetFragment())
101 }
102 return b.Bytes()
103 }
0 /*
1 * Copyright (c) 2018 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg
9
10 import (
11 "container/list"
12 "time"
13 )
14
15 type seqCacheEntry struct {
16 lastUsed time.Time
17 seqid uint64
18 nextSeq uint32
19 }
20
21 type seqCache struct {
22 expiry time.Duration
23 idmap map[uint64]*list.Element
24 lru *list.List
25 }
26
27 func newSequenceCache(expiry time.Duration) *seqCache {
28 return &seqCache{
29 expiry: expiry,
30 idmap: make(map[uint64]*list.Element),
31 lru: list.New(),
32 }
33 }
34
35 const maxDrop = 1048576
36
37 func (sc *seqCache) Update(n *Nmsg) (missed int) {
38 if n.Sequence == nil || n.SequenceId == nil {
39 return
40 }
41 seqid := n.GetSequenceId()
42 lruent, ok := sc.idmap[seqid]
43 if !ok {
44 sc.idmap[seqid] = sc.lru.PushBack(
45 &seqCacheEntry{
46 lastUsed: time.Now(),
47 seqid: seqid,
48 nextSeq: n.GetSequence() + 1,
49 })
50 return 0
51 }
52 seq := n.GetSequence()
53 ent := lruent.Value.(*seqCacheEntry)
54
55 ent.lastUsed = time.Now()
56 sc.lru.MoveToBack(lruent)
57
58 if seq == ent.nextSeq {
59 ent.nextSeq++
60 return 0
61 }
62
63 if seq > ent.nextSeq {
64 if seq-ent.nextSeq < maxDrop {
65 missed = int(seq - ent.nextSeq)
66 }
67 ent.nextSeq = seq + 1
68 return missed
69 }
70
71 delta := int64(int64(seq) + (1 << 32) - int64(ent.nextSeq))
72 if delta < maxDrop {
73 missed = int(delta)
74 }
75
76 ent.nextSeq = seq + 1
77 return missed
78 }
79
80 func (sc *seqCache) Expire() {
81 for sc.lru.Len() > 0 {
82 lruent := sc.lru.Front()
83 ent := lruent.Value.(*seqCacheEntry)
84 if time.Since(ent.lastUsed) <= sc.expiry {
85 break
86 }
87 sc.lru.Remove(lruent)
88 delete(sc.idmap, ent.seqid)
89 }
90 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 package nmsg_test
9
10 import (
11 "bytes"
12 "io"
13 "math"
14 "testing"
15
16 "github.com/farsightsec/go-nmsg"
17 )
18
19 func testReader(t *testing.T, n, size, mtu int) io.Reader {
20 buf := new(bytes.Buffer)
21 // nw := nmsg.NewWriter(w, mtu)
22 o := nmsg.BufferedOutput(buf)
23 o.SetMaxSize(mtu, 0)
24 o.SetSequenced(true)
25
26 p, err := nmsg.Payload(testMessage(size))
27 if err != nil {
28 t.Error(err.Error())
29 return nil
30 }
31
32 for i := 0; i < n; i++ {
33 o.Send(p)
34 }
35
36 o.Close()
37
38 t.Logf("testReader: buf = %d bytes (%d, %d, %d)", buf.Len(), n, size, mtu)
39 return buf
40 }
41
42 func TestInput(t *testing.T) {
43 for _, mtu := range []int{0, 512, 1500} {
44 for _, n := range []int{1, 10, 100} {
45 for _, size := range []int{64, 256, 4096} {
46 i := nmsg.NewInput(testReader(t, n, size, mtu), mtu)
47 if i != nil {
48 c := 0
49 for {
50 _, err := i.Recv()
51 if err != nil {
52 if err != io.EOF {
53 t.Error(err)
54 }
55 break
56 }
57 c++
58 }
59 if c < n {
60 t.Errorf("(%d,%d,%d) expected %d, received %d", n, size, mtu, n, c)
61 }
62 }
63 }
64 }
65 }
66 }
67
68 func TestInputFragExpire(t *testing.T) {
69 // Fragment expiration is not checked here, only in
70 // coverage.
71 var readers []io.Reader
72 npayloads := 10
73 payloadSize := 512
74 mtu := 512
75 for i := 0; i < 1000; i++ {
76 readers = append(readers, testReader(t, npayloads,
77 payloadSize, mtu))
78 }
79 inp := nmsg.NewInput(io.MultiReader(readers...), 512)
80 var count int
81 for ; ; count++ {
82 _, err := inp.Recv()
83 if err != nil {
84 break
85 }
86 }
87 if count != npayloads*1000 {
88 t.Errorf("missed input, received %d payloads", count)
89 }
90 }
91
92 func testLoss(t *testing.T, r io.Reader, loss uint64, title string) {
93 t.Helper()
94 i := nmsg.NewInput(r, nmsg.MaxContainerSize)
95 for {
96 if _, err := i.Recv(); err != nil {
97 break
98 }
99 }
100 stats := i.Stats()
101 if stats.LostContainers != loss {
102 t.Errorf("%s: lost %d (expected %d)", title, stats.LostContainers, loss)
103 }
104 }
105
106 func TestInputSequenceLoss1(t *testing.T) {
107 var buf bytes.Buffer
108 c := nmsg.NewContainer()
109
110 c.SetSequenced(true)
111 c.WriteTo(&buf)
112 c.WriteTo(&buf)
113 *c.Nmsg.Sequence++ // skip one
114 c.WriteTo(&buf)
115
116 testLoss(t, &buf, 1, "drop 1")
117 }
118
119 func TestInputSequenceInterleaveLoss1(t *testing.T) {
120 var buf bytes.Buffer
121
122 c1 := nmsg.NewContainer()
123 c2 := nmsg.NewContainer()
124 c1.SetSequenced(true)
125 c2.SetSequenced(true)
126
127 c1.WriteTo(&buf)
128 c2.WriteTo(&buf)
129 c2.WriteTo(&buf)
130 c1.WriteTo(&buf)
131 c2.WriteTo(&buf)
132 *c1.Nmsg.Sequence++
133 c1.WriteTo(&buf)
134 c2.WriteTo(&buf)
135 testLoss(t, &buf, 1, "interleaved, drop 1")
136 }
137
138 func TestInputSequenceWrap(t *testing.T) {
139 var buf bytes.Buffer
140
141 c := nmsg.NewContainer()
142 c.SetSequenced(true)
143 *c.Nmsg.Sequence = math.MaxUint32 - 1
144 t.Log("sequence", c.Nmsg.GetSequence())
145 c.WriteTo(&buf)
146 t.Log("sequence", c.Nmsg.GetSequence())
147 *c.Nmsg.Sequence++
148 t.Log("sequence", c.Nmsg.GetSequence())
149 c.WriteTo(&buf)
150 t.Log("sequence", c.Nmsg.GetSequence())
151 testLoss(t, &buf, 1, "wrapped, drop 1")
152 }
0 /*
1 * Copyright (c) 2017 by Farsight Security, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7
8 //go:generate protoc --go_out=. nmsg.proto
9
10 package nmsg
11
12 import (
13 "hash/crc32"
14
15 "github.com/golang/protobuf/proto"
16 )
17
18 // Container size limits to avoid silly fragmentation and memory
19 // exhaustion.
20 const (
21 MinContainerSize = 512
22 MaxContainerSize = 1048576
23 EtherContainerSize = 1280
24 invalidContainerSize = MaxContainerSize * 16
25 )
26
27 var crc32c = crc32.MakeTable(crc32.Castagnoli)
28
29 // nmsgCRC calculates a crc32 checksum compatible with that used by
30 // the nmsg C library.
31 //
32 // As in the C library, the checksum is converted to network byte order
33 // before eventually being encoded as a protocol buffers integer. This
34 // defeats the endian neutrality of protocol buffers, but is necessary
35 // for compatibility with the C library operating on little endian machines.
36 func nmsgCRC(b []byte) uint32 {
37 return htonl(crc32.Checksum(b, crc32c))
38 }
39
40 // Message encapsulates a protobuf-encoded payload.
41 //
42 // The values returned by the GetVid() and GetMsgtype() methods return
43 // identify the format of the payload.
44 type Message interface {
45 proto.Message
46 GetVid() uint32
47 GetMsgtype() uint32
48 }
0 // Code generated by protoc-gen-go.
1 // source: nmsg.proto
2 // DO NOT EDIT!
3
4 /*
5 Package nmsg is a generated protocol buffer package.
6
7 It is generated from these files:
8 nmsg.proto
9
10 It has these top-level messages:
11 Nmsg
12 NmsgFragment
13 NmsgPayload
14 */
15 package nmsg
16
17 import proto "github.com/golang/protobuf/proto"
18 import fmt "fmt"
19 import math "math"
20
21 // Reference imports to suppress errors if they are not otherwise used.
22 var _ = proto.Marshal
23 var _ = fmt.Errorf
24 var _ = math.Inf
25
26 // This is a compile-time assertion to ensure that this generated file
27 // is compatible with the proto package it is being compiled against.
28 // A compilation error at this line likely means your copy of the
29 // proto package needs to be updated.
30 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
31
32 type Nmsg struct {
33 Payloads []*NmsgPayload `protobuf:"bytes,1,rep,name=payloads" json:"payloads,omitempty"`
34 PayloadCrcs []uint32 `protobuf:"varint,2,rep,name=payload_crcs" json:"payload_crcs,omitempty"`
35 Sequence *uint32 `protobuf:"varint,3,opt,name=sequence" json:"sequence,omitempty"`
36 SequenceId *uint64 `protobuf:"varint,4,opt,name=sequence_id" json:"sequence_id,omitempty"`
37 XXX_unrecognized []byte `json:"-"`
38 }
39
40 func (m *Nmsg) Reset() { *m = Nmsg{} }
41 func (m *Nmsg) String() string { return proto.CompactTextString(m) }
42 func (*Nmsg) ProtoMessage() {}
43 func (*Nmsg) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
44
45 func (m *Nmsg) GetPayloads() []*NmsgPayload {
46 if m != nil {
47 return m.Payloads
48 }
49 return nil
50 }
51
52 func (m *Nmsg) GetPayloadCrcs() []uint32 {
53 if m != nil {
54 return m.PayloadCrcs
55 }
56 return nil
57 }
58
59 func (m *Nmsg) GetSequence() uint32 {
60 if m != nil && m.Sequence != nil {
61 return *m.Sequence
62 }
63 return 0
64 }
65
66 func (m *Nmsg) GetSequenceId() uint64 {
67 if m != nil && m.SequenceId != nil {
68 return *m.SequenceId
69 }
70 return 0
71 }
72
73 type NmsgFragment struct {
74 Id *uint32 `protobuf:"varint,1,req,name=id" json:"id,omitempty"`
75 Current *uint32 `protobuf:"varint,2,req,name=current" json:"current,omitempty"`
76 Last *uint32 `protobuf:"varint,3,req,name=last" json:"last,omitempty"`
77 Fragment []byte `protobuf:"bytes,4,req,name=fragment" json:"fragment,omitempty"`
78 Crc *uint32 `protobuf:"varint,5,opt,name=crc" json:"crc,omitempty"`
79 XXX_unrecognized []byte `json:"-"`
80 }
81
82 func (m *NmsgFragment) Reset() { *m = NmsgFragment{} }
83 func (m *NmsgFragment) String() string { return proto.CompactTextString(m) }
84 func (*NmsgFragment) ProtoMessage() {}
85 func (*NmsgFragment) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
86
87 func (m *NmsgFragment) GetId() uint32 {
88 if m != nil && m.Id != nil {
89 return *m.Id
90 }
91 return 0
92 }
93
94 func (m *NmsgFragment) GetCurrent() uint32 {
95 if m != nil && m.Current != nil {
96 return *m.Current
97 }
98 return 0
99 }
100
101 func (m *NmsgFragment) GetLast() uint32 {
102 if m != nil && m.Last != nil {
103 return *m.Last
104 }
105 return 0
106 }
107
108 func (m *NmsgFragment) GetFragment() []byte {
109 if m != nil {
110 return m.Fragment
111 }
112 return nil
113 }
114
115 func (m *NmsgFragment) GetCrc() uint32 {
116 if m != nil && m.Crc != nil {
117 return *m.Crc
118 }
119 return 0
120 }
121
122 type NmsgPayload struct {
123 Vid *uint32 `protobuf:"varint,1,req,name=vid" json:"vid,omitempty"`
124 Msgtype *uint32 `protobuf:"varint,2,req,name=msgtype" json:"msgtype,omitempty"`
125 TimeSec *int64 `protobuf:"varint,3,req,name=time_sec" json:"time_sec,omitempty"`
126 TimeNsec *uint32 `protobuf:"fixed32,4,req,name=time_nsec" json:"time_nsec,omitempty"`
127 Payload []byte `protobuf:"bytes,5,opt,name=payload" json:"payload,omitempty"`
128 Source *uint32 `protobuf:"varint,7,opt,name=source" json:"source,omitempty"`
129 Operator *uint32 `protobuf:"varint,8,opt,name=operator" json:"operator,omitempty"`
130 Group *uint32 `protobuf:"varint,9,opt,name=group" json:"group,omitempty"`
131 XXX_unrecognized []byte `json:"-"`
132 }
133
134 func (m *NmsgPayload) Reset() { *m = NmsgPayload{} }
135 func (m *NmsgPayload) String() string { return proto.CompactTextString(m) }
136 func (*NmsgPayload) ProtoMessage() {}
137 func (*NmsgPayload) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
138
139 func (m *NmsgPayload) GetVid() uint32 {
140 if m != nil && m.Vid != nil {
141 return *m.Vid
142 }
143 return 0
144 }
145
146 func (m *NmsgPayload) GetMsgtype() uint32 {
147 if m != nil && m.Msgtype != nil {
148 return *m.Msgtype
149 }
150 return 0
151 }
152
153 func (m *NmsgPayload) GetTimeSec() int64 {
154 if m != nil && m.TimeSec != nil {
155 return *m.TimeSec
156 }
157 return 0
158 }
159
160 func (m *NmsgPayload) GetTimeNsec() uint32 {
161 if m != nil && m.TimeNsec != nil {
162 return *m.TimeNsec
163 }
164 return 0
165 }
166
167 func (m *NmsgPayload) GetPayload() []byte {
168 if m != nil {
169 return m.Payload
170 }
171 return nil
172 }
173
174 func (m *NmsgPayload) GetSource() uint32 {
175 if m != nil && m.Source != nil {
176 return *m.Source
177 }
178 return 0
179 }
180
181 func (m *NmsgPayload) GetOperator() uint32 {
182 if m != nil && m.Operator != nil {
183 return *m.Operator
184 }
185 return 0
186 }
187
188 func (m *NmsgPayload) GetGroup() uint32 {
189 if m != nil && m.Group != nil {
190 return *m.Group
191 }
192 return 0
193 }
194
195 func init() {
196 proto.RegisterType((*Nmsg)(nil), "nmsg.Nmsg")
197 proto.RegisterType((*NmsgFragment)(nil), "nmsg.NmsgFragment")
198 proto.RegisterType((*NmsgPayload)(nil), "nmsg.NmsgPayload")
199 }
200
201 func init() { proto.RegisterFile("nmsg.proto", fileDescriptor0) }
202
203 var fileDescriptor0 = []byte{
204 // 259 bytes of a gzipped FileDescriptorProto
205 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0x8f, 0xb1, 0x4e, 0xc3, 0x30,
206