New upstream version 0.0~git20190917.04d2174
Sascha Steinbiss
4 years ago
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 | 0x10, 0x86, 0x15, 0xc7, 0x25, 0xe9, 0xc5, 0x05, 0x6a, 0x18, 0x3c, 0x46, 0x61, 0xe9, 0xd4, 0x81, | |
207 | 0x87, 0x60, 0x44, 0x8c, 0x6c, 0x91, 0xe5, 0x9a, 0x50, 0xa9, 0x89, 0x8d, 0xed, 0x20, 0xf5, 0x35, | |
208 | 0x78, 0x62, 0xee, 0xdc, 0x54, 0xea, 0x94, 0xf8, 0xfb, 0xef, 0xbe, 0xbb, 0x03, 0x98, 0xc6, 0x38, | |
209 | 0xec, 0x7d, 0x70, 0xc9, 0x49, 0x4e, 0xff, 0xdd, 0x37, 0xf0, 0x77, 0xfc, 0xca, 0x17, 0xa8, 0xbd, | |
210 | 0x3e, 0x9f, 0x9c, 0x3e, 0x44, 0x55, 0xb4, 0xe5, 0xae, 0x79, 0xdd, 0xee, 0x73, 0x31, 0xa5, 0x1f, | |
211 | 0x97, 0x44, 0x3e, 0x83, 0x58, 0x8a, 0x7a, 0x13, 0x4c, 0x54, 0x0c, 0x0b, 0x37, 0xf2, 0x11, 0xea, | |
212 | 0x68, 0x7f, 0x66, 0x3b, 0x19, 0xab, 0xca, 0xb6, 0x40, 0xf2, 0x04, 0xcd, 0x95, 0xf4, 0xc7, 0x83, | |
213 | 0xe2, 0x08, 0x79, 0xf7, 0x09, 0x82, 0x5c, 0x6f, 0x41, 0x0f, 0xa3, 0x9d, 0x92, 0x04, 0x60, 0x98, | |
214 | 0x15, 0x2d, 0xc3, 0x86, 0x07, 0xa8, 0xcc, 0x1c, 0x02, 0x62, 0x74, 0x12, 0x10, 0xc0, 0x4f, 0x3a, | |
215 | 0x26, 0xf4, 0xb1, 0xcb, 0x84, 0xaf, 0xa5, 0x0d, 0x65, 0x6c, 0x27, 0x64, 0x03, 0x25, 0x6e, 0xa0, | |
216 | 0x56, 0x34, 0xae, 0xfb, 0x2b, 0xa0, 0xb9, 0x5d, 0x13, 0xc3, 0xdf, 0x5b, 0x35, 0x46, 0xe9, 0xec, | |
217 | 0xed, 0xa2, 0x46, 0x59, 0x3a, 0x8e, 0xb6, 0x8f, 0xd6, 0x64, 0x7d, 0x29, 0xb7, 0xb0, 0xce, 0x64, | |
218 | 0x22, 0x44, 0xfe, 0x8a, 0xba, 0x96, 0x4b, 0xf3, 0x0c, 0x21, 0xef, 0xe1, 0x2e, 0xba, 0x39, 0xe0, | |
219 | 0x89, 0x55, 0x3e, 0x11, 0x2d, 0xce, 0xdb, 0xa0, 0x93, 0x0b, 0xaa, 0xce, 0x64, 0x03, 0xab, 0x21, | |
220 | 0xb8, 0xd9, 0xab, 0x35, 0x3d, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x73, 0x07, 0x52, 0x34, 0x6b, | |
221 | 0x01, 0x00, 0x00, | |
222 | } |
0 | syntax = "proto2"; | |
1 | package nmsg; | |
2 | ||
3 | message Nmsg { | |
4 | repeated NmsgPayload payloads = 1; | |
5 | repeated uint32 payload_crcs = 2; | |
6 | optional uint32 sequence = 3; | |
7 | optional uint64 sequence_id = 4; | |
8 | } | |
9 | ||
10 | message NmsgFragment { | |
11 | required uint32 id = 1; | |
12 | required uint32 current = 2; | |
13 | required uint32 last = 3; | |
14 | required bytes fragment = 4; | |
15 | optional uint32 crc = 5; | |
16 | } | |
17 | ||
18 | message NmsgPayload { | |
19 | required uint32 vid = 1; | |
20 | required uint32 msgtype = 2; | |
21 | required int64 time_sec = 3; | |
22 | required fixed32 time_nsec = 4; | |
23 | optional bytes payload = 5; | |
24 | optional uint32 source = 7; | |
25 | optional uint32 operator = 8; | |
26 | optional uint32 group = 9; | |
27 | } |
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_base | |
9 | ||
10 | import ( | |
11 | "github.com/dnstap/golang-dnstap" | |
12 | "github.com/farsightsec/go-nmsg" | |
13 | "github.com/golang/protobuf/proto" | |
14 | ) | |
15 | ||
16 | func (p *Ncap) GetVid() uint32 { return 1 } | |
17 | func (p *Ncap) GetMsgtype() uint32 { return 1 } | |
18 | ||
19 | func (p *Email) GetVid() uint32 { return 1 } | |
20 | func (p *Email) GetMsgtype() uint32 { return 2 } | |
21 | ||
22 | func (p *Linkpair) GetVid() uint32 { return 1 } | |
23 | func (p *Linkpair) GetMsgtype() uint32 { return 3 } | |
24 | ||
25 | func (p *Http) GetVid() uint32 { return 1 } | |
26 | func (p *Http) GetMsgtype() uint32 { return 4 } | |
27 | ||
28 | func (p *IPConn) GetVid() uint32 { return 1 } | |
29 | func (p *IPConn) GetMsgtype() uint32 { return 5 } | |
30 | ||
31 | func (p *LogLine) GetVid() uint32 { return 1 } | |
32 | func (p *LogLine) GetMsgtype() uint32 { return 6 } | |
33 | ||
34 | func (p *Dns) GetVid() uint32 { return 1 } | |
35 | func (p *Dns) GetMsgtype() uint32 { return 7 } | |
36 | ||
37 | func (p *Pkt) GetVid() uint32 { return 1 } | |
38 | func (p *Pkt) GetMsgtype() uint32 { return 8 } | |
39 | ||
40 | func (p *DnsQR) GetVid() uint32 { return 1 } | |
41 | func (p *DnsQR) GetMsgtype() uint32 { return 9 } | |
42 | ||
43 | func (p *Xml) GetVid() uint32 { return 1 } | |
44 | func (p *Xml) GetMsgtype() uint32 { return 10 } | |
45 | ||
46 | func (p *Encode) GetVid() uint32 { return 1 } | |
47 | func (p *Encode) GetMsgtype() uint32 { return 11 } | |
48 | ||
49 | func (p *Packet) GetVid() uint32 { return 1 } | |
50 | func (p *Packet) GetMsgtype() uint32 { return 12 } | |
51 | ||
52 | type Dnstap struct { | |
53 | dnstap.Dnstap | |
54 | } | |
55 | ||
56 | func (d *Dnstap) GetVid() uint32 { return 1 } | |
57 | func (d *Dnstap) GetMsgtype() uint32 { return 13 } | |
58 | ||
59 | func (d *Dnstap) Marshal() ([]byte, error) { | |
60 | return proto.Marshal(&d.Dnstap) | |
61 | } | |
62 | func (d *Dnstap) Unmarshal(b []byte) error { | |
63 | return proto.Unmarshal(b, &d.Dnstap) | |
64 | } | |
65 | ||
66 | func init() { | |
67 | nmsg.Register(&Ncap{}) | |
68 | nmsg.Register(&Email{}) | |
69 | nmsg.Register(&Linkpair{}) | |
70 | nmsg.Register(&Http{}) | |
71 | nmsg.Register(&IPConn{}) | |
72 | nmsg.Register(&LogLine{}) | |
73 | nmsg.Register(&Dns{}) | |
74 | nmsg.Register(&Pkt{}) | |
75 | nmsg.Register(&DnsQR{}) | |
76 | nmsg.Register(&Xml{}) | |
77 | nmsg.Register(&Encode{}) | |
78 | nmsg.Register(&Packet{}) | |
79 | nmsg.Register(&Dnstap{}) | |
80 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: dns.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | /* | |
5 | Package nmsg_base is a generated protocol buffer package. | |
6 | ||
7 | It is generated from these files: | |
8 | dns.proto | |
9 | dnsqr.proto | |
10 | email.proto | |
11 | encode.proto | |
12 | http.proto | |
13 | ipconn.proto | |
14 | linkpair.proto | |
15 | logline.proto | |
16 | ncap.proto | |
17 | packet.proto | |
18 | pkt.proto | |
19 | xml.proto | |
20 | ||
21 | It has these top-level messages: | |
22 | Dns | |
23 | DnsQR | |
24 | ||
25 | Encode | |
26 | Http | |
27 | IPConn | |
28 | Linkpair | |
29 | LogLine | |
30 | Ncap | |
31 | Packet | |
32 | Pkt | |
33 | Xml | |
34 | */ | |
35 | package nmsg_base | |
36 | ||
37 | import proto "github.com/golang/protobuf/proto" | |
38 | import fmt "fmt" | |
39 | import math "math" | |
40 | ||
41 | // Reference imports to suppress errors if they are not otherwise used. | |
42 | var _ = proto.Marshal | |
43 | var _ = fmt.Errorf | |
44 | var _ = math.Inf | |
45 | ||
46 | // This is a compile-time assertion to ensure that this generated file | |
47 | // is compatible with the proto package it is being compiled against. | |
48 | // A compilation error at this line likely means your copy of the | |
49 | // proto package needs to be updated. | |
50 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package | |
51 | ||
52 | type Dns struct { | |
53 | Section *uint32 `protobuf:"varint,6,opt,name=section" json:"section,omitempty"` | |
54 | Qname []byte `protobuf:"bytes,7,opt,name=qname" json:"qname,omitempty"` | |
55 | Qtype *uint32 `protobuf:"varint,8,opt,name=qtype" json:"qtype,omitempty"` | |
56 | Qclass *uint32 `protobuf:"varint,9,opt,name=qclass" json:"qclass,omitempty"` | |
57 | Rrname []byte `protobuf:"bytes,1,opt,name=rrname" json:"rrname,omitempty"` | |
58 | Rrtype *uint32 `protobuf:"varint,2,opt,name=rrtype" json:"rrtype,omitempty"` | |
59 | Rrclass *uint32 `protobuf:"varint,3,opt,name=rrclass" json:"rrclass,omitempty"` | |
60 | Rrttl *uint32 `protobuf:"varint,4,opt,name=rrttl" json:"rrttl,omitempty"` | |
61 | Rdata [][]byte `protobuf:"bytes,5,rep,name=rdata" json:"rdata,omitempty"` | |
62 | XXX_unrecognized []byte `json:"-"` | |
63 | } | |
64 | ||
65 | func (m *Dns) Reset() { *m = Dns{} } | |
66 | func (m *Dns) String() string { return proto.CompactTextString(m) } | |
67 | func (*Dns) ProtoMessage() {} | |
68 | func (*Dns) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } | |
69 | ||
70 | func (m *Dns) GetSection() uint32 { | |
71 | if m != nil && m.Section != nil { | |
72 | return *m.Section | |
73 | } | |
74 | return 0 | |
75 | } | |
76 | ||
77 | func (m *Dns) GetQname() []byte { | |
78 | if m != nil { | |
79 | return m.Qname | |
80 | } | |
81 | return nil | |
82 | } | |
83 | ||
84 | func (m *Dns) GetQtype() uint32 { | |
85 | if m != nil && m.Qtype != nil { | |
86 | return *m.Qtype | |
87 | } | |
88 | return 0 | |
89 | } | |
90 | ||
91 | func (m *Dns) GetQclass() uint32 { | |
92 | if m != nil && m.Qclass != nil { | |
93 | return *m.Qclass | |
94 | } | |
95 | return 0 | |
96 | } | |
97 | ||
98 | func (m *Dns) GetRrname() []byte { | |
99 | if m != nil { | |
100 | return m.Rrname | |
101 | } | |
102 | return nil | |
103 | } | |
104 | ||
105 | func (m *Dns) GetRrtype() uint32 { | |
106 | if m != nil && m.Rrtype != nil { | |
107 | return *m.Rrtype | |
108 | } | |
109 | return 0 | |
110 | } | |
111 | ||
112 | func (m *Dns) GetRrclass() uint32 { | |
113 | if m != nil && m.Rrclass != nil { | |
114 | return *m.Rrclass | |
115 | } | |
116 | return 0 | |
117 | } | |
118 | ||
119 | func (m *Dns) GetRrttl() uint32 { | |
120 | if m != nil && m.Rrttl != nil { | |
121 | return *m.Rrttl | |
122 | } | |
123 | return 0 | |
124 | } | |
125 | ||
126 | func (m *Dns) GetRdata() [][]byte { | |
127 | if m != nil { | |
128 | return m.Rdata | |
129 | } | |
130 | return nil | |
131 | } | |
132 | ||
133 | func init() { | |
134 | proto.RegisterType((*Dns)(nil), "nmsg.base.Dns") | |
135 | } | |
136 | ||
137 | func init() { proto.RegisterFile("dns.proto", fileDescriptor0) } | |
138 | ||
139 | var fileDescriptor0 = []byte{ | |
140 | // 148 bytes of a gzipped FileDescriptorProto | |
141 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0xc9, 0x2b, 0xd6, | |
142 | 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, 0xd7, 0x4b, 0x4a, 0x2c, 0x4e, | |
143 | 0x55, 0x9a, 0xcc, 0xc8, 0xc5, 0xec, 0x92, 0x57, 0x2c, 0xc4, 0xcf, 0xc5, 0x5e, 0x9c, 0x9a, 0x5c, | |
144 | 0x92, 0x99, 0x9f, 0x27, 0xc1, 0xa6, 0xc0, 0xa8, 0xc1, 0x2b, 0xc4, 0xcb, 0xc5, 0x5a, 0x98, 0x97, | |
145 | 0x98, 0x9b, 0x2a, 0xc1, 0x0e, 0xe4, 0xf2, 0x80, 0xb9, 0x25, 0x95, 0x05, 0xa9, 0x12, 0x1c, 0x60, | |
146 | 0x59, 0x3e, 0x2e, 0xb6, 0xc2, 0xe4, 0x9c, 0xc4, 0xe2, 0x62, 0x09, 0x4e, 0x18, 0xbf, 0xa8, 0x08, | |
147 | 0xac, 0x9c, 0x11, 0xac, 0x1c, 0xcc, 0x07, 0xab, 0x67, 0x02, 0xcb, 0x03, 0x8d, 0x2f, 0x2a, 0x82, | |
148 | 0x68, 0x60, 0x86, 0x19, 0x0f, 0x54, 0x50, 0x92, 0x23, 0xc1, 0x02, 0xe7, 0xa6, 0x24, 0x96, 0x24, | |
149 | 0x4a, 0xb0, 0x2a, 0x30, 0x6b, 0xf0, 0x00, 0x02, 0x00, 0x00, 0xff, 0xff, 0x75, 0x4a, 0x12, 0x4c, | |
150 | 0xac, 0x00, 0x00, 0x00, | |
151 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | message Dns { | |
4 | optional uint32 section = 6; | |
5 | optional bytes qname = 7; | |
6 | optional uint32 qtype = 8; | |
7 | optional uint32 qclass = 9; | |
8 | optional bytes rrname = 1; | |
9 | optional uint32 rrtype = 2; | |
10 | optional uint32 rrclass = 3; | |
11 | optional uint32 rrttl = 4; | |
12 | repeated bytes rdata = 5; | |
13 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: dnsqr.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type DnsQRType int32 | |
16 | ||
17 | const ( | |
18 | DnsQRType_UDP_INVALID DnsQRType = 0 | |
19 | DnsQRType_UDP_QUERY_RESPONSE DnsQRType = 1 | |
20 | DnsQRType_UDP_UNANSWERED_QUERY DnsQRType = 2 | |
21 | DnsQRType_UDP_UNSOLICITED_RESPONSE DnsQRType = 3 | |
22 | DnsQRType_TCP DnsQRType = 4 | |
23 | DnsQRType_ICMP DnsQRType = 5 | |
24 | DnsQRType_UDP_QUERY_ONLY DnsQRType = 6 | |
25 | DnsQRType_UDP_RESPONSE_ONLY DnsQRType = 7 | |
26 | ) | |
27 | ||
28 | var DnsQRType_name = map[int32]string{ | |
29 | 0: "UDP_INVALID", | |
30 | 1: "UDP_QUERY_RESPONSE", | |
31 | 2: "UDP_UNANSWERED_QUERY", | |
32 | 3: "UDP_UNSOLICITED_RESPONSE", | |
33 | 4: "TCP", | |
34 | 5: "ICMP", | |
35 | 6: "UDP_QUERY_ONLY", | |
36 | 7: "UDP_RESPONSE_ONLY", | |
37 | } | |
38 | var DnsQRType_value = map[string]int32{ | |
39 | "UDP_INVALID": 0, | |
40 | "UDP_QUERY_RESPONSE": 1, | |
41 | "UDP_UNANSWERED_QUERY": 2, | |
42 | "UDP_UNSOLICITED_RESPONSE": 3, | |
43 | "TCP": 4, | |
44 | "ICMP": 5, | |
45 | "UDP_QUERY_ONLY": 6, | |
46 | "UDP_RESPONSE_ONLY": 7, | |
47 | } | |
48 | ||
49 | func (x DnsQRType) Enum() *DnsQRType { | |
50 | p := new(DnsQRType) | |
51 | *p = x | |
52 | return p | |
53 | } | |
54 | func (x DnsQRType) String() string { | |
55 | return proto.EnumName(DnsQRType_name, int32(x)) | |
56 | } | |
57 | func (x *DnsQRType) UnmarshalJSON(data []byte) error { | |
58 | value, err := proto.UnmarshalJSONEnum(DnsQRType_value, data, "DnsQRType") | |
59 | if err != nil { | |
60 | return err | |
61 | } | |
62 | *x = DnsQRType(value) | |
63 | return nil | |
64 | } | |
65 | func (DnsQRType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } | |
66 | ||
67 | type UdpChecksum int32 | |
68 | ||
69 | const ( | |
70 | UdpChecksum_ERROR UdpChecksum = 0 | |
71 | UdpChecksum_ABSENT UdpChecksum = 1 | |
72 | UdpChecksum_INCORRECT UdpChecksum = 2 | |
73 | UdpChecksum_CORRECT UdpChecksum = 3 | |
74 | ) | |
75 | ||
76 | var UdpChecksum_name = map[int32]string{ | |
77 | 0: "ERROR", | |
78 | 1: "ABSENT", | |
79 | 2: "INCORRECT", | |
80 | 3: "CORRECT", | |
81 | } | |
82 | var UdpChecksum_value = map[string]int32{ | |
83 | "ERROR": 0, | |
84 | "ABSENT": 1, | |
85 | "INCORRECT": 2, | |
86 | "CORRECT": 3, | |
87 | } | |
88 | ||
89 | func (x UdpChecksum) Enum() *UdpChecksum { | |
90 | p := new(UdpChecksum) | |
91 | *p = x | |
92 | return p | |
93 | } | |
94 | func (x UdpChecksum) String() string { | |
95 | return proto.EnumName(UdpChecksum_name, int32(x)) | |
96 | } | |
97 | func (x *UdpChecksum) UnmarshalJSON(data []byte) error { | |
98 | value, err := proto.UnmarshalJSONEnum(UdpChecksum_value, data, "UdpChecksum") | |
99 | if err != nil { | |
100 | return err | |
101 | } | |
102 | *x = UdpChecksum(value) | |
103 | return nil | |
104 | } | |
105 | func (UdpChecksum) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } | |
106 | ||
107 | type DnsQR struct { | |
108 | Type *DnsQRType `protobuf:"varint,1,req,name=type,enum=nmsg.base.DnsQRType" json:"type,omitempty"` | |
109 | QueryIp []byte `protobuf:"bytes,2,req,name=query_ip" json:"query_ip,omitempty"` | |
110 | ResponseIp []byte `protobuf:"bytes,3,req,name=response_ip" json:"response_ip,omitempty"` | |
111 | Proto *uint32 `protobuf:"varint,4,req,name=proto" json:"proto,omitempty"` | |
112 | QueryPort *uint32 `protobuf:"varint,5,req,name=query_port" json:"query_port,omitempty"` | |
113 | ResponsePort *uint32 `protobuf:"varint,6,req,name=response_port" json:"response_port,omitempty"` | |
114 | Id *uint32 `protobuf:"varint,7,req,name=id" json:"id,omitempty"` | |
115 | Qname []byte `protobuf:"bytes,8,opt,name=qname" json:"qname,omitempty"` | |
116 | Qtype *uint32 `protobuf:"varint,9,opt,name=qtype" json:"qtype,omitempty"` | |
117 | Qclass *uint32 `protobuf:"varint,10,opt,name=qclass" json:"qclass,omitempty"` | |
118 | Rcode *uint32 `protobuf:"varint,11,opt,name=rcode" json:"rcode,omitempty"` | |
119 | QueryPacket [][]byte `protobuf:"bytes,12,rep,name=query_packet" json:"query_packet,omitempty"` | |
120 | QueryTimeSec []int64 `protobuf:"varint,13,rep,name=query_time_sec" json:"query_time_sec,omitempty"` | |
121 | QueryTimeNsec []int32 `protobuf:"fixed32,14,rep,name=query_time_nsec" json:"query_time_nsec,omitempty"` | |
122 | ResponsePacket [][]byte `protobuf:"bytes,15,rep,name=response_packet" json:"response_packet,omitempty"` | |
123 | ResponseTimeSec []int64 `protobuf:"varint,16,rep,name=response_time_sec" json:"response_time_sec,omitempty"` | |
124 | ResponseTimeNsec []int32 `protobuf:"fixed32,17,rep,name=response_time_nsec" json:"response_time_nsec,omitempty"` | |
125 | Tcp []byte `protobuf:"bytes,18,opt,name=tcp" json:"tcp,omitempty"` | |
126 | Icmp []byte `protobuf:"bytes,19,opt,name=icmp" json:"icmp,omitempty"` | |
127 | Timeout *float64 `protobuf:"fixed64,20,opt,name=timeout" json:"timeout,omitempty"` | |
128 | UdpChecksum *UdpChecksum `protobuf:"varint,21,opt,name=udp_checksum,enum=nmsg.base.UdpChecksum" json:"udp_checksum,omitempty"` | |
129 | ResolverAddressZeroed *bool `protobuf:"varint,22,opt,name=resolver_address_zeroed" json:"resolver_address_zeroed,omitempty"` | |
130 | XXX_unrecognized []byte `json:"-"` | |
131 | } | |
132 | ||
133 | func (m *DnsQR) Reset() { *m = DnsQR{} } | |
134 | func (m *DnsQR) String() string { return proto.CompactTextString(m) } | |
135 | func (*DnsQR) ProtoMessage() {} | |
136 | func (*DnsQR) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } | |
137 | ||
138 | func (m *DnsQR) GetType() DnsQRType { | |
139 | if m != nil && m.Type != nil { | |
140 | return *m.Type | |
141 | } | |
142 | return DnsQRType_UDP_INVALID | |
143 | } | |
144 | ||
145 | func (m *DnsQR) GetQueryIp() []byte { | |
146 | if m != nil { | |
147 | return m.QueryIp | |
148 | } | |
149 | return nil | |
150 | } | |
151 | ||
152 | func (m *DnsQR) GetResponseIp() []byte { | |
153 | if m != nil { | |
154 | return m.ResponseIp | |
155 | } | |
156 | return nil | |
157 | } | |
158 | ||
159 | func (m *DnsQR) GetProto() uint32 { | |
160 | if m != nil && m.Proto != nil { | |
161 | return *m.Proto | |
162 | } | |
163 | return 0 | |
164 | } | |
165 | ||
166 | func (m *DnsQR) GetQueryPort() uint32 { | |
167 | if m != nil && m.QueryPort != nil { | |
168 | return *m.QueryPort | |
169 | } | |
170 | return 0 | |
171 | } | |
172 | ||
173 | func (m *DnsQR) GetResponsePort() uint32 { | |
174 | if m != nil && m.ResponsePort != nil { | |
175 | return *m.ResponsePort | |
176 | } | |
177 | return 0 | |
178 | } | |
179 | ||
180 | func (m *DnsQR) GetId() uint32 { | |
181 | if m != nil && m.Id != nil { | |
182 | return *m.Id | |
183 | } | |
184 | return 0 | |
185 | } | |
186 | ||
187 | func (m *DnsQR) GetQname() []byte { | |
188 | if m != nil { | |
189 | return m.Qname | |
190 | } | |
191 | return nil | |
192 | } | |
193 | ||
194 | func (m *DnsQR) GetQtype() uint32 { | |
195 | if m != nil && m.Qtype != nil { | |
196 | return *m.Qtype | |
197 | } | |
198 | return 0 | |
199 | } | |
200 | ||
201 | func (m *DnsQR) GetQclass() uint32 { | |
202 | if m != nil && m.Qclass != nil { | |
203 | return *m.Qclass | |
204 | } | |
205 | return 0 | |
206 | } | |
207 | ||
208 | func (m *DnsQR) GetRcode() uint32 { | |
209 | if m != nil && m.Rcode != nil { | |
210 | return *m.Rcode | |
211 | } | |
212 | return 0 | |
213 | } | |
214 | ||
215 | func (m *DnsQR) GetQueryPacket() [][]byte { | |
216 | if m != nil { | |
217 | return m.QueryPacket | |
218 | } | |
219 | return nil | |
220 | } | |
221 | ||
222 | func (m *DnsQR) GetQueryTimeSec() []int64 { | |
223 | if m != nil { | |
224 | return m.QueryTimeSec | |
225 | } | |
226 | return nil | |
227 | } | |
228 | ||
229 | func (m *DnsQR) GetQueryTimeNsec() []int32 { | |
230 | if m != nil { | |
231 | return m.QueryTimeNsec | |
232 | } | |
233 | return nil | |
234 | } | |
235 | ||
236 | func (m *DnsQR) GetResponsePacket() [][]byte { | |
237 | if m != nil { | |
238 | return m.ResponsePacket | |
239 | } | |
240 | return nil | |
241 | } | |
242 | ||
243 | func (m *DnsQR) GetResponseTimeSec() []int64 { | |
244 | if m != nil { | |
245 | return m.ResponseTimeSec | |
246 | } | |
247 | return nil | |
248 | } | |
249 | ||
250 | func (m *DnsQR) GetResponseTimeNsec() []int32 { | |
251 | if m != nil { | |
252 | return m.ResponseTimeNsec | |
253 | } | |
254 | return nil | |
255 | } | |
256 | ||
257 | func (m *DnsQR) GetTcp() []byte { | |
258 | if m != nil { | |
259 | return m.Tcp | |
260 | } | |
261 | return nil | |
262 | } | |
263 | ||
264 | func (m *DnsQR) GetIcmp() []byte { | |
265 | if m != nil { | |
266 | return m.Icmp | |
267 | } | |
268 | return nil | |
269 | } | |
270 | ||
271 | func (m *DnsQR) GetTimeout() float64 { | |
272 | if m != nil && m.Timeout != nil { | |
273 | return *m.Timeout | |
274 | } | |
275 | return 0 | |
276 | } | |
277 | ||
278 | func (m *DnsQR) GetUdpChecksum() UdpChecksum { | |
279 | if m != nil && m.UdpChecksum != nil { | |
280 | return *m.UdpChecksum | |
281 | } | |
282 | return UdpChecksum_ERROR | |
283 | } | |
284 | ||
285 | func (m *DnsQR) GetResolverAddressZeroed() bool { | |
286 | if m != nil && m.ResolverAddressZeroed != nil { | |
287 | return *m.ResolverAddressZeroed | |
288 | } | |
289 | return false | |
290 | } | |
291 | ||
292 | func init() { | |
293 | proto.RegisterType((*DnsQR)(nil), "nmsg.base.DnsQR") | |
294 | proto.RegisterEnum("nmsg.base.DnsQRType", DnsQRType_name, DnsQRType_value) | |
295 | proto.RegisterEnum("nmsg.base.UdpChecksum", UdpChecksum_name, UdpChecksum_value) | |
296 | } | |
297 | ||
298 | func init() { proto.RegisterFile("dnsqr.proto", fileDescriptor1) } | |
299 | ||
300 | var fileDescriptor1 = []byte{ | |
301 | // 491 bytes of a gzipped FileDescriptorProto | |
302 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x54, 0x92, 0xdb, 0x6e, 0x9b, 0x40, | |
303 | 0x10, 0x86, 0x6b, 0xe3, 0xe3, 0x70, 0xf4, 0xc6, 0x71, 0xb6, 0x55, 0xa5, 0x5a, 0xb9, 0xaa, 0xa2, | |
304 | 0xca, 0x17, 0x79, 0x82, 0xba, 0x98, 0x0b, 0x24, 0x17, 0x1c, 0xc0, 0xad, 0x72, 0x85, 0x28, 0xac, | |
305 | 0x5a, 0x2b, 0xe1, 0xb8, 0xb8, 0x52, 0xfa, 0x48, 0x7d, 0xb1, 0xbe, 0x46, 0x87, 0x25, 0xc1, 0xce, | |
306 | 0x1d, 0xf3, 0xfd, 0x33, 0xff, 0xfc, 0xcb, 0x2e, 0xc8, 0x49, 0xc6, 0xcb, 0x6a, 0x55, 0x54, 0x79, | |
307 | 0x9d, 0x93, 0x69, 0x96, 0xf2, 0x9f, 0xab, 0x1f, 0x11, 0x67, 0xd7, 0xff, 0x24, 0x18, 0x6e, 0x32, | |
308 | 0x7e, 0xe7, 0x91, 0x6b, 0x18, 0xd4, 0x4f, 0x05, 0xa3, 0xbd, 0x65, 0xff, 0xa3, 0x76, 0x3b, 0x5f, | |
309 | 0x75, 0x3d, 0x2b, 0xa1, 0x07, 0xa8, 0x11, 0x03, 0x26, 0xe5, 0x91, 0x55, 0x4f, 0xe1, 0xa1, 0xa0, | |
310 | 0x7d, 0xec, 0x53, 0xc8, 0x05, 0xc8, 0x15, 0xe3, 0x45, 0x9e, 0x71, 0xd6, 0x40, 0x49, 0x40, 0x15, | |
311 | 0x86, 0x62, 0x11, 0x1d, 0x60, 0xa9, 0x12, 0x02, 0xd0, 0x4e, 0x15, 0x79, 0x55, 0xd3, 0xa1, 0x60, | |
312 | 0x97, 0xa0, 0x76, 0x73, 0x02, 0x8f, 0x04, 0x06, 0xe8, 0x1f, 0x12, 0x3a, 0x16, 0xdf, 0xe8, 0x52, | |
313 | 0x66, 0x51, 0xca, 0xe8, 0x64, 0xd9, 0x6b, 0x4d, 0x4b, 0x11, 0x70, 0x8a, 0xa5, 0x4a, 0x34, 0x18, | |
314 | 0x95, 0xf1, 0x63, 0xc4, 0x39, 0x05, 0x51, 0xa3, 0x5c, 0xc5, 0x79, 0xc2, 0xa8, 0x2c, 0xca, 0x39, | |
315 | 0x28, 0xcf, 0x3b, 0xa3, 0xf8, 0x81, 0xd5, 0x54, 0x59, 0x4a, 0xe8, 0xb1, 0x00, 0xad, 0xa5, 0xf5, | |
316 | 0x21, 0x65, 0x21, 0x67, 0x31, 0x55, 0x91, 0x4b, 0xe4, 0x0a, 0xf4, 0x33, 0x9e, 0x35, 0x82, 0x86, | |
317 | 0x82, 0xde, 0x08, 0xa7, 0x98, 0xad, 0x93, 0x2e, 0x9c, 0xde, 0xc2, 0xac, 0x13, 0x3a, 0x33, 0x43, | |
318 | 0x98, 0xbd, 0x03, 0xf2, 0x5a, 0x12, 0x7e, 0x33, 0xe1, 0x27, 0x83, 0x54, 0xc7, 0x05, 0x25, 0xe2, | |
319 | 0x44, 0x0a, 0x0c, 0x0e, 0x71, 0x5a, 0xd0, 0x0b, 0x51, 0xe9, 0x30, 0x6e, 0xba, 0xf3, 0x63, 0x4d, | |
320 | 0xe7, 0x08, 0x7a, 0xe4, 0x13, 0x28, 0xc7, 0xa4, 0x08, 0xe3, 0x5f, 0x2c, 0x7e, 0xe0, 0xc7, 0x94, | |
321 | 0x5e, 0x22, 0xd5, 0x6e, 0x17, 0x67, 0x17, 0xb3, 0x4f, 0x0a, 0xf3, 0x59, 0x25, 0x1f, 0xe0, 0x0a, | |
322 | 0xb7, 0xe6, 0x8f, 0xbf, 0x59, 0x15, 0x46, 0x49, 0x82, 0xdf, 0x3c, 0xfc, 0xc3, 0xaa, 0x9c, 0x25, | |
323 | 0x74, 0x81, 0x83, 0x93, 0x9b, 0xbf, 0x3d, 0x98, 0x9e, 0x6e, 0x52, 0x07, 0x79, 0xbf, 0xd9, 0x85, | |
324 | 0xb6, 0xf3, 0x6d, 0xbd, 0xb5, 0x37, 0xc6, 0x1b, 0xfc, 0x35, 0xa4, 0x01, 0x77, 0x7b, 0xcb, 0xbb, | |
325 | 0x0f, 0x3d, 0xcb, 0xdf, 0xb9, 0x8e, 0x6f, 0x19, 0x3d, 0x42, 0x61, 0xde, 0xf0, 0xbd, 0xb3, 0x76, | |
326 | 0xfc, 0xef, 0x96, 0x67, 0x6d, 0xda, 0x16, 0xa3, 0x4f, 0xde, 0x03, 0x6d, 0x15, 0xdf, 0xdd, 0xda, | |
327 | 0xa6, 0x1d, 0xa0, 0xd4, 0xcd, 0x49, 0x64, 0x0c, 0x52, 0x60, 0xee, 0x8c, 0x01, 0x99, 0xc0, 0xc0, | |
328 | 0x36, 0xbf, 0xee, 0x8c, 0x21, 0xbe, 0x03, 0xed, 0xb4, 0xc2, 0x75, 0xb6, 0xf7, 0xc6, 0x08, 0xdf, | |
329 | 0xc1, 0xac, 0x61, 0x2f, 0x83, 0x2d, 0x1e, 0xdf, 0x7c, 0xc6, 0x78, 0x67, 0x87, 0x9b, 0xc2, 0xd0, | |
330 | 0xf2, 0x3c, 0xd7, 0xc3, 0x9c, 0x00, 0xa3, 0xf5, 0x17, 0xdf, 0x72, 0x02, 0xcc, 0xa6, 0xc2, 0xd4, | |
331 | 0x76, 0x4c, 0xd7, 0xf3, 0x2c, 0x33, 0xc0, 0x40, 0x32, 0x8c, 0x5f, 0x0a, 0xe9, 0x7f, 0x00, 0x00, | |
332 | 0x00, 0xff, 0xff, 0x04, 0x82, 0x9b, 0xdb, 0xf1, 0x02, 0x00, 0x00, | |
333 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | enum DnsQRType { | |
4 | UDP_INVALID = 0; | |
5 | UDP_QUERY_RESPONSE = 1; | |
6 | UDP_UNANSWERED_QUERY = 2; | |
7 | UDP_UNSOLICITED_RESPONSE = 3; | |
8 | TCP = 4; | |
9 | ICMP = 5; | |
10 | UDP_QUERY_ONLY = 6; | |
11 | UDP_RESPONSE_ONLY = 7; | |
12 | } | |
13 | ||
14 | enum UdpChecksum { | |
15 | ERROR = 0; | |
16 | ABSENT = 1; | |
17 | INCORRECT = 2; | |
18 | CORRECT = 3; | |
19 | } | |
20 | ||
21 | message DnsQR { | |
22 | required DnsQRType type = 1; | |
23 | ||
24 | // the 9-tuple | |
25 | ||
26 | required bytes query_ip = 2; | |
27 | required bytes response_ip = 3; | |
28 | required uint32 proto = 4; | |
29 | required uint32 query_port = 5; | |
30 | required uint32 response_port = 6; | |
31 | ||
32 | required uint32 id = 7; | |
33 | optional bytes qname = 8; | |
34 | optional uint32 qtype = 9; | |
35 | optional uint32 qclass = 10; | |
36 | ||
37 | // rcode from the response | |
38 | ||
39 | optional uint32 rcode = 11; | |
40 | ||
41 | // packet data | |
42 | ||
43 | repeated bytes query_packet = 12; | |
44 | repeated int64 query_time_sec = 13; | |
45 | repeated sfixed32 query_time_nsec = 14; | |
46 | ||
47 | repeated bytes response_packet = 15; | |
48 | repeated int64 response_time_sec = 16; | |
49 | repeated sfixed32 response_time_nsec = 17; | |
50 | ||
51 | // only used if type = TCP | |
52 | ||
53 | optional bytes tcp = 18; | |
54 | ||
55 | // only used if type = ICMP | |
56 | ||
57 | optional bytes icmp = 19; | |
58 | ||
59 | // only set for UDP_UNANSWERED_QUERY | |
60 | ||
61 | optional double timeout = 20; | |
62 | ||
63 | // the result of UDP checksum verification of the response datagram. | |
64 | // note that the query datagram isn't checksummed, since a) the relevant | |
65 | // information from the query is almost always included in the response, | |
66 | // b) when capturing from the perspective of an initiator, the outbound | |
67 | // query is commonly subject to UDP checksum offload and will be incorrect | |
68 | // anyway. | |
69 | ||
70 | optional UdpChecksum udp_checksum = 21; | |
71 | ||
72 | // set if the address of the initiator was zeroed. | |
73 | ||
74 | optional bool resolver_address_zeroed = 22; | |
75 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: email.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type EmailType int32 | |
16 | ||
17 | const ( | |
18 | EmailType_unknown EmailType = 0 | |
19 | EmailType_spamtrap EmailType = 1 | |
20 | EmailType_rej_network EmailType = 2 | |
21 | EmailType_rej_content EmailType = 3 | |
22 | EmailType_rej_user EmailType = 4 | |
23 | ) | |
24 | ||
25 | var EmailType_name = map[int32]string{ | |
26 | 0: "unknown", | |
27 | 1: "spamtrap", | |
28 | 2: "rej_network", | |
29 | 3: "rej_content", | |
30 | 4: "rej_user", | |
31 | } | |
32 | var EmailType_value = map[string]int32{ | |
33 | "unknown": 0, | |
34 | "spamtrap": 1, | |
35 | "rej_network": 2, | |
36 | "rej_content": 3, | |
37 | "rej_user": 4, | |
38 | } | |
39 | ||
40 | func (x EmailType) Enum() *EmailType { | |
41 | p := new(EmailType) | |
42 | *p = x | |
43 | return p | |
44 | } | |
45 | func (x EmailType) String() string { | |
46 | return proto.EnumName(EmailType_name, int32(x)) | |
47 | } | |
48 | func (x *EmailType) UnmarshalJSON(data []byte) error { | |
49 | value, err := proto.UnmarshalJSONEnum(EmailType_value, data, "EmailType") | |
50 | if err != nil { | |
51 | return err | |
52 | } | |
53 | *x = EmailType(value) | |
54 | return nil | |
55 | } | |
56 | func (EmailType) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } | |
57 | ||
58 | type Email struct { | |
59 | Type *EmailType `protobuf:"varint,8,opt,name=type,enum=nmsg.base.EmailType" json:"type,omitempty"` | |
60 | Headers []byte `protobuf:"bytes,2,opt,name=headers" json:"headers,omitempty"` | |
61 | Srcip []byte `protobuf:"bytes,3,opt,name=srcip" json:"srcip,omitempty"` | |
62 | Srchost []byte `protobuf:"bytes,4,opt,name=srchost" json:"srchost,omitempty"` | |
63 | Helo []byte `protobuf:"bytes,5,opt,name=helo" json:"helo,omitempty"` | |
64 | From []byte `protobuf:"bytes,6,opt,name=from" json:"from,omitempty"` | |
65 | Rcpt [][]byte `protobuf:"bytes,7,rep,name=rcpt" json:"rcpt,omitempty"` | |
66 | Bodyurl [][]byte `protobuf:"bytes,9,rep,name=bodyurl" json:"bodyurl,omitempty"` | |
67 | Body []byte `protobuf:"bytes,10,opt,name=body" json:"body,omitempty"` | |
68 | XXX_unrecognized []byte `json:"-"` | |
69 | } | |
70 | ||
71 | func (m *Email) Reset() { *m = Email{} } | |
72 | func (m *Email) String() string { return proto.CompactTextString(m) } | |
73 | func (*Email) ProtoMessage() {} | |
74 | func (*Email) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } | |
75 | ||
76 | func (m *Email) GetType() EmailType { | |
77 | if m != nil && m.Type != nil { | |
78 | return *m.Type | |
79 | } | |
80 | return EmailType_unknown | |
81 | } | |
82 | ||
83 | func (m *Email) GetHeaders() []byte { | |
84 | if m != nil { | |
85 | return m.Headers | |
86 | } | |
87 | return nil | |
88 | } | |
89 | ||
90 | func (m *Email) GetSrcip() []byte { | |
91 | if m != nil { | |
92 | return m.Srcip | |
93 | } | |
94 | return nil | |
95 | } | |
96 | ||
97 | func (m *Email) GetSrchost() []byte { | |
98 | if m != nil { | |
99 | return m.Srchost | |
100 | } | |
101 | return nil | |
102 | } | |
103 | ||
104 | func (m *Email) GetHelo() []byte { | |
105 | if m != nil { | |
106 | return m.Helo | |
107 | } | |
108 | return nil | |
109 | } | |
110 | ||
111 | func (m *Email) GetFrom() []byte { | |
112 | if m != nil { | |
113 | return m.From | |
114 | } | |
115 | return nil | |
116 | } | |
117 | ||
118 | func (m *Email) GetRcpt() [][]byte { | |
119 | if m != nil { | |
120 | return m.Rcpt | |
121 | } | |
122 | return nil | |
123 | } | |
124 | ||
125 | func (m *Email) GetBodyurl() [][]byte { | |
126 | if m != nil { | |
127 | return m.Bodyurl | |
128 | } | |
129 | return nil | |
130 | } | |
131 | ||
132 | func (m *Email) GetBody() []byte { | |
133 | if m != nil { | |
134 | return m.Body | |
135 | } | |
136 | return nil | |
137 | } | |
138 | ||
139 | func init() { | |
140 | proto.RegisterType((*Email)(nil), "nmsg.base.Email") | |
141 | proto.RegisterEnum("nmsg.base.EmailType", EmailType_name, EmailType_value) | |
142 | } | |
143 | ||
144 | func init() { proto.RegisterFile("email.proto", fileDescriptor2) } | |
145 | ||
146 | var fileDescriptor2 = []byte{ | |
147 | // 222 bytes of a gzipped FileDescriptorProto | |
148 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x44, 0x8e, 0x41, 0x4e, 0xc3, 0x30, | |
149 | 0x10, 0x45, 0x49, 0x93, 0x90, 0x66, 0x52, 0xc0, 0x8a, 0x58, 0xcc, 0xb2, 0xea, 0x0a, 0xb1, 0xc8, | |
150 | 0x82, 0x3b, 0x70, 0x03, 0xc4, 0x16, 0xb9, 0xe9, 0x40, 0x4a, 0x13, 0x8f, 0x35, 0x76, 0x54, 0xf5, | |
151 | 0x40, 0xdc, 0x13, 0xdb, 0x28, 0x74, 0xf9, 0xdf, 0x7b, 0xb6, 0x06, 0x1a, 0x9a, 0xf4, 0x71, 0xec, | |
152 | 0xac, 0xb0, 0xe7, 0xb6, 0x36, 0x93, 0xfb, 0xea, 0xf6, 0xda, 0xd1, 0xee, 0x27, 0x83, 0xf2, 0x35, | |
153 | 0xaa, 0x76, 0x07, 0x85, 0xbf, 0x58, 0xc2, 0xf5, 0x36, 0x7b, 0xba, 0x7f, 0x79, 0xec, 0xfe, 0x9b, | |
154 | 0x2e, 0xf9, 0xb7, 0xe0, 0xda, 0x07, 0xa8, 0x06, 0xd2, 0x07, 0x12, 0x87, 0xab, 0x90, 0x6d, 0xda, | |
155 | 0x3b, 0x28, 0x9d, 0xf4, 0x47, 0x8b, 0x79, 0x9a, 0xc1, 0x87, 0x39, 0xb0, 0xf3, 0x58, 0x24, 0xb0, | |
156 | 0x81, 0x62, 0xa0, 0x91, 0xb1, 0x5c, 0xd6, 0xa7, 0xf0, 0x84, 0xb7, 0xcb, 0x92, 0xde, 0x7a, 0xac, | |
157 | 0xb6, 0xf9, 0xdf, 0xd3, 0x3d, 0x1f, 0x2e, 0xb3, 0x8c, 0x58, 0x27, 0x10, 0x74, 0x04, 0x08, 0x31, | |
158 | 0x7e, 0x7e, 0x87, 0xfa, 0x7a, 0x46, 0x03, 0xd5, 0x6c, 0x4e, 0x86, 0xcf, 0x46, 0xdd, 0x84, 0x6e, | |
159 | 0xed, 0xac, 0x9e, 0xbc, 0x68, 0xab, 0xb2, 0xf0, 0x4d, 0x23, 0xf4, 0xfd, 0x61, 0xc8, 0x9f, 0x59, | |
160 | 0x4e, 0x6a, 0xb5, 0x80, 0x9e, 0x8d, 0x27, 0xe3, 0x55, 0x1e, 0xfb, 0x08, 0x66, 0x47, 0xa2, 0x8a, | |
161 | 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6b, 0xe2, 0x02, 0x36, 0x18, 0x01, 0x00, 0x00, | |
162 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | enum EmailType { | |
4 | unknown = 0; | |
5 | spamtrap = 1; | |
6 | rej_network = 2; | |
7 | rej_content = 3; | |
8 | rej_user = 4; | |
9 | } | |
10 | ||
11 | message Email { | |
12 | optional EmailType type = 8; | |
13 | optional bytes headers = 2; | |
14 | optional bytes srcip = 3; | |
15 | optional bytes srchost = 4; | |
16 | optional bytes helo = 5; | |
17 | optional bytes from = 6; | |
18 | repeated bytes rcpt = 7; | |
19 | repeated bytes bodyurl = 9; | |
20 | optional bytes body = 10; | |
21 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: encode.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type EncodeType int32 | |
16 | ||
17 | const ( | |
18 | EncodeType_TEXT EncodeType = 0 | |
19 | EncodeType_JSON EncodeType = 1 | |
20 | EncodeType_YAML EncodeType = 2 | |
21 | EncodeType_MSGPACK EncodeType = 3 | |
22 | EncodeType_XML EncodeType = 4 | |
23 | ) | |
24 | ||
25 | var EncodeType_name = map[int32]string{ | |
26 | 0: "TEXT", | |
27 | 1: "JSON", | |
28 | 2: "YAML", | |
29 | 3: "MSGPACK", | |
30 | 4: "XML", | |
31 | } | |
32 | var EncodeType_value = map[string]int32{ | |
33 | "TEXT": 0, | |
34 | "JSON": 1, | |
35 | "YAML": 2, | |
36 | "MSGPACK": 3, | |
37 | "XML": 4, | |
38 | } | |
39 | ||
40 | func (x EncodeType) Enum() *EncodeType { | |
41 | p := new(EncodeType) | |
42 | *p = x | |
43 | return p | |
44 | } | |
45 | func (x EncodeType) String() string { | |
46 | return proto.EnumName(EncodeType_name, int32(x)) | |
47 | } | |
48 | func (x *EncodeType) UnmarshalJSON(data []byte) error { | |
49 | value, err := proto.UnmarshalJSONEnum(EncodeType_value, data, "EncodeType") | |
50 | if err != nil { | |
51 | return err | |
52 | } | |
53 | *x = EncodeType(value) | |
54 | return nil | |
55 | } | |
56 | func (EncodeType) EnumDescriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } | |
57 | ||
58 | type Encode struct { | |
59 | Type *EncodeType `protobuf:"varint,1,req,name=type,enum=nmsg.base.EncodeType" json:"type,omitempty"` | |
60 | Payload []byte `protobuf:"bytes,2,req,name=payload" json:"payload,omitempty"` | |
61 | XXX_unrecognized []byte `json:"-"` | |
62 | } | |
63 | ||
64 | func (m *Encode) Reset() { *m = Encode{} } | |
65 | func (m *Encode) String() string { return proto.CompactTextString(m) } | |
66 | func (*Encode) ProtoMessage() {} | |
67 | func (*Encode) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } | |
68 | ||
69 | func (m *Encode) GetType() EncodeType { | |
70 | if m != nil && m.Type != nil { | |
71 | return *m.Type | |
72 | } | |
73 | return EncodeType_TEXT | |
74 | } | |
75 | ||
76 | func (m *Encode) GetPayload() []byte { | |
77 | if m != nil { | |
78 | return m.Payload | |
79 | } | |
80 | return nil | |
81 | } | |
82 | ||
83 | func init() { | |
84 | proto.RegisterType((*Encode)(nil), "nmsg.base.Encode") | |
85 | proto.RegisterEnum("nmsg.base.EncodeType", EncodeType_name, EncodeType_value) | |
86 | } | |
87 | ||
88 | func init() { proto.RegisterFile("encode.proto", fileDescriptor3) } | |
89 | ||
90 | var fileDescriptor3 = []byte{ | |
91 | // 148 bytes of a gzipped FileDescriptorProto | |
92 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0xcd, 0x4b, 0xce, | |
93 | 0x4f, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, 0xd7, 0x4b, | |
94 | 0x4a, 0x2c, 0x4e, 0x55, 0xb2, 0xe3, 0x62, 0x73, 0x05, 0x4b, 0x09, 0x29, 0x73, 0xb1, 0x94, 0x54, | |
95 | 0x16, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x69, 0xf0, 0x19, 0x89, 0xea, 0xc1, 0xd5, 0xe8, 0x41, 0x14, | |
96 | 0x84, 0x00, 0x25, 0x85, 0xf8, 0xb9, 0xd8, 0x0b, 0x12, 0x2b, 0x73, 0xf2, 0x13, 0x53, 0x24, 0x98, | |
97 | 0x80, 0xea, 0x78, 0xb4, 0x1c, 0xb8, 0xb8, 0x90, 0xa4, 0x39, 0xb8, 0x58, 0x42, 0x5c, 0x23, 0x42, | |
98 | 0x04, 0x18, 0x40, 0x2c, 0xaf, 0x60, 0x7f, 0x3f, 0x01, 0x46, 0x10, 0x2b, 0xd2, 0xd1, 0xd7, 0x47, | |
99 | 0x80, 0x49, 0x88, 0x9b, 0x8b, 0xdd, 0x37, 0xd8, 0x3d, 0xc0, 0xd1, 0xd9, 0x5b, 0x80, 0x59, 0x88, | |
100 | 0x9d, 0x8b, 0x39, 0x02, 0x28, 0xca, 0x02, 0x08, 0x00, 0x00, 0xff, 0xff, 0xb9, 0x9e, 0xfe, 0xff, | |
101 | 0x9b, 0x00, 0x00, 0x00, | |
102 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | enum EncodeType { | |
4 | TEXT = 0; | |
5 | JSON = 1; | |
6 | YAML = 2; | |
7 | MSGPACK = 3; | |
8 | XML = 4; | |
9 | } | |
10 | ||
11 | message Encode { | |
12 | required EncodeType type = 1; | |
13 | required bytes payload = 2; | |
14 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: http.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type HttpType int32 | |
16 | ||
17 | const ( | |
18 | // unknown = 0; | |
19 | HttpType_sinkhole HttpType = 1 | |
20 | ) | |
21 | ||
22 | var HttpType_name = map[int32]string{ | |
23 | 1: "sinkhole", | |
24 | } | |
25 | var HttpType_value = map[string]int32{ | |
26 | "sinkhole": 1, | |
27 | } | |
28 | ||
29 | func (x HttpType) Enum() *HttpType { | |
30 | p := new(HttpType) | |
31 | *p = x | |
32 | return p | |
33 | } | |
34 | func (x HttpType) String() string { | |
35 | return proto.EnumName(HttpType_name, int32(x)) | |
36 | } | |
37 | func (x *HttpType) UnmarshalJSON(data []byte) error { | |
38 | value, err := proto.UnmarshalJSONEnum(HttpType_value, data, "HttpType") | |
39 | if err != nil { | |
40 | return err | |
41 | } | |
42 | *x = HttpType(value) | |
43 | return nil | |
44 | } | |
45 | func (HttpType) EnumDescriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } | |
46 | ||
47 | type Http struct { | |
48 | Type *HttpType `protobuf:"varint,1,req,name=type,enum=nmsg.base.HttpType" json:"type,omitempty"` | |
49 | Srcip []byte `protobuf:"bytes,2,opt,name=srcip" json:"srcip,omitempty"` | |
50 | Srchost []byte `protobuf:"bytes,3,opt,name=srchost" json:"srchost,omitempty"` | |
51 | Srcport *uint32 `protobuf:"varint,4,opt,name=srcport" json:"srcport,omitempty"` | |
52 | Dstip []byte `protobuf:"bytes,5,opt,name=dstip" json:"dstip,omitempty"` | |
53 | Dstport *uint32 `protobuf:"varint,6,opt,name=dstport" json:"dstport,omitempty"` | |
54 | Request []byte `protobuf:"bytes,7,opt,name=request" json:"request,omitempty"` | |
55 | P0FGenre []byte `protobuf:"bytes,65,opt,name=p0f_genre" json:"p0f_genre,omitempty"` | |
56 | P0FDetail []byte `protobuf:"bytes,66,opt,name=p0f_detail" json:"p0f_detail,omitempty"` | |
57 | P0FDist *int32 `protobuf:"varint,67,opt,name=p0f_dist" json:"p0f_dist,omitempty"` | |
58 | P0FLink []byte `protobuf:"bytes,68,opt,name=p0f_link" json:"p0f_link,omitempty"` | |
59 | P0FTos []byte `protobuf:"bytes,69,opt,name=p0f_tos" json:"p0f_tos,omitempty"` | |
60 | P0FFw *uint32 `protobuf:"varint,70,opt,name=p0f_fw" json:"p0f_fw,omitempty"` | |
61 | P0FNat *uint32 `protobuf:"varint,71,opt,name=p0f_nat" json:"p0f_nat,omitempty"` | |
62 | P0FReal *uint32 `protobuf:"varint,72,opt,name=p0f_real" json:"p0f_real,omitempty"` | |
63 | P0FScore *int32 `protobuf:"varint,73,opt,name=p0f_score" json:"p0f_score,omitempty"` | |
64 | P0FMflags *uint32 `protobuf:"varint,74,opt,name=p0f_mflags" json:"p0f_mflags,omitempty"` | |
65 | P0FUptime *int32 `protobuf:"varint,75,opt,name=p0f_uptime" json:"p0f_uptime,omitempty"` | |
66 | XXX_unrecognized []byte `json:"-"` | |
67 | } | |
68 | ||
69 | func (m *Http) Reset() { *m = Http{} } | |
70 | func (m *Http) String() string { return proto.CompactTextString(m) } | |
71 | func (*Http) ProtoMessage() {} | |
72 | func (*Http) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } | |
73 | ||
74 | func (m *Http) GetType() HttpType { | |
75 | if m != nil && m.Type != nil { | |
76 | return *m.Type | |
77 | } | |
78 | return HttpType_sinkhole | |
79 | } | |
80 | ||
81 | func (m *Http) GetSrcip() []byte { | |
82 | if m != nil { | |
83 | return m.Srcip | |
84 | } | |
85 | return nil | |
86 | } | |
87 | ||
88 | func (m *Http) GetSrchost() []byte { | |
89 | if m != nil { | |
90 | return m.Srchost | |
91 | } | |
92 | return nil | |
93 | } | |
94 | ||
95 | func (m *Http) GetSrcport() uint32 { | |
96 | if m != nil && m.Srcport != nil { | |
97 | return *m.Srcport | |
98 | } | |
99 | return 0 | |
100 | } | |
101 | ||
102 | func (m *Http) GetDstip() []byte { | |
103 | if m != nil { | |
104 | return m.Dstip | |
105 | } | |
106 | return nil | |
107 | } | |
108 | ||
109 | func (m *Http) GetDstport() uint32 { | |
110 | if m != nil && m.Dstport != nil { | |
111 | return *m.Dstport | |
112 | } | |
113 | return 0 | |
114 | } | |
115 | ||
116 | func (m *Http) GetRequest() []byte { | |
117 | if m != nil { | |
118 | return m.Request | |
119 | } | |
120 | return nil | |
121 | } | |
122 | ||
123 | func (m *Http) GetP0FGenre() []byte { | |
124 | if m != nil { | |
125 | return m.P0FGenre | |
126 | } | |
127 | return nil | |
128 | } | |
129 | ||
130 | func (m *Http) GetP0FDetail() []byte { | |
131 | if m != nil { | |
132 | return m.P0FDetail | |
133 | } | |
134 | return nil | |
135 | } | |
136 | ||
137 | func (m *Http) GetP0FDist() int32 { | |
138 | if m != nil && m.P0FDist != nil { | |
139 | return *m.P0FDist | |
140 | } | |
141 | return 0 | |
142 | } | |
143 | ||
144 | func (m *Http) GetP0FLink() []byte { | |
145 | if m != nil { | |
146 | return m.P0FLink | |
147 | } | |
148 | return nil | |
149 | } | |
150 | ||
151 | func (m *Http) GetP0FTos() []byte { | |
152 | if m != nil { | |
153 | return m.P0FTos | |
154 | } | |
155 | return nil | |
156 | } | |
157 | ||
158 | func (m *Http) GetP0FFw() uint32 { | |
159 | if m != nil && m.P0FFw != nil { | |
160 | return *m.P0FFw | |
161 | } | |
162 | return 0 | |
163 | } | |
164 | ||
165 | func (m *Http) GetP0FNat() uint32 { | |
166 | if m != nil && m.P0FNat != nil { | |
167 | return *m.P0FNat | |
168 | } | |
169 | return 0 | |
170 | } | |
171 | ||
172 | func (m *Http) GetP0FReal() uint32 { | |
173 | if m != nil && m.P0FReal != nil { | |
174 | return *m.P0FReal | |
175 | } | |
176 | return 0 | |
177 | } | |
178 | ||
179 | func (m *Http) GetP0FScore() int32 { | |
180 | if m != nil && m.P0FScore != nil { | |
181 | return *m.P0FScore | |
182 | } | |
183 | return 0 | |
184 | } | |
185 | ||
186 | func (m *Http) GetP0FMflags() uint32 { | |
187 | if m != nil && m.P0FMflags != nil { | |
188 | return *m.P0FMflags | |
189 | } | |
190 | return 0 | |
191 | } | |
192 | ||
193 | func (m *Http) GetP0FUptime() int32 { | |
194 | if m != nil && m.P0FUptime != nil { | |
195 | return *m.P0FUptime | |
196 | } | |
197 | return 0 | |
198 | } | |
199 | ||
200 | func init() { | |
201 | proto.RegisterType((*Http)(nil), "nmsg.base.Http") | |
202 | proto.RegisterEnum("nmsg.base.HttpType", HttpType_name, HttpType_value) | |
203 | } | |
204 | ||
205 | func init() { proto.RegisterFile("http.proto", fileDescriptor4) } | |
206 | ||
207 | var fileDescriptor4 = []byte{ | |
208 | // 268 bytes of a gzipped FileDescriptorProto | |
209 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0xd0, 0x4d, 0x4f, 0xf3, 0x30, | |
210 | 0x0c, 0x07, 0x70, 0xb5, 0x4f, 0xbb, 0x75, 0xd6, 0xb6, 0x67, 0x94, 0x8b, 0x8f, 0x83, 0xd3, 0xc4, | |
211 | 0xa1, 0x42, 0x7c, 0x03, 0xde, 0x07, 0x5c, 0xb9, 0xa3, 0xb2, 0xa5, 0x2f, 0x22, 0x6d, 0x42, 0xe2, | |
212 | 0x09, 0xf1, 0x41, 0xf9, 0x3e, 0x38, 0x56, 0x3b, 0x71, 0xf4, 0xef, 0x6f, 0xc7, 0x56, 0x00, 0x1a, | |
213 | 0x22, 0x5b, 0x58, 0x67, 0xc8, 0xe4, 0xb3, 0xbe, 0xf3, 0x75, 0xf1, 0x5e, 0x7a, 0x75, 0xfe, 0x13, | |
214 | 0x43, 0xb2, 0xe5, 0x24, 0x3f, 0x83, 0x84, 0xbe, 0xad, 0xc2, 0x68, 0x1d, 0x6f, 0x96, 0x57, 0xa7, | |
215 | 0xc5, 0xb1, 0xa5, 0x08, 0xf1, 0x2b, 0x47, 0xf9, 0x02, 0x52, 0xef, 0x76, 0xad, 0xc5, 0x78, 0x1d, | |
216 | 0x6d, 0xe6, 0xf9, 0x7f, 0x98, 0x72, 0xd9, 0x18, 0x4f, 0xf8, 0xef, 0x0f, 0x58, 0xe3, 0x08, 0x13, | |
217 | 0x86, 0x45, 0x18, 0xd8, 0x7b, 0xe2, 0x81, 0x74, 0xcc, 0xb9, 0x94, 0x7c, 0x22, 0x39, 0x83, 0x53, | |
218 | 0x9f, 0x07, 0xc5, 0x2f, 0x4c, 0xa5, 0xe3, 0x04, 0x66, 0xf6, 0xb2, 0x7a, 0xab, 0x55, 0xef, 0x14, | |
219 | 0x5e, 0x0b, 0xe5, 0x00, 0x81, 0xf6, 0x8a, 0xca, 0x56, 0xe3, 0x8d, 0xd8, 0x0a, 0x32, 0xb1, 0x96, | |
220 | 0x07, 0x6f, 0x59, 0xd2, 0x51, 0x74, 0xdb, 0x7f, 0xe0, 0xdd, 0xb8, 0x2c, 0x08, 0x19, 0x8f, 0xf7, | |
221 | 0x02, 0x4b, 0x98, 0x04, 0xa8, 0xbe, 0xf0, 0x61, 0x5c, 0x1e, 0xea, 0xbe, 0x24, 0x7c, 0x14, 0x18, | |
222 | 0xde, 0x70, 0xaa, 0xd4, 0xb8, 0x15, 0x19, 0xce, 0xf1, 0x3b, 0xc3, 0xe7, 0x3c, 0xc9, 0xa2, 0xe1, | |
223 | 0x9c, 0xae, 0xd2, 0x65, 0xed, 0xf1, 0x59, 0xda, 0x06, 0x3b, 0x58, 0x6a, 0x3b, 0x85, 0x2f, 0xa1, | |
224 | 0xef, 0x02, 0x21, 0x3b, 0xfe, 0xdb, 0x1c, 0x32, 0xcf, 0x87, 0x35, 0x46, 0xab, 0x55, 0xf4, 0x1b, | |
225 | 0x00, 0x00, 0xff, 0xff, 0xa3, 0x64, 0x11, 0x56, 0x89, 0x01, 0x00, 0x00, | |
226 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | enum HttpType { | |
4 | // unknown = 0; | |
5 | sinkhole = 1; | |
6 | } | |
7 | ||
8 | message Http { | |
9 | required HttpType type = 1; | |
10 | optional bytes srcip = 2; | |
11 | optional bytes srchost = 3; | |
12 | optional uint32 srcport = 4; | |
13 | optional bytes dstip = 5; | |
14 | optional uint32 dstport = 6; | |
15 | optional bytes request = 7; | |
16 | ||
17 | optional bytes p0f_genre = 65; | |
18 | optional bytes p0f_detail = 66; | |
19 | optional int32 p0f_dist = 67; | |
20 | optional bytes p0f_link = 68; | |
21 | optional bytes p0f_tos = 69; | |
22 | optional uint32 p0f_fw = 70; | |
23 | optional uint32 p0f_nat = 71; | |
24 | optional uint32 p0f_real = 72; | |
25 | optional int32 p0f_score = 73; | |
26 | optional uint32 p0f_mflags = 74; | |
27 | optional int32 p0f_uptime = 75; | |
28 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: ipconn.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type IPConn struct { | |
16 | Proto *uint32 `protobuf:"varint,1,opt,name=proto" json:"proto,omitempty"` | |
17 | Srcip []byte `protobuf:"bytes,2,opt,name=srcip" json:"srcip,omitempty"` | |
18 | Srcport *uint32 `protobuf:"varint,3,opt,name=srcport" json:"srcport,omitempty"` | |
19 | Dstip []byte `protobuf:"bytes,4,opt,name=dstip" json:"dstip,omitempty"` | |
20 | Dstport *uint32 `protobuf:"varint,5,opt,name=dstport" json:"dstport,omitempty"` | |
21 | XXX_unrecognized []byte `json:"-"` | |
22 | } | |
23 | ||
24 | func (m *IPConn) Reset() { *m = IPConn{} } | |
25 | func (m *IPConn) String() string { return proto.CompactTextString(m) } | |
26 | func (*IPConn) ProtoMessage() {} | |
27 | func (*IPConn) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } | |
28 | ||
29 | func (m *IPConn) GetProto() uint32 { | |
30 | if m != nil && m.Proto != nil { | |
31 | return *m.Proto | |
32 | } | |
33 | return 0 | |
34 | } | |
35 | ||
36 | func (m *IPConn) GetSrcip() []byte { | |
37 | if m != nil { | |
38 | return m.Srcip | |
39 | } | |
40 | return nil | |
41 | } | |
42 | ||
43 | func (m *IPConn) GetSrcport() uint32 { | |
44 | if m != nil && m.Srcport != nil { | |
45 | return *m.Srcport | |
46 | } | |
47 | return 0 | |
48 | } | |
49 | ||
50 | func (m *IPConn) GetDstip() []byte { | |
51 | if m != nil { | |
52 | return m.Dstip | |
53 | } | |
54 | return nil | |
55 | } | |
56 | ||
57 | func (m *IPConn) GetDstport() uint32 { | |
58 | if m != nil && m.Dstport != nil { | |
59 | return *m.Dstport | |
60 | } | |
61 | return 0 | |
62 | } | |
63 | ||
64 | func init() { | |
65 | proto.RegisterType((*IPConn)(nil), "nmsg.base.IPConn") | |
66 | } | |
67 | ||
68 | func init() { proto.RegisterFile("ipconn.proto", fileDescriptor5) } | |
69 | ||
70 | var fileDescriptor5 = []byte{ | |
71 | // 109 bytes of a gzipped FileDescriptorProto | |
72 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xc9, 0x2c, 0x48, 0xce, | |
73 | 0xcf, 0xcb, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, 0xd7, 0x4b, | |
74 | 0x4a, 0x2c, 0x4e, 0x55, 0x0a, 0xe7, 0x62, 0xf3, 0x0c, 0x70, 0x06, 0x4a, 0x09, 0xf1, 0x72, 0xb1, | |
75 | 0x82, 0x65, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x41, 0xdc, 0xe2, 0xa2, 0xe4, 0xcc, 0x02, 0x09, | |
76 | 0x26, 0x20, 0x97, 0x47, 0x88, 0x9f, 0x8b, 0x1d, 0xc8, 0x2d, 0xc8, 0x2f, 0x2a, 0x91, 0x60, 0x86, | |
77 | 0xc9, 0xa7, 0x14, 0x97, 0x00, 0xe5, 0x59, 0x60, 0xf2, 0x40, 0x2e, 0x58, 0x9e, 0x15, 0x24, 0x0f, | |
78 | 0x08, 0x00, 0x00, 0xff, 0xff, 0x83, 0x37, 0xd2, 0x7d, 0x72, 0x00, 0x00, 0x00, | |
79 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | message IPConn { | |
4 | optional uint32 proto = 1; | |
5 | optional bytes srcip = 2; | |
6 | optional uint32 srcport = 3; | |
7 | optional bytes dstip = 4; | |
8 | optional uint32 dstport = 5; | |
9 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: linkpair.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type Linktype int32 | |
16 | ||
17 | const ( | |
18 | Linktype_anchor Linktype = 0 | |
19 | Linktype_redirect Linktype = 1 | |
20 | ) | |
21 | ||
22 | var Linktype_name = map[int32]string{ | |
23 | 0: "anchor", | |
24 | 1: "redirect", | |
25 | } | |
26 | var Linktype_value = map[string]int32{ | |
27 | "anchor": 0, | |
28 | "redirect": 1, | |
29 | } | |
30 | ||
31 | func (x Linktype) Enum() *Linktype { | |
32 | p := new(Linktype) | |
33 | *p = x | |
34 | return p | |
35 | } | |
36 | func (x Linktype) String() string { | |
37 | return proto.EnumName(Linktype_name, int32(x)) | |
38 | } | |
39 | func (x *Linktype) UnmarshalJSON(data []byte) error { | |
40 | value, err := proto.UnmarshalJSONEnum(Linktype_value, data, "Linktype") | |
41 | if err != nil { | |
42 | return err | |
43 | } | |
44 | *x = Linktype(value) | |
45 | return nil | |
46 | } | |
47 | func (Linktype) EnumDescriptor() ([]byte, []int) { return fileDescriptor6, []int{0} } | |
48 | ||
49 | type Linkpair struct { | |
50 | Type *Linktype `protobuf:"varint,1,req,name=type,enum=nmsg.base.Linktype" json:"type,omitempty"` | |
51 | Src []byte `protobuf:"bytes,2,req,name=src" json:"src,omitempty"` | |
52 | Dst []byte `protobuf:"bytes,3,req,name=dst" json:"dst,omitempty"` | |
53 | Headers []byte `protobuf:"bytes,5,opt,name=headers" json:"headers,omitempty"` | |
54 | XXX_unrecognized []byte `json:"-"` | |
55 | } | |
56 | ||
57 | func (m *Linkpair) Reset() { *m = Linkpair{} } | |
58 | func (m *Linkpair) String() string { return proto.CompactTextString(m) } | |
59 | func (*Linkpair) ProtoMessage() {} | |
60 | func (*Linkpair) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{0} } | |
61 | ||
62 | func (m *Linkpair) GetType() Linktype { | |
63 | if m != nil && m.Type != nil { | |
64 | return *m.Type | |
65 | } | |
66 | return Linktype_anchor | |
67 | } | |
68 | ||
69 | func (m *Linkpair) GetSrc() []byte { | |
70 | if m != nil { | |
71 | return m.Src | |
72 | } | |
73 | return nil | |
74 | } | |
75 | ||
76 | func (m *Linkpair) GetDst() []byte { | |
77 | if m != nil { | |
78 | return m.Dst | |
79 | } | |
80 | return nil | |
81 | } | |
82 | ||
83 | func (m *Linkpair) GetHeaders() []byte { | |
84 | if m != nil { | |
85 | return m.Headers | |
86 | } | |
87 | return nil | |
88 | } | |
89 | ||
90 | func init() { | |
91 | proto.RegisterType((*Linkpair)(nil), "nmsg.base.Linkpair") | |
92 | proto.RegisterEnum("nmsg.base.Linktype", Linktype_name, Linktype_value) | |
93 | } | |
94 | ||
95 | func init() { proto.RegisterFile("linkpair.proto", fileDescriptor6) } | |
96 | ||
97 | var fileDescriptor6 = []byte{ | |
98 | // 149 bytes of a gzipped FileDescriptorProto | |
99 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xcb, 0xc9, 0xcc, 0xcb, | |
100 | 0x2e, 0x48, 0xcc, 0x2c, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, | |
101 | 0xd7, 0x4b, 0x4a, 0x2c, 0x4e, 0x55, 0x8a, 0xe0, 0xe2, 0xf0, 0x81, 0x4a, 0x0a, 0x29, 0x72, 0xb1, | |
102 | 0x94, 0x54, 0x16, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x69, 0xf0, 0x19, 0x09, 0xeb, 0xc1, 0x55, 0xe9, | |
103 | 0x81, 0x94, 0x80, 0xa4, 0x84, 0xb8, 0xb9, 0x98, 0x8b, 0x8b, 0x92, 0x25, 0x98, 0x80, 0x2a, 0x78, | |
104 | 0x40, 0x9c, 0x94, 0xe2, 0x12, 0x09, 0x66, 0x30, 0x87, 0x9f, 0x8b, 0x3d, 0x23, 0x35, 0x31, 0x25, | |
105 | 0xb5, 0xa8, 0x58, 0x82, 0x55, 0x81, 0x51, 0x83, 0x47, 0x4b, 0x05, 0x62, 0x32, 0x58, 0x1b, 0x17, | |
106 | 0x17, 0x5b, 0x62, 0x5e, 0x72, 0x46, 0x7e, 0x91, 0x00, 0x83, 0x10, 0x0f, 0x17, 0x47, 0x51, 0x6a, | |
107 | 0x4a, 0x66, 0x51, 0x6a, 0x72, 0x89, 0x00, 0x23, 0x20, 0x00, 0x00, 0xff, 0xff, 0x64, 0x13, 0x33, | |
108 | 0xdf, 0x9b, 0x00, 0x00, 0x00, | |
109 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | enum Linktype { | |
4 | anchor = 0; | |
5 | redirect = 1; | |
6 | } | |
7 | ||
8 | message Linkpair { | |
9 | required Linktype type = 1; | |
10 | required bytes src = 2; | |
11 | required bytes dst = 3; | |
12 | optional bytes headers = 5; | |
13 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: logline.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type LogLine struct { | |
16 | Category []byte `protobuf:"bytes,1,opt,name=category" json:"category,omitempty"` | |
17 | Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` | |
18 | XXX_unrecognized []byte `json:"-"` | |
19 | } | |
20 | ||
21 | func (m *LogLine) Reset() { *m = LogLine{} } | |
22 | func (m *LogLine) String() string { return proto.CompactTextString(m) } | |
23 | func (*LogLine) ProtoMessage() {} | |
24 | func (*LogLine) Descriptor() ([]byte, []int) { return fileDescriptor7, []int{0} } | |
25 | ||
26 | func (m *LogLine) GetCategory() []byte { | |
27 | if m != nil { | |
28 | return m.Category | |
29 | } | |
30 | return nil | |
31 | } | |
32 | ||
33 | func (m *LogLine) GetMessage() []byte { | |
34 | if m != nil { | |
35 | return m.Message | |
36 | } | |
37 | return nil | |
38 | } | |
39 | ||
40 | func init() { | |
41 | proto.RegisterType((*LogLine)(nil), "nmsg.base.LogLine") | |
42 | } | |
43 | ||
44 | func init() { proto.RegisterFile("logline.proto", fileDescriptor7) } | |
45 | ||
46 | var fileDescriptor7 = []byte{ | |
47 | // 93 bytes of a gzipped FileDescriptorProto | |
48 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0xc9, 0x4f, 0xcf, | |
49 | 0xc9, 0xcc, 0x4b, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, 0xd7, | |
50 | 0x4b, 0x4a, 0x2c, 0x4e, 0x55, 0xd2, 0xe1, 0x62, 0xf7, 0xc9, 0x4f, 0xf7, 0x01, 0xca, 0x09, 0x09, | |
51 | 0x70, 0x71, 0x24, 0x27, 0x96, 0xa4, 0xa6, 0xe7, 0x17, 0x55, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, | |
52 | 0x08, 0xf1, 0x73, 0xb1, 0xe7, 0xa6, 0x16, 0x17, 0x27, 0xa6, 0xa7, 0x4a, 0x30, 0x81, 0x04, 0x00, | |
53 | 0x01, 0x00, 0x00, 0xff, 0xff, 0x6e, 0x4e, 0xe7, 0x48, 0x48, 0x00, 0x00, 0x00, | |
54 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | message LogLine { | |
4 | optional bytes category = 1; | |
5 | optional bytes message = 2; | |
6 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: ncap.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type NcapType int32 | |
16 | ||
17 | const ( | |
18 | NcapType_IPV4 NcapType = 0 | |
19 | NcapType_IPV6 NcapType = 1 | |
20 | NcapType_Legacy NcapType = 2 | |
21 | ) | |
22 | ||
23 | var NcapType_name = map[int32]string{ | |
24 | 0: "IPV4", | |
25 | 1: "IPV6", | |
26 | 2: "Legacy", | |
27 | } | |
28 | var NcapType_value = map[string]int32{ | |
29 | "IPV4": 0, | |
30 | "IPV6": 1, | |
31 | "Legacy": 2, | |
32 | } | |
33 | ||
34 | func (x NcapType) Enum() *NcapType { | |
35 | p := new(NcapType) | |
36 | *p = x | |
37 | return p | |
38 | } | |
39 | func (x NcapType) String() string { | |
40 | return proto.EnumName(NcapType_name, int32(x)) | |
41 | } | |
42 | func (x *NcapType) UnmarshalJSON(data []byte) error { | |
43 | value, err := proto.UnmarshalJSONEnum(NcapType_value, data, "NcapType") | |
44 | if err != nil { | |
45 | return err | |
46 | } | |
47 | *x = NcapType(value) | |
48 | return nil | |
49 | } | |
50 | func (NcapType) EnumDescriptor() ([]byte, []int) { return fileDescriptor8, []int{0} } | |
51 | ||
52 | type NcapLegacyType int32 | |
53 | ||
54 | const ( | |
55 | NcapLegacyType_Ncap_UDP NcapLegacyType = 0 | |
56 | NcapLegacyType_Ncap_TCP NcapLegacyType = 1 | |
57 | NcapLegacyType_Ncap_ICMP NcapLegacyType = 2 | |
58 | ) | |
59 | ||
60 | var NcapLegacyType_name = map[int32]string{ | |
61 | 0: "Ncap_UDP", | |
62 | 1: "Ncap_TCP", | |
63 | 2: "Ncap_ICMP", | |
64 | } | |
65 | var NcapLegacyType_value = map[string]int32{ | |
66 | "Ncap_UDP": 0, | |
67 | "Ncap_TCP": 1, | |
68 | "Ncap_ICMP": 2, | |
69 | } | |
70 | ||
71 | func (x NcapLegacyType) Enum() *NcapLegacyType { | |
72 | p := new(NcapLegacyType) | |
73 | *p = x | |
74 | return p | |
75 | } | |
76 | func (x NcapLegacyType) String() string { | |
77 | return proto.EnumName(NcapLegacyType_name, int32(x)) | |
78 | } | |
79 | func (x *NcapLegacyType) UnmarshalJSON(data []byte) error { | |
80 | value, err := proto.UnmarshalJSONEnum(NcapLegacyType_value, data, "NcapLegacyType") | |
81 | if err != nil { | |
82 | return err | |
83 | } | |
84 | *x = NcapLegacyType(value) | |
85 | return nil | |
86 | } | |
87 | func (NcapLegacyType) EnumDescriptor() ([]byte, []int) { return fileDescriptor8, []int{1} } | |
88 | ||
89 | type Ncap struct { | |
90 | Type *NcapType `protobuf:"varint,1,req,name=type,enum=nmsg.base.NcapType" json:"type,omitempty"` | |
91 | Payload []byte `protobuf:"bytes,2,req,name=payload" json:"payload,omitempty"` | |
92 | // legacy NCAP fields | |
93 | Ltype *NcapLegacyType `protobuf:"varint,3,opt,name=ltype,enum=nmsg.base.NcapLegacyType" json:"ltype,omitempty"` | |
94 | Srcip []byte `protobuf:"bytes,4,opt,name=srcip" json:"srcip,omitempty"` | |
95 | Dstip []byte `protobuf:"bytes,5,opt,name=dstip" json:"dstip,omitempty"` | |
96 | Lint0 *uint32 `protobuf:"varint,6,opt,name=lint0" json:"lint0,omitempty"` | |
97 | Lint1 *uint32 `protobuf:"varint,7,opt,name=lint1" json:"lint1,omitempty"` | |
98 | XXX_unrecognized []byte `json:"-"` | |
99 | } | |
100 | ||
101 | func (m *Ncap) Reset() { *m = Ncap{} } | |
102 | func (m *Ncap) String() string { return proto.CompactTextString(m) } | |
103 | func (*Ncap) ProtoMessage() {} | |
104 | func (*Ncap) Descriptor() ([]byte, []int) { return fileDescriptor8, []int{0} } | |
105 | ||
106 | func (m *Ncap) GetType() NcapType { | |
107 | if m != nil && m.Type != nil { | |
108 | return *m.Type | |
109 | } | |
110 | return NcapType_IPV4 | |
111 | } | |
112 | ||
113 | func (m *Ncap) GetPayload() []byte { | |
114 | if m != nil { | |
115 | return m.Payload | |
116 | } | |
117 | return nil | |
118 | } | |
119 | ||
120 | func (m *Ncap) GetLtype() NcapLegacyType { | |
121 | if m != nil && m.Ltype != nil { | |
122 | return *m.Ltype | |
123 | } | |
124 | return NcapLegacyType_Ncap_UDP | |
125 | } | |
126 | ||
127 | func (m *Ncap) GetSrcip() []byte { | |
128 | if m != nil { | |
129 | return m.Srcip | |
130 | } | |
131 | return nil | |
132 | } | |
133 | ||
134 | func (m *Ncap) GetDstip() []byte { | |
135 | if m != nil { | |
136 | return m.Dstip | |
137 | } | |
138 | return nil | |
139 | } | |
140 | ||
141 | func (m *Ncap) GetLint0() uint32 { | |
142 | if m != nil && m.Lint0 != nil { | |
143 | return *m.Lint0 | |
144 | } | |
145 | return 0 | |
146 | } | |
147 | ||
148 | func (m *Ncap) GetLint1() uint32 { | |
149 | if m != nil && m.Lint1 != nil { | |
150 | return *m.Lint1 | |
151 | } | |
152 | return 0 | |
153 | } | |
154 | ||
155 | func init() { | |
156 | proto.RegisterType((*Ncap)(nil), "nmsg.base.Ncap") | |
157 | proto.RegisterEnum("nmsg.base.NcapType", NcapType_name, NcapType_value) | |
158 | proto.RegisterEnum("nmsg.base.NcapLegacyType", NcapLegacyType_name, NcapLegacyType_value) | |
159 | } | |
160 | ||
161 | func init() { proto.RegisterFile("ncap.proto", fileDescriptor8) } | |
162 | ||
163 | var fileDescriptor8 = []byte{ | |
164 | // 218 bytes of a gzipped FileDescriptorProto | |
165 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xca, 0x4b, 0x4e, 0x2c, | |
166 | 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, 0xd7, 0x4b, 0x4a, 0x2c, | |
167 | 0x4e, 0x55, 0x5a, 0xc0, 0xc8, 0xc5, 0xe2, 0x07, 0x94, 0x11, 0x52, 0xe4, 0x62, 0x29, 0xa9, 0x2c, | |
168 | 0x48, 0x95, 0x60, 0x54, 0x60, 0xd2, 0xe0, 0x33, 0x12, 0xd6, 0x83, 0x2b, 0xd1, 0x03, 0x49, 0x87, | |
169 | 0x00, 0xa5, 0x84, 0xf8, 0xb9, 0xd8, 0x0b, 0x12, 0x2b, 0x73, 0xf2, 0x13, 0x53, 0x24, 0x98, 0x80, | |
170 | 0xaa, 0x78, 0x84, 0x34, 0xb8, 0x58, 0x73, 0xc0, 0x9a, 0x98, 0x15, 0x18, 0x81, 0x9a, 0x24, 0xd1, | |
171 | 0x34, 0xf9, 0xa4, 0xa6, 0x27, 0x26, 0x57, 0x82, 0xb5, 0xf2, 0x72, 0xb1, 0x16, 0x17, 0x25, 0x67, | |
172 | 0x16, 0x48, 0xb0, 0x00, 0x55, 0xf2, 0x80, 0xb8, 0x29, 0xc5, 0x25, 0x40, 0x2e, 0x2b, 0x8c, 0x9b, | |
173 | 0x93, 0x99, 0x57, 0x62, 0x20, 0xc1, 0x06, 0xe4, 0xf2, 0xc2, 0xb8, 0x86, 0x12, 0xec, 0x20, 0xae, | |
174 | 0x96, 0x16, 0x17, 0x07, 0xdc, 0x09, 0x1c, 0x5c, 0x2c, 0x9e, 0x01, 0x61, 0x26, 0x02, 0x0c, 0x50, | |
175 | 0x96, 0x99, 0x00, 0xa3, 0x10, 0x17, 0x17, 0x1b, 0xc4, 0x26, 0x01, 0x26, 0x2d, 0x6b, 0x2e, 0x3e, | |
176 | 0x34, 0x9b, 0x79, 0x20, 0xba, 0xe3, 0x43, 0x5d, 0x02, 0x80, 0xba, 0x60, 0xbc, 0x10, 0xe7, 0x00, | |
177 | 0xa0, 0x4e, 0x5e, 0x2e, 0x4e, 0x30, 0xcf, 0xd3, 0xd9, 0x37, 0x40, 0x80, 0x09, 0x10, 0x00, 0x00, | |
178 | 0xff, 0xff, 0x36, 0x82, 0xd0, 0xf3, 0x23, 0x01, 0x00, 0x00, | |
179 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | enum NcapType { | |
4 | IPV4 = 0; | |
5 | IPV6 = 1; | |
6 | Legacy = 2; | |
7 | } | |
8 | ||
9 | enum NcapLegacyType { | |
10 | Ncap_UDP = 0; | |
11 | Ncap_TCP = 1; | |
12 | Ncap_ICMP = 2; | |
13 | } | |
14 | ||
15 | message Ncap { | |
16 | required NcapType type = 1; | |
17 | required bytes payload = 2; | |
18 | ||
19 | // legacy NCAP fields | |
20 | optional NcapLegacyType ltype = 3; | |
21 | optional bytes srcip = 4; | |
22 | optional bytes dstip = 5; | |
23 | optional uint32 lint0 = 6; | |
24 | optional uint32 lint1 = 7; | |
25 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: packet.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type PacketType int32 | |
16 | ||
17 | const ( | |
18 | // An IPv4 or IPv6 packet. The packet begins immediately with the IP | |
19 | // header and contains the complete packet payload. Distinguishing between | |
20 | // IPv4 and IPv6 packets is done by examining the IP version field in the | |
21 | // IP header. | |
22 | PacketType_IP PacketType = 1 | |
23 | ) | |
24 | ||
25 | var PacketType_name = map[int32]string{ | |
26 | 1: "IP", | |
27 | } | |
28 | var PacketType_value = map[string]int32{ | |
29 | "IP": 1, | |
30 | } | |
31 | ||
32 | func (x PacketType) Enum() *PacketType { | |
33 | p := new(PacketType) | |
34 | *p = x | |
35 | return p | |
36 | } | |
37 | func (x PacketType) String() string { | |
38 | return proto.EnumName(PacketType_name, int32(x)) | |
39 | } | |
40 | func (x *PacketType) UnmarshalJSON(data []byte) error { | |
41 | value, err := proto.UnmarshalJSONEnum(PacketType_value, data, "PacketType") | |
42 | if err != nil { | |
43 | return err | |
44 | } | |
45 | *x = PacketType(value) | |
46 | return nil | |
47 | } | |
48 | func (PacketType) EnumDescriptor() ([]byte, []int) { return fileDescriptor9, []int{0} } | |
49 | ||
50 | type Packet struct { | |
51 | PayloadType *PacketType `protobuf:"varint,1,req,name=payload_type,enum=nmsg.base.PacketType" json:"payload_type,omitempty"` | |
52 | Payload []byte `protobuf:"bytes,2,req,name=payload" json:"payload,omitempty"` | |
53 | XXX_unrecognized []byte `json:"-"` | |
54 | } | |
55 | ||
56 | func (m *Packet) Reset() { *m = Packet{} } | |
57 | func (m *Packet) String() string { return proto.CompactTextString(m) } | |
58 | func (*Packet) ProtoMessage() {} | |
59 | func (*Packet) Descriptor() ([]byte, []int) { return fileDescriptor9, []int{0} } | |
60 | ||
61 | func (m *Packet) GetPayloadType() PacketType { | |
62 | if m != nil && m.PayloadType != nil { | |
63 | return *m.PayloadType | |
64 | } | |
65 | return PacketType_IP | |
66 | } | |
67 | ||
68 | func (m *Packet) GetPayload() []byte { | |
69 | if m != nil { | |
70 | return m.Payload | |
71 | } | |
72 | return nil | |
73 | } | |
74 | ||
75 | func init() { | |
76 | proto.RegisterType((*Packet)(nil), "nmsg.base.Packet") | |
77 | proto.RegisterEnum("nmsg.base.PacketType", PacketType_name, PacketType_value) | |
78 | } | |
79 | ||
80 | func init() { proto.RegisterFile("packet.proto", fileDescriptor9) } | |
81 | ||
82 | var fileDescriptor9 = []byte{ | |
83 | // 111 bytes of a gzipped FileDescriptorProto | |
84 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x48, 0x4c, 0xce, | |
85 | 0x4e, 0x2d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, 0xd7, 0x4b, | |
86 | 0x4a, 0x2c, 0x4e, 0x55, 0x72, 0xe3, 0x62, 0x0b, 0x00, 0x4b, 0x09, 0x69, 0x83, 0x14, 0x55, 0xe6, | |
87 | 0xe4, 0x27, 0xa6, 0xc4, 0x97, 0x54, 0x16, 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x69, 0xf0, 0x19, 0x89, | |
88 | 0xea, 0xc1, 0xd5, 0xea, 0x41, 0x14, 0x86, 0x00, 0x25, 0x85, 0xf8, 0xb9, 0xd8, 0xa1, 0x8a, 0x25, | |
89 | 0x98, 0x80, 0xea, 0x78, 0xb4, 0x44, 0xb8, 0xb8, 0x90, 0xa4, 0xd9, 0xb8, 0x98, 0x3c, 0x03, 0x04, | |
90 | 0x18, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf6, 0x3e, 0xce, 0x93, 0x77, 0x00, 0x00, 0x00, | |
91 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | enum PacketType { | |
4 | // An IPv4 or IPv6 packet. The packet begins immediately with the IP | |
5 | // header and contains the complete packet payload. Distinguishing between | |
6 | // IPv4 and IPv6 packets is done by examining the IP version field in the | |
7 | // IP header. | |
8 | IP = 1; | |
9 | } | |
10 | ||
11 | message Packet { | |
12 | required PacketType payload_type = 1; | |
13 | required bytes payload = 2; | |
14 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: pkt.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type Pkt struct { | |
16 | Payload []byte `protobuf:"bytes,1,req,name=payload" json:"payload,omitempty"` | |
17 | LenFrame *uint32 `protobuf:"varint,2,opt,name=len_frame" json:"len_frame,omitempty"` | |
18 | XXX_unrecognized []byte `json:"-"` | |
19 | } | |
20 | ||
21 | func (m *Pkt) Reset() { *m = Pkt{} } | |
22 | func (m *Pkt) String() string { return proto.CompactTextString(m) } | |
23 | func (*Pkt) ProtoMessage() {} | |
24 | func (*Pkt) Descriptor() ([]byte, []int) { return fileDescriptor10, []int{0} } | |
25 | ||
26 | func (m *Pkt) GetPayload() []byte { | |
27 | if m != nil { | |
28 | return m.Payload | |
29 | } | |
30 | return nil | |
31 | } | |
32 | ||
33 | func (m *Pkt) GetLenFrame() uint32 { | |
34 | if m != nil && m.LenFrame != nil { | |
35 | return *m.LenFrame | |
36 | } | |
37 | return 0 | |
38 | } | |
39 | ||
40 | func init() { | |
41 | proto.RegisterType((*Pkt)(nil), "nmsg.base.Pkt") | |
42 | } | |
43 | ||
44 | func init() { proto.RegisterFile("pkt.proto", fileDescriptor10) } | |
45 | ||
46 | var fileDescriptor10 = []byte{ | |
47 | // 89 bytes of a gzipped FileDescriptorProto | |
48 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2c, 0xc8, 0x2e, 0xd1, | |
49 | 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, 0xd7, 0x4b, 0x4a, 0x2c, 0x4e, | |
50 | 0x55, 0xd2, 0xe4, 0x62, 0x0e, 0xc8, 0x2e, 0x11, 0xe2, 0xe7, 0x62, 0x2f, 0x48, 0xac, 0xcc, 0xc9, | |
51 | 0x4f, 0x4c, 0x91, 0x60, 0x54, 0x60, 0xd2, 0xe0, 0x11, 0x12, 0xe4, 0xe2, 0xcc, 0x49, 0xcd, 0x8b, | |
52 | 0x4f, 0x2b, 0x4a, 0xcc, 0x4d, 0x95, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x05, 0x04, 0x00, 0x00, 0xff, | |
53 | 0xff, 0x9d, 0xda, 0xa2, 0xb6, 0x41, 0x00, 0x00, 0x00, | |
54 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | message Pkt { | |
4 | required bytes payload = 1; | |
5 | optional uint32 len_frame = 2; | |
6 | } |
0 | // Code generated by protoc-gen-go. | |
1 | // source: xml.proto | |
2 | // DO NOT EDIT! | |
3 | ||
4 | package nmsg_base | |
5 | ||
6 | import proto "github.com/golang/protobuf/proto" | |
7 | import fmt "fmt" | |
8 | import math "math" | |
9 | ||
10 | // Reference imports to suppress errors if they are not otherwise used. | |
11 | var _ = proto.Marshal | |
12 | var _ = fmt.Errorf | |
13 | var _ = math.Inf | |
14 | ||
15 | type Xml struct { | |
16 | Xmltype []byte `protobuf:"bytes,1,req,name=xmltype" json:"xmltype,omitempty"` | |
17 | Xmlpayload []byte `protobuf:"bytes,2,req,name=xmlpayload" json:"xmlpayload,omitempty"` | |
18 | XXX_unrecognized []byte `json:"-"` | |
19 | } | |
20 | ||
21 | func (m *Xml) Reset() { *m = Xml{} } | |
22 | func (m *Xml) String() string { return proto.CompactTextString(m) } | |
23 | func (*Xml) ProtoMessage() {} | |
24 | func (*Xml) Descriptor() ([]byte, []int) { return fileDescriptor11, []int{0} } | |
25 | ||
26 | func (m *Xml) GetXmltype() []byte { | |
27 | if m != nil { | |
28 | return m.Xmltype | |
29 | } | |
30 | return nil | |
31 | } | |
32 | ||
33 | func (m *Xml) GetXmlpayload() []byte { | |
34 | if m != nil { | |
35 | return m.Xmlpayload | |
36 | } | |
37 | return nil | |
38 | } | |
39 | ||
40 | func init() { | |
41 | proto.RegisterType((*Xml)(nil), "nmsg.base.Xml") | |
42 | } | |
43 | ||
44 | func init() { proto.RegisterFile("xml.proto", fileDescriptor11) } | |
45 | ||
46 | var fileDescriptor11 = []byte{ | |
47 | // 86 bytes of a gzipped FileDescriptorProto | |
48 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xac, 0xc8, 0xcd, 0xd1, | |
49 | 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0xcc, 0xcb, 0x2d, 0x4e, 0xd7, 0x4b, 0x4a, 0x2c, 0x4e, | |
50 | 0x55, 0xd2, 0xe2, 0x62, 0x8e, 0xc8, 0xcd, 0x11, 0xe2, 0xe7, 0x62, 0x07, 0x4a, 0x97, 0x54, 0x16, | |
51 | 0xa4, 0x4a, 0x30, 0x2a, 0x30, 0x69, 0xf0, 0x08, 0x09, 0x71, 0x71, 0x01, 0x05, 0x0a, 0x12, 0x2b, | |
52 | 0x73, 0xf2, 0x13, 0x53, 0x24, 0x98, 0x40, 0x62, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb0, 0x92, | |
53 | 0x10, 0x81, 0x42, 0x00, 0x00, 0x00, | |
54 | } |
0 | syntax = "proto2"; | |
1 | package nmsg.base; | |
2 | ||
3 | message Xml { | |
4 | required bytes xmltype = 1; | |
5 | required bytes xmlpayload = 2; | |
6 | } |
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 | import ( | |
11 | "io" | |
12 | "sync" | |
13 | "time" | |
14 | ) | |
15 | ||
16 | // An Output encapsulates NmsgPayloads in Nmsg containers and writes them to | |
17 | // an io.Writer. | |
18 | type Output interface { | |
19 | // Send sends an Nmsg Payload along the output. Implementations | |
20 | // may queue the payload for later sending, so the caller should | |
21 | // not modify the payload after calling Send. | |
22 | // | |
23 | // Send may be safely called from multiple goroutines. | |
24 | Send(*NmsgPayload) error | |
25 | // SetSequenced controls whether the Nmsg containers generated by | |
26 | // the Output have sequence numbers. | |
27 | SetSequenced(bool) | |
28 | // SetCompression controls whether the Output generates compressed | |
29 | // containers or uncompressed. | |
30 | SetCompression(bool) | |
31 | // SetCompressionRatio sets the anticipated compression ratio for | |
32 | // compressed containers. | |
33 | SetCompressionRatio(float32) | |
34 | // SetMaxSize sets the maximum size of a container the Output will | |
35 | // buffer, and the maximum size of a container or fragment the Output | |
36 | // will write. For Ethernet, consider using nmsg.EtherContainerSize. | |
37 | SetMaxSize(size int, writeSize int) | |
38 | // Close shuts down the output, flushing any queued payloads. | |
39 | // It will not close the underlying io.Writer. | |
40 | Close() error | |
41 | } | |
42 | ||
43 | type output struct { | |
44 | w io.Writer | |
45 | *Container | |
46 | } | |
47 | ||
48 | func (o *output) Send(p *NmsgPayload) error { | |
49 | c := o.Container | |
50 | c.AddPayload(p) | |
51 | _, err := c.WriteTo(o.w) | |
52 | return err | |
53 | } | |
54 | ||
55 | func (o *output) Close() error { | |
56 | return nil | |
57 | } | |
58 | ||
59 | // UnbufferedOutput returns an Output which writes an Nmsg container for | |
60 | // each payload. | |
61 | func UnbufferedOutput(w io.Writer) Output { | |
62 | return &output{w: w, Container: NewContainer()} | |
63 | } | |
64 | ||
65 | type bufferedOutput struct { | |
66 | output | |
67 | mu sync.Mutex | |
68 | } | |
69 | ||
70 | func (o *bufferedOutput) Send(p *NmsgPayload) error { | |
71 | o.mu.Lock() | |
72 | defer o.mu.Unlock() | |
73 | var ok, full bool | |
74 | for !ok { | |
75 | ok, full = o.AddPayload(p) | |
76 | if !full { | |
77 | return nil | |
78 | } | |
79 | ||
80 | _, err := o.WriteTo(o.w) | |
81 | if err != nil { | |
82 | return err | |
83 | } | |
84 | } | |
85 | return nil | |
86 | } | |
87 | ||
88 | func (o *bufferedOutput) Close() error { | |
89 | o.mu.Lock() | |
90 | defer o.mu.Unlock() | |
91 | if len(o.Nmsg.Payloads) > 0 { | |
92 | _, err := o.WriteTo(o.w) | |
93 | return err | |
94 | } | |
95 | return nil | |
96 | } | |
97 | ||
98 | // BufferedOutput creates an Output which collects NmsgPayloads and sends | |
99 | // them in containers as close as possible to the size set by SetMaxSize() | |
100 | func BufferedOutput(w io.Writer) Output { | |
101 | o := new(bufferedOutput) | |
102 | o.output = output{w: w, Container: NewContainer()} | |
103 | return o | |
104 | } | |
105 | ||
106 | type timedBufferedOutput struct { | |
107 | bufferedOutput | |
108 | timer *time.Timer | |
109 | d time.Duration | |
110 | err error | |
111 | } | |
112 | ||
113 | func (t *timedBufferedOutput) Send(p *NmsgPayload) error { | |
114 | t.mu.Lock() | |
115 | defer t.mu.Unlock() | |
116 | ||
117 | if t.err != nil { | |
118 | return t.err | |
119 | } | |
120 | ||
121 | // We are sending the first payload on a new or recently-flushed | |
122 | // output. Reset or restart flush timer. | |
123 | if len(t.Nmsg.Payloads) == 0 && !t.timer.Reset(t.d) { | |
124 | t.timer = time.AfterFunc(t.d, t.flush) | |
125 | } | |
126 | ||
127 | var ok, full bool | |
128 | for !ok { | |
129 | ok, full = t.AddPayload(p) | |
130 | if !full { | |
131 | break | |
132 | } | |
133 | ||
134 | t.timer.Reset(t.d) | |
135 | ||
136 | _, err := t.WriteTo(t.w) | |
137 | if err != nil { | |
138 | t.err = err | |
139 | return err | |
140 | } | |
141 | } | |
142 | return nil | |
143 | } | |
144 | ||
145 | func (t *timedBufferedOutput) Close() error { | |
146 | t.timer.Stop() | |
147 | return t.bufferedOutput.Close() | |
148 | } | |
149 | ||
150 | func (t *timedBufferedOutput) flush() { | |
151 | t.mu.Lock() | |
152 | defer t.mu.Unlock() | |
153 | if len(t.Nmsg.Payloads) > 0 { | |
154 | _, t.err = t.WriteTo(t.w) | |
155 | } | |
156 | } | |
157 | ||
158 | // TimedBufferedOutput creates an Output which collects NmsgPayloads | |
159 | // and sends them in containers as close as possible to the size provided to | |
160 | // SetMaxSize or after the given Duration, whichever comes first. | |
161 | func TimedBufferedOutput(w io.Writer, d time.Duration) Output { | |
162 | t := &timedBufferedOutput{d: d} | |
163 | t.bufferedOutput.output = output{w: w, Container: NewContainer()} | |
164 | t.timer = time.AfterFunc(d, t.flush) | |
165 | ||
166 | return t | |
167 | } |
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 | "errors" | |
13 | "testing" | |
14 | "time" | |
15 | ||
16 | "github.com/farsightsec/go-nmsg" | |
17 | ) | |
18 | ||
19 | type countWriter struct { | |
20 | count, total int | |
21 | closed bool | |
22 | t *testing.T | |
23 | } | |
24 | ||
25 | // Testing output. | |
26 | ||
27 | // countWriter Implements io.WriteCloser, plus a Count() method returning | |
28 | // how many times it has been called and a Total() method returning the | |
29 | // number of bytes written. | |
30 | ||
31 | func (w *countWriter) Count() int { return w.count } | |
32 | func (w *countWriter) Total() int { return w.total } | |
33 | ||
34 | func (w *countWriter) Write(b []byte) (int, error) { | |
35 | w.t.Logf("Writing %d bytes", len(b)) | |
36 | w.count++ | |
37 | w.total += len(b) | |
38 | return len(b), nil | |
39 | } | |
40 | ||
41 | func newCountWriter(t *testing.T) *countWriter { | |
42 | return &countWriter{t: t} | |
43 | } | |
44 | ||
45 | // bufWriter augments bytes.Buffer with a Clos() method to | |
46 | // satisfy io.WriteCloser | |
47 | type bufWriter struct { | |
48 | *bytes.Buffer | |
49 | } | |
50 | ||
51 | func newBufWriter() *bufWriter { | |
52 | return &bufWriter{new(bytes.Buffer)} | |
53 | } | |
54 | ||
55 | func TestUnBufferedOutput(t *testing.T) { | |
56 | c := newCountWriter(t) | |
57 | p, err := nmsg.Payload(testMessage(1000)) | |
58 | if err != nil { | |
59 | t.Errorf(err.Error()) | |
60 | } | |
61 | o := nmsg.UnbufferedOutput(c) | |
62 | o.SetMaxSize(1500, 0) | |
63 | if err := o.Send(p); err != nil { | |
64 | t.Errorf(err.Error()) | |
65 | } | |
66 | if c.Count() < 1 { | |
67 | t.Errorf("No write occurred") | |
68 | } | |
69 | if c.Total() < 1000 { | |
70 | t.Errorf("Write was too short") | |
71 | } | |
72 | if err := o.Close(); err != nil { | |
73 | t.Errorf("Close failed") | |
74 | } | |
75 | ||
76 | } | |
77 | ||
78 | func TestBufferedOutput(t *testing.T) { | |
79 | c := newCountWriter(t) | |
80 | o := nmsg.BufferedOutput(c) | |
81 | o.SetMaxSize(1500, 0) | |
82 | o.SetSequenced(true) | |
83 | ||
84 | // this should go in the buffer, and not be written | |
85 | if err := o.Send(testPayload(800)); err != nil { | |
86 | t.Errorf(err.Error()) | |
87 | } | |
88 | if c.Count() > 0 { | |
89 | t.Error("Buffer did not suppress write") | |
90 | } | |
91 | ||
92 | // this should flush the buffer, causing one write, | |
93 | // then go into the buffer, not causing a second write. | |
94 | if err := o.Send(testPayload(800)); err != nil { | |
95 | t.Errorf(err.Error()) | |
96 | } | |
97 | if c.Count() < 1 { | |
98 | t.Error("Buffer did not write") | |
99 | } | |
100 | if c.Count() > 1 { | |
101 | t.Error("Buffer did not suppress write") | |
102 | } | |
103 | ||
104 | // this should flush the buffer, causing one write, | |
105 | // then bypass the buffer and be written in two fragments | |
106 | if err := o.Send(testPayload(1700)); err != nil { | |
107 | t.Errorf(err.Error()) | |
108 | } | |
109 | if err := o.Close(); err != nil { | |
110 | t.Errorf(err.Error()) | |
111 | } | |
112 | if c.Count() < 4 { | |
113 | t.Errorf("Missing writes: %d should be 4", c.Count()) | |
114 | } | |
115 | if c.Count() > 4 { | |
116 | t.Error("Extra writes") | |
117 | } | |
118 | } | |
119 | ||
120 | func TestBufferedOutputNoConfig(t *testing.T) { | |
121 | c := newCountWriter(t) | |
122 | o := nmsg.BufferedOutput(c) | |
123 | ||
124 | // this should go in the buffer with the default | |
125 | // MinContainerSize maximum, and not be written | |
126 | if err := o.Send(testPayload(300)); err != nil { | |
127 | t.Errorf(err.Error()) | |
128 | } | |
129 | if c.Count() > 0 { | |
130 | t.Error("Buffer did not suppress write") | |
131 | } | |
132 | ||
133 | // this should flush the buffer, causing one write, | |
134 | // then go into the buffer, not causing a second write. | |
135 | if err := o.Send(testPayload(300)); err != nil { | |
136 | t.Errorf(err.Error()) | |
137 | } | |
138 | if c.Count() < 1 { | |
139 | t.Error("Buffer did not write") | |
140 | } | |
141 | if c.Count() > 1 { | |
142 | t.Error("Buffer did not suppress write") | |
143 | } | |
144 | ||
145 | // this should flush the buffer, causing one write, | |
146 | // then bypass the buffer and be written in two fragments | |
147 | if err := o.Send(testPayload(600)); err != nil { | |
148 | t.Errorf(err.Error()) | |
149 | } | |
150 | if err := o.Close(); err != nil { | |
151 | t.Errorf(err.Error()) | |
152 | } | |
153 | if c.Count() < 4 { | |
154 | t.Errorf("Missing writes: %d should be 4", c.Count()) | |
155 | } | |
156 | if c.Count() > 4 { | |
157 | t.Error("Extra writes") | |
158 | } | |
159 | } | |
160 | ||
161 | func TestTimedBufferedOutput(t *testing.T) { | |
162 | c := newCountWriter(t) | |
163 | o := nmsg.TimedBufferedOutput(c, 100*time.Millisecond) | |
164 | o.SetMaxSize(1500, 0) | |
165 | o.SetSequenced(true) | |
166 | ||
167 | // This should wait about 100ms to send | |
168 | if err := o.Send(testPayload(100)); err != nil { | |
169 | t.Error(err.Error()) | |
170 | } | |
171 | if c.Count() > 0 { | |
172 | t.Error("Write not delayed") | |
173 | } | |
174 | ||
175 | time.Sleep(110 * time.Millisecond) | |
176 | ||
177 | if c.Count() < 1 { | |
178 | t.Error("Write timed out.") | |
179 | } | |
180 | ||
181 | if err := o.Close(); err != nil { | |
182 | t.Error(err.Error()) | |
183 | } | |
184 | } | |
185 | ||
186 | func TestTimedBufferedOutputNoConfig(t *testing.T) { | |
187 | c := newCountWriter(t) | |
188 | o := nmsg.TimedBufferedOutput(c, 100*time.Millisecond) | |
189 | o.SetSequenced(true) | |
190 | ||
191 | // This should wait about 100ms to send | |
192 | if err := o.Send(testPayload(100)); err != nil { | |
193 | t.Error(err.Error()) | |
194 | } | |
195 | if c.Count() > 0 { | |
196 | t.Error("Write not delayed") | |
197 | } | |
198 | ||
199 | time.Sleep(110 * time.Millisecond) | |
200 | ||
201 | if c.Count() < 1 { | |
202 | t.Error("Write timed out.") | |
203 | } | |
204 | ||
205 | if err := o.Close(); err != nil { | |
206 | t.Error(err.Error()) | |
207 | } | |
208 | ||
209 | for i := 0; i < 10; i++ { | |
210 | o.Send(testPayload(100)) | |
211 | } | |
212 | time.Sleep(110 * time.Millisecond) | |
213 | ||
214 | if c.Count() < 2 { | |
215 | t.Error("Writes timed out") | |
216 | } | |
217 | } | |
218 | ||
219 | func TestTimedBufferReset(t *testing.T) { | |
220 | c := newCountWriter(t) | |
221 | o := nmsg.TimedBufferedOutput(c, 100*time.Millisecond) | |
222 | o.SetMaxSize(1500, 0) | |
223 | o.SetSequenced(true) | |
224 | ||
225 | if err := o.Send(testPayload(750)); err != nil { | |
226 | t.Error(err.Error()) | |
227 | } | |
228 | time.Sleep(50 * time.Millisecond) | |
229 | // This should trigger a write, leave this payload in | |
230 | // the buffer, and reset the timer for another 100ms. | |
231 | if err := o.Send(testPayload(750)); err != nil { | |
232 | t.Error(err.Error()) | |
233 | } | |
234 | ||
235 | time.Sleep(25 * time.Millisecond) | |
236 | ||
237 | if c.Count() < 1 { | |
238 | t.Error("Write failed to happen") | |
239 | } | |
240 | if c.Count() > 1 { | |
241 | t.Error("Spurious write happened") | |
242 | } | |
243 | ||
244 | // Check at start + 100ms, to make sure the buffer didn't fire twice | |
245 | time.Sleep(25 * time.Millisecond) | |
246 | if c.Count() > 1 { | |
247 | t.Error("premature second write") | |
248 | } | |
249 | ||
250 | // Check in after start + 150ms, second write should have happened. | |
251 | time.Sleep(55 * time.Millisecond) | |
252 | if c.Count() < 2 { | |
253 | t.Error("second write late") | |
254 | } | |
255 | ||
256 | time.Sleep(55 * time.Millisecond) | |
257 | // The previous write caused the timer to expire, and it will need to | |
258 | // be restarted. Test that code path with one more sequence of Sends | |
259 | // which will force a flush. | |
260 | for i := 0; i < 3; i++ { | |
261 | if err := o.Send(testPayload(750)); err != nil { | |
262 | t.Error(err.Error()) | |
263 | } | |
264 | } | |
265 | ||
266 | time.Sleep(25 * time.Millisecond) | |
267 | ||
268 | if c.Count() < 3 { | |
269 | t.Error("third write late") | |
270 | } | |
271 | ||
272 | time.Sleep(80 * time.Millisecond) | |
273 | if c.Count() < 4 { | |
274 | t.Error("Final write late") | |
275 | } | |
276 | ||
277 | o.Close() | |
278 | } | |
279 | ||
280 | type countdownWriter int | |
281 | ||
282 | func (c *countdownWriter) Write(b []byte) (int, error) { | |
283 | if *c > 0 { | |
284 | (*c)-- | |
285 | return len(b), nil | |
286 | } | |
287 | return 0, errors.New("writer finished") | |
288 | } | |
289 | ||
290 | func newCountdownWriter(n int) *countdownWriter { | |
291 | c := countdownWriter(n) | |
292 | return &c | |
293 | } | |
294 | ||
295 | func TestTimedBufferedOutputError(t *testing.T) { | |
296 | cw := newCountdownWriter(1) | |
297 | ||
298 | o := nmsg.TimedBufferedOutput(cw, 100*time.Millisecond) | |
299 | o.SetMaxSize(1500, 0) | |
300 | if err := o.Send(testPayload(750)); err != nil { | |
301 | t.Error(err.Error()) | |
302 | } | |
303 | if err := o.Send(testPayload(750)); err != nil { | |
304 | t.Error(err.Error()) | |
305 | } | |
306 | // write should occur above, and leave one payload in buffer, | |
307 | // to be flushed by the next, which should return an error | |
308 | if err := o.Send(testPayload(750)); err == nil { | |
309 | t.Error("no error") | |
310 | } | |
311 | } | |
312 | ||
313 | func TestTimedBufferedOutputTimedError(t *testing.T) { | |
314 | cw := newCountdownWriter(0) | |
315 | o := nmsg.TimedBufferedOutput(cw, 100*time.Millisecond) | |
316 | if err := o.Send(testPayload(100)); err != nil { | |
317 | t.Error(err) | |
318 | } | |
319 | <-time.After(110 * time.Millisecond) | |
320 | // At this point, a timer-driven flush should have triggered | |
321 | // a writer error, which should be returned on the next Send. | |
322 | if err := o.Send(testPayload(100)); err == nil { | |
323 | t.Error("no error") | |
324 | } | |
325 | } | |
326 | ||
327 | type nullwriter struct{} | |
328 | ||
329 | func (n nullwriter) Write(b []byte) (int, error) { return len(b), nil } | |
330 | ||
331 | func BenchmarkUnbufferedOutput(b *testing.B) { | |
332 | var w nullwriter | |
333 | p, err := nmsg.Payload(testMessage(1000)) | |
334 | if err != nil { | |
335 | b.Error(err.Error()) | |
336 | } | |
337 | o := nmsg.UnbufferedOutput(w) | |
338 | o.SetMaxSize(1500, 0) | |
339 | for i := 0; i < b.N; i++ { | |
340 | if err := o.Send(p); err != nil { | |
341 | b.Error(err.Error()) | |
342 | return | |
343 | } | |
344 | } | |
345 | o.Close() | |
346 | } | |
347 | ||
348 | func BenchmarkBufferedOutput(b *testing.B) { | |
349 | var w nullwriter | |
350 | p, err := nmsg.Payload(testMessage(1000)) | |
351 | if err != nil { | |
352 | b.Error(err.Error()) | |
353 | } | |
354 | o := nmsg.BufferedOutput(w) | |
355 | o.SetMaxSize(1500, 0) | |
356 | o.SetSequenced(true) | |
357 | for i := 0; i < b.N; i++ { | |
358 | if err := o.Send(p); err != nil { | |
359 | b.Error(err.Error()) | |
360 | return | |
361 | } | |
362 | } | |
363 | o.Close() | |
364 | } | |
365 | ||
366 | func BenchmarkTimedBufferedOutput(b *testing.B) { | |
367 | var w nullwriter | |
368 | p, err := nmsg.Payload(testMessage(1000)) | |
369 | if err != nil { | |
370 | b.Error(err.Error()) | |
371 | } | |
372 | o := nmsg.TimedBufferedOutput(w, 100*time.Millisecond) | |
373 | o.SetMaxSize(1500, 0) | |
374 | o.SetSequenced(true) | |
375 | for i := 0; i < b.N; i++ { | |
376 | if err := o.Send(p); err != nil { | |
377 | b.Error(err.Error()) | |
378 | return | |
379 | } | |
380 | } | |
381 | o.Close() | |
382 | } |
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 | import ( | |
11 | "encoding/binary" | |
12 | "time" | |
13 | ||
14 | "github.com/golang/protobuf/proto" | |
15 | ) | |
16 | ||
17 | // Payload encapsulates an nmsg message in a NmsgPayload, suitable for sending to | |
18 | // an Output | |
19 | func Payload(m Message) (*NmsgPayload, error) { | |
20 | mbytes, err := proto.Marshal(m) | |
21 | if err != nil { | |
22 | return nil, err | |
23 | } | |
24 | now := time.Now().UnixNano() | |
25 | return &NmsgPayload{ | |
26 | Vid: proto.Uint32(m.GetVid()), | |
27 | Msgtype: proto.Uint32(m.GetMsgtype()), | |
28 | TimeSec: proto.Int64(now / 1000000000), | |
29 | TimeNsec: proto.Uint32(uint32(now % 1000000000)), | |
30 | Payload: mbytes, | |
31 | }, nil | |
32 | } | |
33 | ||
34 | // SetSource sets the NmsgPayload source identifier. | |
35 | func (p *NmsgPayload) SetSource(s uint32) { | |
36 | p.Source = proto.Uint32(s) | |
37 | } | |
38 | ||
39 | // SetOperator sets the NmsgPayload operator identifier. | |
40 | func (p *NmsgPayload) SetOperator(o uint32) { | |
41 | p.Operator = proto.Uint32(o) | |
42 | } | |
43 | ||
44 | // SetGroup sets the NmsgPayload group identifier. | |
45 | func (p *NmsgPayload) SetGroup(g uint32) { | |
46 | p.Group = proto.Uint32(g) | |
47 | } | |
48 | ||
49 | // Message returns the message encapsulated in the NmsgPayload, | |
50 | // Unmarshaled | |
51 | func (p *NmsgPayload) Message() (Message, error) { | |
52 | m, err := NewMessage(*p.Vid, *p.Msgtype) | |
53 | if err != nil { | |
54 | return nil, err | |
55 | } | |
56 | err = proto.Unmarshal(p.Payload, m) | |
57 | if err != nil { | |
58 | return nil, err | |
59 | } | |
60 | return m, nil | |
61 | } | |
62 | ||
63 | func (p *NmsgPayload) payloadSize() int { | |
64 | var ibuf [binary.MaxVarintLen64]byte | |
65 | ||
66 | psiz := proto.Size(p) | |
67 | // tag + varint length of encoded p | |
68 | psiz += 1 + binary.PutUvarint(ibuf[:], uint64(psiz)) | |
69 | // tag + varint CRC32 | |
70 | psiz += 1 + binary.MaxVarintLen32 | |
71 | return psiz | |
72 | } |
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 | "testing" | |
12 | ||
13 | "github.com/farsightsec/go-nmsg" | |
14 | "github.com/golang/protobuf/proto" | |
15 | ) | |
16 | ||
17 | func testMessage(length int) nmsg.Message { | |
18 | return &testMsg{Bytes: make([]byte, length)} | |
19 | } | |
20 | ||
21 | func testPayload(length int) *nmsg.NmsgPayload { | |
22 | p, err := nmsg.Payload(testMessage(length)) | |
23 | if err != nil { | |
24 | return nil | |
25 | } | |
26 | return p | |
27 | } | |
28 | ||
29 | type testMsg struct { | |
30 | Bytes []byte `protobuf:"bytes,2,opt,name=bytes"` | |
31 | } | |
32 | ||
33 | func (t *testMsg) GetVid() uint32 { return 10 } | |
34 | func (t *testMsg) GetMsgtype() uint32 { return 20 } | |
35 | ||
36 | func (t *testMsg) Reset() { *t = testMsg{} } | |
37 | func (t *testMsg) String() string { return proto.CompactTextString(t) } | |
38 | func (t *testMsg) ProtoMessage() {} | |
39 | ||
40 | func init() { | |
41 | nmsg.Register(&testMsg{}) | |
42 | } | |
43 | ||
44 | func TestRegister(t *testing.T) { | |
45 | msg, err := nmsg.NewMessage(10, 20) | |
46 | if err != nil { | |
47 | t.Error(err) | |
48 | } | |
49 | if _, ok := msg.(*testMsg); !ok { | |
50 | t.Errorf("NewMessage returned wrong type") | |
51 | } | |
52 | } | |
53 | ||
54 | func TestPayload(t *testing.T) { | |
55 | p, err := nmsg.Payload(testMessage(1000)) | |
56 | if err != nil { | |
57 | t.Errorf("nmsg.Payload(): %s", err) | |
58 | } | |
59 | ||
60 | m, err := p.Message() | |
61 | if err != nil { | |
62 | t.Error(err) | |
63 | } | |
64 | ||
65 | if tp, ok := m.(*testMsg); !ok { | |
66 | t.Errorf("Wrong type from payload") | |
67 | } else if len(tp.Bytes) != 1000 { | |
68 | t.Error("decode failed") | |
69 | } | |
70 | } |
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 | import ( | |
11 | "fmt" | |
12 | "reflect" | |
13 | ) | |
14 | ||
15 | var types map[uint32]map[uint32]reflect.Type | |
16 | ||
17 | // Register records the supplied message's type, indexed by its MessageType | |
18 | // and VendorID, for the purposes of decoding protobuf-encoded payloads. | |
19 | // | |
20 | // Register should be called from the init() function of the module defining | |
21 | // the payload type. It is not safe to call from multiple goroutines, and | |
22 | // may not be called if any goroutine is concurrently decoding NMSG payloads. | |
23 | func Register(m Message) { | |
24 | if types == nil { | |
25 | types = make(map[uint32]map[uint32]reflect.Type) | |
26 | } | |
27 | vid := m.GetVid() | |
28 | v, ok := types[vid] | |
29 | if !ok { | |
30 | v = make(map[uint32]reflect.Type) | |
31 | types[vid] = v | |
32 | } | |
33 | ||
34 | msgtype := m.GetMsgtype() | |
35 | v[msgtype] = reflect.TypeOf(m) | |
36 | } | |
37 | ||
38 | type unknownVendor uint32 | |
39 | ||
40 | func (v unknownVendor) Error() string { | |
41 | return fmt.Sprintf("Vendor %d has no registered Msgtypes.", v) | |
42 | } | |
43 | ||
44 | type unknownMsgtype struct{ vid, msgtype uint32 } | |
45 | ||
46 | func (t unknownMsgtype) Error() string { | |
47 | return fmt.Sprintf("Msgtype %d is not registered for vendor %d.", t.msgtype, t.vid) | |
48 | } | |
49 | ||
50 | // NewMessage creates a new Message with an underlying type identified | |
51 | // by vid, msgtype. | |
52 | func NewMessage(vid, msgtype uint32) (Message, error) { | |
53 | v, ok := types[vid] | |
54 | if !ok { | |
55 | return nil, unknownVendor(vid) | |
56 | } | |
57 | ||
58 | t, ok := v[msgtype] | |
59 | if !ok { | |
60 | return nil, unknownMsgtype{vid, msgtype} | |
61 | } | |
62 | ||
63 | return reflect.New(t.Elem()).Interface().(Message), nil | |
64 | } |
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 | "encoding/json" | |
12 | "fmt" | |
13 | "net" | |
14 | "strconv" | |
15 | "strings" | |
16 | ) | |
17 | ||
18 | // A Sockspec is an address of a single socket (addr/port) or a series of | |
19 | // sockets with contiguous port numbers (addr/loport..hiport) | |
20 | type Sockspec struct { | |
21 | Addr *net.UDPAddr | |
22 | Hiport int | |
23 | } | |
24 | ||
25 | // ParseSockspec creates a Sockspec from its text representaion v. | |
26 | func ParseSockspec(v string) (*Sockspec, error) { | |
27 | s := &Sockspec{} | |
28 | return s, s.Set(v) | |
29 | } | |
30 | ||
31 | // Set initializes a Sockspec from its text representation v. Set satisfies | |
32 | // flag.Value allowing a sockspec to be conveniently specified as a command | |
33 | // line parameter. | |
34 | func (s *Sockspec) Set(v string) error { | |
35 | l := strings.SplitN(v, "/", 2) | |
36 | if len(l) != 2 { | |
37 | return fmt.Errorf("Invalid sockspec: %s", v) | |
38 | } | |
39 | p := strings.SplitN(l[1], "..", 2) | |
40 | addr := fmt.Sprintf("%s:%s", l[0], p[0]) | |
41 | uaddr, err := net.ResolveUDPAddr("udp", addr) | |
42 | if err != nil { | |
43 | return fmt.Errorf("Invalid addr %s: %v", addr, err) | |
44 | } | |
45 | s.Addr = uaddr | |
46 | if len(p) == 1 { | |
47 | s.Hiport = uaddr.Port | |
48 | return nil | |
49 | } | |
50 | ||
51 | hiport, err := strconv.ParseUint(p[1], 10, 16) | |
52 | if err != nil { | |
53 | return fmt.Errorf("Invalid high port %s: %v", p[1], err) | |
54 | } | |
55 | ||
56 | if int(hiport) <= uaddr.Port { | |
57 | return fmt.Errorf("Invalid port range %s", l[1]) | |
58 | } | |
59 | s.Hiport = int(hiport) | |
60 | return nil | |
61 | } | |
62 | ||
63 | // UnmarshalJSON satisifies json.Unmarshaler allowing Sockspecs to be parsed | |
64 | // from JSON configurations. | |
65 | func (s *Sockspec) UnmarshalJSON(b []byte) error { | |
66 | var v string | |
67 | if err := json.Unmarshal(b, &v); err != nil { | |
68 | return err | |
69 | } | |
70 | return s.Set(v) | |
71 | } | |
72 | ||
73 | // UnmarshalYAML satisifies yaml.Unmarshaler allowing Sockspecs to be parsed | |
74 | // from YAML configurations. | |
75 | func (s *Sockspec) UnmarshalYAML(u func(interface{}) error) error { | |
76 | var v string | |
77 | if err := u(&v); err != nil { | |
78 | return err | |
79 | } | |
80 | return s.Set(v) | |
81 | } | |
82 | ||
83 | // Addrs returns the list of UDP socket addresses of the Sockspec, or nil | |
84 | // if the Sockspec is uninitialized. | |
85 | func (s *Sockspec) Addrs() []*net.UDPAddr { | |
86 | var addrs []*net.UDPAddr | |
87 | if s.Addr == nil { | |
88 | return nil | |
89 | } | |
90 | for i := s.Addr.Port; i <= s.Hiport; i++ { | |
91 | a := &net.UDPAddr{} | |
92 | *a = *s.Addr | |
93 | a.Port = i | |
94 | addrs = append(addrs, a) | |
95 | } | |
96 | return addrs | |
97 | } | |
98 | ||
99 | // String returns the string representation of the Sockspec. If the Sockspec | |
100 | // is uninitialized, String returns the empty string. | |
101 | func (s *Sockspec) String() string { | |
102 | if s.Addr == nil { | |
103 | return "" | |
104 | } | |
105 | if s.Hiport > s.Addr.Port { | |
106 | return fmt.Sprintf("%s/%d..%d", s.Addr.IP.String(), | |
107 | s.Addr.Port, s.Hiport) | |
108 | } | |
109 | return fmt.Sprintf("%s/%d", s.Addr.IP.String(), s.Addr.Port) | |
110 | } |
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 | "encoding/json" | |
12 | "testing" | |
13 | ||
14 | yaml "gopkg.in/yaml.v2" | |
15 | ) | |
16 | ||
17 | var sockspecTestCases = []struct { | |
18 | sockspec string | |
19 | valid bool | |
20 | naddrs int | |
21 | }{ | |
22 | {"127.0.0.1/382", true, 1}, | |
23 | {"127.0.0.1/382..390", true, 9}, | |
24 | {"foobar", false, 0}, | |
25 | {"127.0.0.1/foobar", false, 0}, | |
26 | {"127.0.0.1/390..382", false, 0}, | |
27 | {"127.0.0.1/390..foobar", false, 0}, | |
28 | {"invalid_hostname/381", false, 0}, | |
29 | } | |
30 | ||
31 | func testSockSpecCommon(t *testing.T, parse func(string, *Sockspec) error) { | |
32 | t.Helper() | |
33 | for _, tc := range sockspecTestCases { | |
34 | var ss Sockspec | |
35 | if err := parse(tc.sockspec, &ss); err != nil { | |
36 | if tc.valid { | |
37 | t.Errorf("%s: %v", tc.sockspec, err) | |
38 | } | |
39 | continue | |
40 | } | |
41 | if !tc.valid { | |
42 | t.Errorf("parsed invalid sockspec %s", tc.sockspec) | |
43 | continue | |
44 | } | |
45 | if len(ss.Addrs()) != tc.naddrs { | |
46 | t.Errorf("%s: expected %d addrs, got %d", tc.sockspec, | |
47 | tc.naddrs, len(ss.Addrs())) | |
48 | } | |
49 | if ss.String() != tc.sockspec { | |
50 | t.Errorf("%s parsed to %s (%#v)", tc.sockspec, &ss, ss) | |
51 | } | |
52 | } | |
53 | } | |
54 | ||
55 | func TestSockSpecSet(t *testing.T) { | |
56 | testSockSpecCommon(t, func(s string, ss *Sockspec) error { | |
57 | return ss.Set(s) | |
58 | }) | |
59 | } | |
60 | ||
61 | func TestSockSpecParse(t *testing.T) { | |
62 | testSockSpecCommon(t, func(s string, ss *Sockspec) error { | |
63 | parsed, err := ParseSockspec(s) | |
64 | *ss = *parsed | |
65 | return err | |
66 | }) | |
67 | } | |
68 | ||
69 | func TestSockSpecJSON(t *testing.T) { | |
70 | testSockSpecCommon(t, func(s string, ss *Sockspec) error { | |
71 | b, err := json.Marshal(s) | |
72 | if err != nil { | |
73 | return err | |
74 | } | |
75 | return json.Unmarshal(b, ss) | |
76 | }) | |
77 | } | |
78 | ||
79 | func TestSockSpecYAML(t *testing.T) { | |
80 | testSockSpecCommon(t, func(s string, ss *Sockspec) error { | |
81 | b, err := yaml.Marshal(s) | |
82 | if err != nil { | |
83 | return err | |
84 | } | |
85 | return yaml.Unmarshal(b, ss) | |
86 | }) | |
87 | } |
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 | import ( | |
11 | "bytes" | |
12 | "compress/zlib" | |
13 | "encoding/binary" | |
14 | "io" | |
15 | ) | |
16 | ||
17 | func zbufDeflate(b []byte) ([]byte, error) { | |
18 | buf := new(bytes.Buffer) | |
19 | binary.Write(buf, binary.BigEndian, uint32(len(b))) | |
20 | w := zlib.NewWriter(buf) | |
21 | if _, err := w.Write(b); err != nil { | |
22 | return nil, err | |
23 | } | |
24 | if err := w.Close(); err != nil { | |
25 | return nil, err | |
26 | } | |
27 | return buf.Bytes(), nil | |
28 | } | |
29 | ||
30 | func zbufInflate(b []byte) ([]byte, error) { | |
31 | br := bytes.NewReader(b) | |
32 | var ilen uint32 | |
33 | binary.Read(br, binary.BigEndian, &ilen) | |
34 | buf := bytes.NewBuffer(make([]byte, 0, int(ilen))) | |
35 | r, err := zlib.NewReader(br) | |
36 | if err != nil { | |
37 | return nil, err | |
38 | } | |
39 | if _, err = io.Copy(buf, r); err != nil { | |
40 | return nil, err | |
41 | } | |
42 | r.Close() | |
43 | return buf.Bytes(), nil | |
44 | } |
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 | "testing" | |
13 | ||
14 | "github.com/farsightsec/go-nmsg" | |
15 | ) | |
16 | ||
17 | func TestZlib(t *testing.T) { | |
18 | b := new(bytes.Buffer) | |
19 | m := testMessage(20) | |
20 | p, err := nmsg.Payload(m) | |
21 | if err != nil { | |
22 | t.Fatal(err) | |
23 | } | |
24 | out := nmsg.UnbufferedOutput(b) | |
25 | out.SetCompression(true) | |
26 | out.SetMaxSize(1500, 0) | |
27 | if err := out.Send(p); err != nil { | |
28 | t.Fatal(err) | |
29 | } | |
30 | ||
31 | inp := nmsg.NewInput(b, 1500) | |
32 | p, err = inp.Recv() | |
33 | if err != nil { | |
34 | t.Fatal(err) | |
35 | } | |
36 | mm, err := p.Message() | |
37 | if err != nil { | |
38 | t.Fatal(err) | |
39 | } | |
40 | mi, ok := mm.(*testMsg) | |
41 | if !ok { | |
42 | t.Error("received message of wrong type") | |
43 | } | |
44 | if len(mi.Bytes) != len(m.(*testMsg).Bytes) { | |
45 | t.Error("received message of wrong length") | |
46 | } | |
47 | for i := range mi.Bytes { | |
48 | if mi.Bytes[i] != 0 { | |
49 | t.Fatal("received message with wrong data") | |
50 | } | |
51 | } | |
52 | ||
53 | } |