1 /*
2 ** Copyright (C) 2001-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8 
9 /*
10 **  rwrec.h
11 **
12 **    The SiLK Flow record (rwRec) definition and functions/macros for
13 **    manipulating it.
14 **
15 */
16 #ifndef _RWREC_H
17 #define _RWREC_H
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 #include <silk/silk.h>
23 
24 RCSIDENTVAR(rcsID_RWREC_H, "$SiLK: rwrec.h ef14e54179be 2020-04-14 21:57:45Z mthomas $");
25 
26 #include <silk/silk_types.h>
27 
28 #ifndef RWREC_OPAQUE
29 #  define RWREC_OPAQUE 0
30 #  include <silk/skipaddr.h>
31 #endif
32 
33 
34 /*
35  * The following documents macros defined in this file that work to
36  * access and manipulate the data in an rwRec.  Although these are
37  * macros, they have been documented as functions in order to convey
38  * the expected types of the arguments.
39  *
40  * ****  Convenience macros  ****
41  *
42  *   void RWREC_CLEAR(rwRec *r);
43  *    Zero out the record, and set Sensor ID and Flowtype to invalid
44  *    values.
45  *
46  *   void RWREC_COPY(rwRec *dst, const rwRec *src);
47  *    Copy the rwRec from 'src' to 'dst'.
48  *
49  *   int rwRecIsICMP(const rwRec *r);
50  *    Returns non-zero if the record is an ICMP record, zero otherwise.
51  *
52  *   int rwRecIsWeb(const rwRec *r);
53  *    Returns non-zero if the record can be represented using the SiLK
54  *    web-specific file formats, zero otherwise.
55  *
56  *
57  * **** More macros ****
58  *
59  * Function versions of all of the following macros exist.  Simply
60  * change the "rwRec" prefix of the macro to "rwrec_" to use the
61  * function version.
62  *
63  * ***  Whether a record is IPv6  ***
64  *
65  * int      rwRecIsIPv6(const rwRec *r);
66  *
67  * ***  Set record as IPv4 or IPv6  ***
68  *
69  * void     rwRecSetIPv6(rwRec *r);
70  * void     rwRecSetIPv4(rwRec *r);
71  *
72  * It is important to note that the above two macros do not do any
73  * conversions on the contained IP addresses.  They are primarily to
74  * be used when creating a new rwRec from scratch.  See the following
75  * for conversion.
76  *
77  * ***  Convert record to IPv4 or IPv6  ***
78  *
79  * int      rwRecConvertToIPv4(rwRec *r);
80  * void     rwRecConvertToIPv6(rwRec *r);
81  *
82  * These macros convert an rwRec to IPv4 or IPv6.  The latter always
83  * succeeds.  The former will return -1 if unable to convert due to
84  * the existence of IPv6 addresses that cannot be represented as IPv4
85  * (and return zero on success).
86  *
87  * ****  rwRec accessor macros ****
88  *
89  * Most of the following accessor macros come in five standard
90  * variations:
91  *
92  *   <fieldtype> rwRecGet<field>(const reRec *r)
93  *    Gets the value of the field directly
94  *
95  *   void rwRecSet<field>(rwRec *r, <fieldtype> in_v)
96  *    Sets the value of the field to 'in_v'
97  *
98  *   void rwRecMemGet<field>(const rwRec *r, <fieldtype> *out_vp)
99  *    Copies the value of the field to location out_vp
100  *
101  *   void rwRecMemSet<field>(rwRec *r, const <fieldtype> *in_vp)
102  *    Copies the value in location in_vp into the field
103  *
104  *   int rwRecMemCmp<field>(const rwRec *r, const <fieldtype> *vp)
105  *    Compares the field to the value in location vp, returning a
106  *    negative integer if the field is less than vp, 0 if equal, and a
107  *    positive integer if greater than vp.
108  *
109  * For the rwRecMem{Get,Set,Cmp}<field>() macros, we use of
110  * <fieldtype> in the comment to explain the size of the data
111  * involved.  With the exception of those dealing the skipaddr_t
112  * objects, the actual functions use void pointers; as a result, those
113  * macros do not require the value pointer to be aligned.  The macros
114  * that handle values larger than uint8_t use memcpy() or memcmp() to
115  * copy or compare the values.
116  *
117  * ** IP Address Macros **
118  *
119  * For handling IP addresses, there are three sets of macros: one for
120  * IPv4 addresses: one for IPv6 addresses, and one for skipaddr_t
121  * objects, which can represent either an IPv4 address or and IPv6
122  * object.
123  *
124  * In addition to the Get, Set, and Comparison macros, the follow
125  * macro exists in IPv4, IPv6, and skipaddr_t varieties:
126  *
127  *   void rwRecApplyMask<field>(rwRec *r, const <fieldtype> mask);
128  *    Modify the rwRec's <field> IP addresses by applying the
129  *    specified mask (using a bit-wise AND) to that IP address.
130  *
131  * All of the macros that deal with IPv4 addresses assume that you
132  * know the rwRec holds IPv4 addresses.  No conversion of the rwRec or
133  * of the address occurs.
134  *
135  * Using the Get macros for IPv6 on an rwRec that contains V4 data
136  * will return a properly encoded IPv4-in-IPv6 address.  All other
137  * macros for IPv6 assume you know that the rwRec holds IPv6
138  * addresses.  For IPv6, the rwRecGet<field>() and rwRecSet<field>()
139  * macros do not exist; you must use the rwRecMemGet<field>() and
140  * rwRecMemSet<field>() versions.
141  *
142  * Since an skipaddr_t can hold an IPv4 or an IPv6 address, the macros
143  * that use skipaddr_t objects will correctly handle with rwRecs that
144  * hold IPv4 or IPv6 data.  Setting or masking an IPv4 rwRec with an
145  * IPv6 skipaddr_t may convert the record to IPv6.  The comparison
146  * macros will operate in IPv6 space if either argument involves IPv6.
147  * Unlike all other rwRecMem{Get,Set,Cmp}<field>() macros, the
148  * functions that work with skipaddr_t pointers require the skipaddr_t
149  * to be properly aligned.
150  *
151  * The IPv4 macros include an extra DEPRECATED macro:
152  *
153  *   uint32_t rwRecGetMask<field>v4(rwRec *r, uint32_t mask)
154  *    Gets the value of the field with the given bit-mask applied
155  *
156  * ***  Source IPv4 Address (sIP)  ***
157  *
158  * uint32_t rwRecGetSIPv4(const rwRec *r);
159  * void     rwRecSetSIPv4(rwRec *r, uint32_t in_v);
160  * void     rwRecMemGetSIPv4(const rwRec *r, uint32_t *out_vp);
161  * void     rwRecMemSetSIPv4(rwRec *r, const uint32_t *in_vp);
162  * int      rwRecMemCmpSIPv4(const rwRec *r, const uint32_t *vp);
163  * void     rwRecApplyMaskSIPv4(rwRec *r, uint32_t mask);
164  * uint32_t rwRecGetMaskSIPv4(const rwRec *r, uint32_t mask);
165  *
166  * ***  Source IPv6 Address (sIP)  ***
167  *
168  * void     rwRecMemGetSIPv6(const rwRec *r, uint8_t[16] out_vp);
169  * void     rwRecMemSetSIPv6(rwRec *r, const uint8_t[16] in_vp);
170  * int      rwRecMemCmpSIPv6(const rwRec *r, const uint8_t[16] vp);
171  * void     rwRecApplyMaskSIPv6(rwRec *r, const uint8_t[16] mask);
172  *
173  * ***  Source IP Address (sIP) as skipaddr_t  ***
174  *
175  * void     rwRecMemGetSIP(const rwRec *r, skipaddr_t *out_addr);
176  * void     rwRecMemSetSIP(rwRec *r, const skipaddr_t *in_addr);
177  * int      rwRecMemCmpSIP(const rwRec *r, const skipaddr_t *addr);
178  * void     rwRecApplyMaskSIP(rwRec *r, const skipaddr_t *mask);
179  *
180  * ***  Destination IP Address (dIP)  ***
181  *
182  * uint32_t rwRecGetDIPv4(const rwRec *r);
183  * void     rwRecSetDIPv4(rwRec *r, uint32_t in_v);
184  * void     rwRecMemGetDIPv4(const rwRec *r, uint32_t *out_vp);
185  * void     rwRecMemSetDIPv4(rwRec *r, const uint32_t *in_vp);
186  * int      rwRecMemCmpDIPv4(const rwRec *r, const uint32_t *vp);
187  * void     rwRecApplyMaskDIPv4(rwRec *r, uint32_t mask);
188  * uint32_t rwRecGetMaskDIPv4(const rwRec *r, uint32_t mask);
189  *
190  * ***  Destination IPv6 Address (dIP)  ***
191  *
192  * void     rwRecMemGetDIPv6(const rwRec *r, uint8_t[16] out_vp);
193  * void     rwRecMemSetDIPv6(rwRec *r, const uint8_t[16] in_vp);
194  * int      rwRecMemCmpDIPv6(const rwRec *r, const uint8_t[16] vp);
195  * void     rwRecApplyMaskDIPv6(rwRec *r, const uint8_t[16] mask);
196  *
197  * ***  Destination IP Address (dIP) as skipaddr_t  ***
198  *
199  * void     rwRecMemGetDIP(const rwRec *r, skipaddr_t *out_addr);
200  * void     rwRecMemSetDIP(rwRec *r, const skipaddr_t *in_addr);
201  * int      rwRecMemCmpDIP(const rwRec *r, const skipaddr_t *addr);
202  * void     rwRecApplyMaskDIP(rwRec *r, const skipaddr_t *mask);
203  *
204  * ***  Next Hop IP Address  ***
205  *
206  * uint32_t rwRecGetNhIPv4(const rwRec *r);
207  * void     rwRecSetNhIPv4(rwRec *r, uint32_t in_v);
208  * void     rwRecMemGetNhIPv4(const rwRec *r, uint32_t *out_vp);
209  * void     rwRecMemSetNhIPv4(rwRec *r, const uint32_t *in_vp);
210  * int      rwRecMemCmpNhIPv4(const rwRec *r, const uint32_t *vp);
211  * void     rwRecApplyMaskNhIPv4(rwRec *r, uint32_t mask);
212  * uint32_t rwRecGetMaskNhIPv4(const rwRec *r, uint32_t mask);
213  *
214  * ***  Next Hop IPv6 Address (nhIP)  ***
215  *
216  * void     rwRecMemGetNhIPv6(const rwRec *r, uint8_t[16] out_vp);
217  * void     rwRecMemSetNhIPv6(rwRec *r, const uint8_t[16] in_vp);
218  * int      rwRecMemCmpNhIPv6(const rwRec *r, const uint8_t[16] vp);
219  * void     rwRecApplyMaskNhIPv6(rwRec *r, const uint8_t[16] mask);
220  *
221  * ***  Next Hop IP Address (nhIP) as skipaddr_t  ***
222  *
223  * void     rwRecMemGetNhIP(const rwRec *r, skipaddr_t *out_addr);
224  * void     rwRecMemSetNhIP(rwRec *r, const skipaddr_t *in_addr);
225  * int      rwRecMemCmpNhIP(const rwRec *r, const skipaddr_t *addr);
226  * void     rwRecApplyMaskNhIP(rwRec *r, const skipaddr_t *mask);
227  *
228  * ***  Source Port (sPort)  ***
229  *
230  * uint16_t rwRecGetSPort(const rwRec *r);
231  * void     rwRecSetSPort(rwRec *r, uint16_t in_v);
232  * void     rwRecMemGetSPort(const rwRec *r, uint16_t *out_vp);
233  * void     rwRecMemSetSPort(rwRec *r, const uint16_t *in_vp);
234  * int      rwRecMemCmpSPort(const rwRec *r, const uint16_t *vp);
235  *
236  * ***  Destination Port (dPort)  ***
237  *
238  * uint16_t rwRecGetDPort(const rwRec *r);
239  * void     rwRecSetDPort(rwRec *r, uint16_t in_v);
240  * void     rwRecMemGetDPort(const rwRec *r, uint16_t *out_vp);
241  * void     rwRecMemSetDPort(rwRec *r, const uint16_t *in_vp);
242  * int      rwRecMemCmpDPort(const rwRec *r, const uint16_t *vp);
243  *
244  * ***  Protocol  ***
245  *
246  * uint8_t  rwRecGetProto(const rwRec *r);
247  * void     rwRecSetProto(rwRec *r, uint8_t in_v);
248  * void     rwRecMemGetProto(const rwRec *r, uint8_t *out_vp);
249  * void     rwRecMemSetProto(rwRec *r, const uint8_t *in_vp);
250  * int      rwRecMemCmpProto(const rwRec *r, const uint8_t *vp);
251  *
252  * ***  Packet Count (pkts)  ***
253  *
254  * uint32_t rwRecGetPkts(const rwRec *r);
255  * void     rwRecSetPkts(rwRec *r, uint32_t in_v);
256  * void     rwRecMemGetPkts(const rwRec *r, uint32_t *out_vp);
257  * void     rwRecMemSetPkts(rwRec *r, const uint32_t *in_vp);
258  * int      rwRecMemCmpPkts(const rwRec *r, const uint32_t *vp);
259  *
260  * ***  Byte count  ***
261  *
262  * uint32_t rwRecGetBytes(const rwRec *r);
263  * void     rwRecSetBytes(rwRec *r, uint32_t in_v);
264  * void     rwRecMemGetBytes(const rwRec *r, uint32_t *out_vp);
265  * void     rwRecMemSetBytes(rwRec *r, const uint32_t *in_vp);
266  * int      rwRecMemCmpBytes(const rwRec *r, const uint32_t *vp);
267  *
268  * ***  Bitwise OR of TCP Flags on ALL packets in flow  ***
269  *
270  * uint8_t  rwRecGetFlags(const rwRec *r);
271  * void     rwRecSetFlags(rwRec *r, uint8_t in_v);
272  * void     rwRecMemGetFlags(const rwRec *r, uint8_t *out_vp);
273  * void     rwRecMemSetFlags(rwRec *r, const uint8_t *in_vp);
274  * int      rwRecMemCmpFlags(const rwRec *r, const uint8_t *vp);
275  *
276  * ***  TCP Flags seen on initial packet of flow  ***
277  *
278  * uint8_t  rwRecGetInitFlags(const rwRec *r);
279  * void     rwRecSetInitFlags(rwRec *r, uint8_t in_v);
280  * void     rwRecMemGetInitFlags(const rwRec *r, uint8_t *out_vp);
281  * void     rwRecMemSetInitFlags(rwRec *r, const uint8_t *in_vp);
282  * int      rwRecMemCmpInitFlags(const rwRec *r, const uint8_t *vp);
283  *
284  * ***  Bitwise OR of TCP Flags on all packets in session except first  ***
285  *
286  * uint8_t  rwRecGetRestFlags(const rwRec *r);
287  * void     rwRecSetRestFlags(rwRec *r, uint8_t in_v);
288  * void     rwRecMemGetRestFlags(const rwRec *r, uint8_t *out_vp);
289  * void     rwRecMemSetRestFlags(rwRec *r, const uint8_t *in_vp);
290  * int      rwRecMemCmpRestFlags(const rwRec *r, const uint8_t *vp);
291  *
292  * ***  Start Time as milliseconds since UNIX epoch (sTime)  ***
293  *
294  * sktime_t rwRecGetStartTime(const rwRec *r);
295  * void     rwRecSetStartTime(rwRec *r, sktime_t in_v);
296  * void     rwRecMemGetStartTime(const rwRec *r, sktime_t *out_vp);
297  * void     rwRecMemSetStartTime(rwRec *r, const sktime_t *in_vp);
298  * int      rwRecMemCmpStartTime(const rwRec *r, const sktime_t *vp);
299  *
300  * uint32_t rwRecGetStartSeconds(const rwRec *r);
301  * void     rwRecMemGetStartSeconds(const rwRec *r, uint32_t *out_vp);
302  *
303  * ***  End Time is derived from the sTime and duration (eTime)  ***
304  *
305  * sktime_t rwRecGetEndTime(const rwRec *r);
306  * void     rwRecMemGetEndTime(const rwRec *r, sktime_t *out_vp);
307  *
308  * uint32_t rwRecGetEndSeconds(const rwRec *r);
309  * void     rwRecMemGetEndSeconds(const rwRec *r, uint32_t *out_vp);
310  *
311  * There are no setter macros for end time, because end time is
312  * derived from start time and duration (elapsed time).
313  *
314  * ***  Elapsed (duration) of the flow, in milliseconds  ***
315  *
316  * uint32_t rwRecGetElapsed(const rwRec *r);
317  * void     rwRecSetElapsed(rwRec *r, uint32_t in_v);
318  * void     rwRecMemGetElapsed(const rwRec *r, uint32_t *out_vp);
319  * void     rwRecMemSetElapsed(rwRec *r, const uint32_t *in_vp);
320  * int      rwRecMemCmpElapsed(const rwRec *r, const uint32_t *vp);
321  *
322  * uint32_t rwRecGetElapsedSeconds(const rwRec *r);
323  * void     rwRecMemGetElapsedSeconds(const rwRec *r, uint32_t *out_vp);
324  *
325  * ***  Sensor ID (sID)  ***
326  *
327  * sensorID_t rwRecGetSensor(const rwRec *r);
328  * void     rwRecSetSensor(rwRec *r, sensorID_t in_v);
329  * void     rwRecMemGetSensor(const rwRec *r, sensorID_t *out_vp);
330  * void     rwRecMemSetSensor(rwRec *r, const sensorID_t *in_vp);
331  * int      rwRecMemCmpSensor(const rwRec *r, const sensorID_t *vp);
332  *
333  * ***  FlowType holds Class and Type  ***
334  *
335  * flowtypeID_t rwRecGetFlowType(const rwRec *r);
336  * void     rwRecSetFlowType(rwRec *r, flowtypeID_t in_v);
337  * void     rwRecMemGetFlowType(const rwRec *r, flowtypeID_t *out_vp);
338  * void     rwRecMemSetFlowType(rwRec *r, const flowtypeID_t *in_vp);
339  * int      rwRecMemCmpFlowType(const rwRec *r, const flowtypeID_t *vp);
340  *
341  * ***  SNMP Input Value (Router incoming/ingress interface/vlanId) ***
342  *
343  * uint16_t rwRecGetInput(const rwRec *r);
344  * void     rwRecSetInput(rwRec *r, uint16_t in_v);
345  * void     rwRecMemGetInput(const rwRec *r, uint16_t *out_vp);
346  * void     rwRecMemSetInput(rwRec *r, const uint16_t *in_vp);
347  * int      rwRecMemCmpInput(const rwRec *r, const uint16_t *vp);
348  *
349  * ***  SNMP Output Value (Router outgoing/egress interface/postVlanId) ***
350  *
351  * uint16_t rwRecGetOutput(const rwRec *r);
352  * void     rwRecSetOutput(rwRec *r, uint16_t in_v);
353  * void     rwRecMemGetOutput(const rwRec *r, uint16_t *out_vp);
354  * void     rwRecMemSetOutput(rwRec *r, const uint16_t *in_vp);
355  * int      rwRecMemCmpOutput(const rwRec *r, const uint16_t *vp);
356  *
357  * ***  TCP State (the Attributes field)  ***
358  *
359  * uint8_t  rwRecGetTcpState(const rwRec *r);
360  * void     rwRecSetTcpState(rwRec *r, uint8_t in_v);
361  * void     rwRecMemGetTcpState(const rwRec *r, uint8_t *out_vp);
362  * void     rwRecMemSetTcpState(rwRec *r, const uint8_t *in_vp);
363  * int      rwRecMemCmpTcpState(const rwRec *r, const uint8_t *vp);
364  *
365  * The TCP state field is a bit field which states certain miscellaneous
366  * information about the flow record.  The following constants are
367  * defined which represent this information:
368  *
369  * #define SK_TCPSTATE_EXPANDED              0x01
370  *  Expanded TCP-flags: This bit must be set if and only if the flow
371  *  is TCP and the init_flags and rest_flags fields are set.
372  *
373  * #define SK_TCPSTATE_FIN_FOLLOWED_NOT_ACK  0x08
374  *  Flow received packets following the FIN packet that were not ACK or
375  *  RST packets.
376  *
377  * #define SK_TCPSTATE_UNIFORM_PACKET_SIZE   0x10
378  *  Flow has packets all of the same size
379  *
380  * #define SK_TCPSTATE_TIMEOUT_KILLED        0x20
381  *  Flow ends prematurely due to a timeout by the collector.
382  *
383  * #define SK_TCPSTATE_TIMEOUT_STARTED       0x40
384  *  Flow is a continuation of a previous flow that was killed
385  *  prematurely due to a timeout by the collector.
386  *
387  * Note: the most significant bit of tcp_state (0x80) is used as a flag
388  * to mark a record as having IPv6 addresses.  The rwRecSetIPv4() and
389  * rwRecSetIPv6() macros should be used to modify this bit.
390  *
391  * Be careful when setting the TCP state.  You usually want get the
392  * current TCP state, add or remove specific bits by masking, then set it
393  * with the resulting value.
394  *
395  * ***  Application  ***
396  *
397  * uint16_t rwRecGetApplication(const rwRec *r);
398  * void     rwRecSetApplication(rwRec *r, uint16_t in_v);
399  * void     rwRecMemGetApplication(const rwRec *r, uint16_t *out_vp);
400  * void     rwRecMemSetApplication(rwRec *r, const uint16_t *in_vp);
401  * int      rwRecMemCmpApplication(const rwRec *r, const uint16_t *vp);
402  *
403  * The application field can be set by the yaf flow generation
404  * software when it is configured with the "applabel" feature.  This
405  * feature causes yaf to inspect the packets in the flow and guess as
406  * to the type of application (HTTP, SMTP, SSH, etc) the packets
407  * represent.  The value for the field is the standard service port
408  * for that service (80, 25, 22, etc).
409  *
410  * ***  Memo  ***
411  *
412  * uint16_t rwRecGetMemo(const rwRec *r);
413  * void     rwRecSetMemo(rwRec *r, uint16_t in_v);
414  * void     rwRecMemGetMemo(const rwRec *r, uint16_t *out_vp);
415  * void     rwRecMemSetMemo(rwRec *r, const uint16_t *in_vp);
416  * int      rwRecMemCmpMemo(const rwRec *r, const uint16_t *vp);
417  *
418  * Currently unused.
419  *
420  * ***  ICMP Type and Code is derived from the DPort  ***
421  *
422  * uint8_t  rwRecGetIcmpType(const rwRec *r);
423  * void     rwRecSetIcmpType(rwRec *r, uint8_t in_v);
424  * void     rwRecMemGetIcmpType(const rwRec *r, uint8_t *out_vp);
425  *
426  * uint8_t  rwRecGetIcmpCode(const rwRec *r);
427  * void     rwRecSetIcmpCode(rwRec *r, uint8_t in_v);
428  * void     rwRecMemGetIcmpCode(const rwRec *r, uint8_t *out_vp);
429  *
430  * uint16_t rwRecGetIcmpTypeAndCode(const rwRec *r);
431  * void     rwRecSetIcmpTypeAndCode(rwRec *r, uint16_t in_v);
432  * void     rwRecMemGetIcmpTypeAndCode(const rwRec *r, uint16_t *out_vp);
433  * void     rwRecMemSetIcmpTypeAndCode(rwRec *r, const uint16_t *in_vp);
434  * int      rwRecMemCmpIcmpTypeAndCode(const rwRec *r, const uint16_t *vp);
435  *
436  * Since the ICMP Type and Code are stored in the dport field, modifying
437  * these will modify the return value of rwRecGetDPort() and friends.
438  */
439 
440 
441 #define SK_WEBPORT_CHECK(p) ((p) == 80 || (p) == 443 || (p) == 8080)
442 /*
443  *    Return a true value if port 'p' is a "web" port; false otherwise
444  */
445 
446 #define RWREC_CLEAR(rec)                                     \
447     do {                                                     \
448         memset((rec), 0, sizeof(rwRec));                     \
449         rwRecSetSensor((rec), SK_INVALID_SENSOR);            \
450         rwRecSetFlowType((rec), SK_INVALID_FLOWTYPE);        \
451     } while(0)
452 /*
453  *    Zero out the record, and set Sensor ID and Flowtype to invalid
454  *    values.
455  */
456 
457 
458 #define RWREC_COPY(dst, src)                    \
459     memcpy((dst), (src), sizeof(rwRec))
460 /*
461  *    Copy the rwRec from 'src' to 'dst'.
462  */
463 
464 
465 /*
466  *  This is the generic SiLK Flow record returned from ANY file format
467  *  containing packed SiLK Flow records.
468  *
469  *  typedef struct rwGenericRec_V5_st rwGenericRec_V5_t; // silk_types.h
470  *  typedef rwGenericRec_V5_t rwRec;                     // silk_types.h
471  */
472 struct rwGenericRec_V5_st {
473 #if RWREC_OPAQUE && !defined(RWREC_DEFINE_BODY)
474 #if SK_ENABLE_IPV6
475     uint8_t         ar[88];
476 #else
477     uint8_t         ar[52];
478 #endif
479 #else
480     int64_t         sTime;       /*  0- 7  Flow start time in milliseconds
481                                   *        since UNIX epoch */
482 
483     uint32_t        elapsed;     /*  8-11  Duration of flow in millisecs */
484 
485     uint16_t        sPort;       /* 12-13  Source port */
486     uint16_t        dPort;       /* 14-15  Destination port */
487 
488     uint8_t         proto;       /* 16     IP protocol */
489     sk_flowtype_id_t flow_type;  /* 17     Class & Type info */
490     sk_sensor_id_t  sID;         /* 18-19  Sensor ID */
491 
492     uint8_t         flags;       /* 20     OR of all flags (Netflow flags) */
493     uint8_t         init_flags;  /* 21     TCP flags in first packet
494                                   *        or blank for "legacy" data */
495     uint8_t         rest_flags;  /* 22     TCP flags on non-initial packet
496                                   *        or blank for "legacy" data */
497     uint8_t         tcp_state;   /* 23     TCP state machine info (below) */
498 
499     uint16_t        application; /* 24-25  "Service" port set by collector */
500     uint16_t        memo;        /* 26-27  Application specific field */
501 
502     uint16_t        input;       /* 28-29  Router incoming SNMP interface */
503     uint16_t        output;      /* 30-31  Router outgoing SNMP interface */
504 
505     uint32_t        pkts;        /* 32-35  Count of packets */
506     uint32_t        bytes;       /* 36-39  Count of bytes */
507 
508     skIPUnion_t     sIP;         /* 40-43  (or 40-55 if IPv6) Source IP */
509     skIPUnion_t     dIP;         /* 44-47  (or 56-71 if IPv6) Destination IP */
510     skIPUnion_t     nhIP;        /* 48-51  (or 72-87 if IPv6) Routr NextHop IP*/
511 #endif  /* RWREC_OPAQUE && !defined(RWREC_DEFINE_BODY) */
512 };
513 
514 
515 /*
516 **  Values for tcp_state value in rwGeneric and packed formats
517 */
518 
519 /* No additional TCP-state machine information is available */
520 #define SK_TCPSTATE_NO_INFO               0x00
521 
522 /* Expanded TCP-flags: This bit must be set if and only if the flow is
523  * TCP and the init_flags and rest_flags fields are valid.  */
524 #define SK_TCPSTATE_EXPANDED              0x01
525 
526 /* Unused SK_TCPSTATE_  0x02 */
527 /* Unused SK_TCPSTATE_  0x04 */
528 
529 /* Flow received packets following the FIN packet that were not ACK or
530  * RST packets. */
531 #define SK_TCPSTATE_FIN_FOLLOWED_NOT_ACK  0x08
532 
533 /* Flow has packets all of the same size */
534 #define SK_TCPSTATE_UNIFORM_PACKET_SIZE   0x10
535 
536 /* Flow ends prematurely due to a timeout by the collector. */
537 #define SK_TCPSTATE_TIMEOUT_KILLED        0x20
538 
539 /* Flow is a continuation of a previous flow that was killed
540  * prematurely due to a timeout by the collector. */
541 #define SK_TCPSTATE_TIMEOUT_STARTED       0x40
542 
543 /* Define a mask that returns the defined bits in tcpstate.  This is
544  * used internally by rwRecGetTcpState(), rwRecSetTcpState() */
545 #define SK_TCPSTATE_MASK                  0x79
546 
547 /* Define a mask that returns the attribute bits in tcpstate. */
548 #define SK_TCPSTATE_ATTRIBUTE_MASK        0x78
549 
550 /* Note: the most significant bit of tcp_state (0x80) is used as a
551  * flag to mark a record as having IPv6 addresses. */
552 
553 
554 /* the sizeof the fields in an rwRec */
555 #define RWREC_SIZEOF_SIPv4        4
556 #define RWREC_SIZEOF_DIPv4        4
557 #define RWREC_SIZEOF_NHIPv4       4
558 #define RWREC_SIZEOF_SPORT        2
559 #define RWREC_SIZEOF_DPORT        2
560 #define RWREC_SIZEOF_INPUT        2
561 #define RWREC_SIZEOF_OUTPUT       2
562 #define RWREC_SIZEOF_STIME        8
563 #define RWREC_SIZEOF_ELAPSED      4
564 #define RWREC_SIZEOF_PKTS         4
565 #define RWREC_SIZEOF_BYTES        4
566 #define RWREC_SIZEOF_PROTO        1
567 #define RWREC_SIZEOF_FLOW_TYPE    1
568 #define RWREC_SIZEOF_SID          2
569 #define RWREC_SIZEOF_FLAGS        1
570 #define RWREC_SIZEOF_INIT_FLAGS   1
571 #define RWREC_SIZEOF_REST_FLAGS   1
572 #define RWREC_SIZEOF_TCP_STATE    1
573 #define RWREC_SIZEOF_APPLICATION  2
574 #define RWREC_SIZEOF_MEMO         2
575 #define RWREC_SIZEOF_SIPv6       16
576 #define RWREC_SIZEOF_DIPv6       16
577 #define RWREC_SIZEOF_NHIPv6      16
578 
579 #if !SK_ENABLE_IPV6
580 #  define RWREC_SIZEOF_SIP  RWREC_SIZEOF_SIPv4
581 #  define RWREC_SIZEOF_DIP  RWREC_SIZEOF_DIPv4
582 #  define RWREC_SIZEOF_NHIP RWREC_SIZEOF_NHIPv4
583 #else
584 #  define RWREC_SIZEOF_SIP  RWREC_SIZEOF_SIPv6
585 #  define RWREC_SIZEOF_DIP  RWREC_SIZEOF_DIPv6
586 #  define RWREC_SIZEOF_NHIP RWREC_SIZEOF_NHIPv6
587 #endif /* SK_ENABLE_IPV6 */
588 
589 
590 /* Helper macros */
591 #if 0
592 #  define MEMCPY8(dst, src)   { *((uint8_t*)(dst))  = *((uint8_t*)(src)); }
593 #  define MEMCPY16(dst, src)  { *((uint16_t*)(dst)) = *((uint16_t*)(src)); }
594 #  define MEMCPY32(dst, src)  { *((uint32_t*)(dst)) = *((uint32_t*)(src)); }
595 #else
596 #  define MEMCPY8(dst, src)   memcpy((dst), (src), sizeof(uint8_t))
597 #  define MEMCPY16(dst, src)  memcpy((dst), (src), sizeof(uint16_t))
598 #  define MEMCPY32(dst, src)  memcpy((dst), (src), sizeof(uint32_t))
599 #endif
600 
601 
602 /***  Whether record is ICMP  ***/
603 
604 #define rwRecIsICMP(r)                                                  \
605     ((IPPROTO_ICMP == rwRecGetProto(r))                                 \
606      || (rwRecIsIPv6(r) && (IPPROTO_ICMPV6 == rwRecGetProto(r))))
607 
608 
609 /***  Whether record is WEB/HTTP  ***/
610 
611 #define rwRecIsWeb(r)                                   \
612     ((IPPROTO_TCP == rwRecGetProto(r))                  \
613      && (SK_WEBPORT_CHECK(rwRecGetSPort(r))             \
614          || SK_WEBPORT_CHECK(rwRecGetDPort(r))))
615 
616 
617 /***  Whether record is IPv6  ***/
618 
619 #if !SK_ENABLE_IPV6
620 #  define rwRecIsIPv6(r)  0
621 #else
622 
623 int  rwrec_IsIPv6(const rwRec *r);
624 void rwrec_SetIPv6(rwRec *r);
625 void rwrec_SetIPv4(rwRec *r);
626 
627 #define _recIsIPv6(r)                           \
628     (((r)->tcp_state & 0x80) ? 1 : 0)
629 #define _recSetIPv6(r)                          \
630     { (r)->tcp_state |= 0x80; }
631 #define _recSetIPv4(r)                          \
632     { (r)->tcp_state &= 0x7F; }
633 
634 #if RWREC_OPAQUE
635 #  define rwRecIsIPv6(r)    rwrec_IsIPv6(r)
636 #  define rwRecSetIPv6(r)   rwrec_SetIPv6(r)
637 #  define rwRecSetIPv4(r)   rwrec_SetIPv4(r)
638 #else
639 #  define rwRecIsIPv6(r)    _recIsIPv6(r)
640 #  define rwRecSetIPv6(r)   _recSetIPv6(r)
641 #  define rwRecSetIPv4(r)   _recSetIPv4(r)
642 #endif /* RWREC_OPAQUE */
643 
644 #endif  /* SK_ENABLE_IPV6 */
645 
646 
647 /***  Convert a Record to IPv6 or IPv4  ***/
648 
649 #if SK_ENABLE_IPV6
650 
651 void rwrec_ConvertToIPv6(rwRec *r);
652 int  rwrec_ConvertToIPv4(rwRec *r);
653 
654 #define _recConvertToIPv6(r)                    \
655     {                                           \
656         skIPUnion4to6(&(r)->sIP, &(r)->sIP);    \
657         skIPUnion4to6(&(r)->dIP, &(r)->dIP);    \
658         skIPUnion4to6(&(r)->nhIP, &(r)->nhIP);  \
659         _recSetIPv6(r);                         \
660     }
661 
662 #if RWREC_OPAQUE
663 #  define rwRecConvertToIPv6(r)   rwrec_ConvertToIPv6(r)
664 #  define rwRecConvertToIPv4(r)   rwrec_ConvertToIPv4(r)
665 #else
666 #  define rwRecConvertToIPv6(r)   _recConvertToIPv6(r)
667 #  define rwRecConvertToIPv4(r)   rwrec_ConvertToIPv4(r)
668 #endif /* RWREC_OPAQUE */
669 
670 #endif  /* SK_ENABLE_IPV6 */
671 
672 
673 /***  Source IPv4 Address (sIP)  ***/
674 
675 uint32_t rwrec_GetSIPv4(const rwRec *r);
676 void     rwrec_SetSIPv4(rwRec *r, uint32_t in_v);
677 void     rwrec_MemGetSIPv4(const rwRec *r, void *out_vp);
678 void     rwrec_MemSetSIPv4(rwRec *r, const void *in_vp);
679 int      rwrec_MemCmpSIPv4(const rwRec *r, const void *vp);
680 uint32_t rwrec_GetMaskSIPv4(const rwRec *r, uint32_t mask);
681 void     rwrec_ApplyMaskSIPv4(rwRec *r, uint32_t mask);
682 
683 #define _recGetSIPv4(r)                         \
684     ((r)->sIP.ipu_ipv4)
685 #define _recSetSIPv4(r, in_v)                   \
686     { ((r)->sIP.ipu_ipv4) = (in_v); }
687 #define _recMemGetSIPv4(r, out_vp)                              \
688     memcpy((out_vp), &((r)->sIP.ipu_ipv4), RWREC_SIZEOF_SIPv4)
689 #define _recMemSetSIPv4(r, in_vp)                               \
690     memcpy(&((r)->sIP.ipu_ipv4), (in_vp), RWREC_SIZEOF_SIPv4)
691 #define _recMemCmpSIPv4(r, vp)                          \
692     memcmp(&((r)->sIP.ipu_ipv4), (vp), RWREC_SIZEOF_SIPv4)
693 #define _recGetMaskSIPv4(r, mask)               \
694     (((r)->sIP.ipu_ipv4) & mask)
695 #define _recApplyMaskSIPv4(r, mask)             \
696     skIPUnionApplyMaskV4(&((r)->sIP), (mask))
697 
698 #if RWREC_OPAQUE
699 #  define rwRecGetSIPv4(r)              rwrec_GetSIPv4(r)
700 #  define rwRecSetSIPv4(r, in_v)        rwrec_SetSIPv4(r, in_v)
701 #  define rwRecMemGetSIPv4(r, out_vp)   rwrec_MemGetSIPv4(r, out_vp)
702 #  define rwRecMemSetSIPv4(r, in_vp)    rwrec_MemSetSIPv4(r, in_vp)
703 #  define rwRecMemCmpSIPv4(r, vp)       rwrec_MemCmpSIPv4(r, vp)
704 #  define rwRecGetMaskSIPv4(r, mask)    rwrec_GetMaskSIPv4(r, mask)
705 #  define rwRecApplyMaskSIPv4(r, mask)  rwrec_ApplyMaskSIPv4(r, mask)
706 #else
707 #  define rwRecGetSIPv4(r)              _recGetSIPv4(r)
708 #  define rwRecSetSIPv4(r, in_v)        _recSetSIPv4(r, in_v)
709 #  define rwRecMemGetSIPv4(r, out_vp)   _recMemGetSIPv4(r, out_vp)
710 #  define rwRecMemSetSIPv4(r, in_vp)    _recMemSetSIPv4(r, in_vp)
711 #  define rwRecMemCmpSIPv4(r, vp)       _recMemCmpSIPv4(r, vp)
712 #  define rwRecGetMaskSIPv4(r, mask)    _recGetMaskSIPv4(r, mask)
713 #  define rwRecApplyMaskSIPv4(r, mask)  _recApplyMaskSIPv4(r, mask)
714 #endif /* RWREC_OPAQUE */
715 
716 
717 /***  Source IPv6 Address (sIP)  ***/
718 
719 #if SK_ENABLE_IPV6
720 
721 void     rwrec_MemGetSIPv6(const rwRec *r, void *out_vp);
722 void     rwrec_MemSetSIPv6(rwRec *r, const void *in_vp);
723 int      rwrec_MemCmpSIPv6(const rwRec *r, const void *vp);
724 void     rwrec_ApplyMaskSIPv6(rwRec *r, const void *mask_vp);
725 
726 #define _recMemGetSIPv6(r, out_vp)                      \
727     if (_recIsIPv6(r)) {                                \
728         skIPUnionGetV6(&((r)->sIP), (out_vp));          \
729     } else {                                            \
730         skIPUnionGetV4AsV6(&((r)->sIP), (out_vp));      \
731     }
732 #define _recMemSetSIPv6(r, in_vp)                               \
733     memcpy(&((r)->sIP.ipu_ipv6), (in_vp), RWREC_SIZEOF_SIPv6)
734 #define _recMemCmpSIPv6(r, vp)                                  \
735     memcmp(&((r)->sIP.ipu_ipv6), (vp), RWREC_SIZEOF_SIPv6)
736 #define _recApplyMaskSIPv6(r, mask)             \
737     skIPUnionApplyMaskV6(&((r)->sIP), (mask))
738 
739 #if RWREC_OPAQUE
740 #  define rwRecMemGetSIPv6(r, out_vp)   rwrec_MemGetSIPv6(r, out_vp)
741 #  define rwRecMemSetSIPv6(r, in_vp)    rwrec_MemSetSIPv6(r, in_vp)
742 #  define rwRecMemCmpSIPv6(r, vp)       rwrec_MemCmpSIPv6(r, vp)
743 #  define rwRecApplyMaskSIPv6(r, mask)  rwrec_ApplyMaskSIPv6(r, mask)
744 #else
745 #  define rwRecMemGetSIPv6(r, out_vp)   _recMemGetSIPv6(r, out_vp)
746 #  define rwRecMemSetSIPv6(r, in_vp)    _recMemSetSIPv6(r, in_vp)
747 #  define rwRecMemCmpSIPv6(r, vp)       _recMemCmpSIPv6(r, vp)
748 #  define rwRecApplyMaskSIPv6(r, mask)  _recApplyMaskSIPv6(r, mask)
749 #endif /* RWREC_OPAQUE */
750 
751 #endif  /* SK_ENABLE_IPV6 */
752 
753 
754 /***  Source IP Address (sIP) as skipaddr_t  ***/
755 
756 void     rwrec_MemGetSIP(const rwRec *r, skipaddr_t *out_addr);
757 void     rwrec_MemSetSIP(rwRec *r, const skipaddr_t *in_addr);
758 int      rwrec_MemCmpSIP(const rwRec *r, const skipaddr_t *addr);
759 void     rwrec_ApplyMaskSIP(rwRec *r, const skipaddr_t *mask_addr);
760 
761 #if !SK_ENABLE_IPV6
762 #define _recMemGetSIP _recMemGetSIPv4
763 #define _recMemSetSIP _recMemSetSIPv4
764 #define _recMemCmpSIP(r, addr)                          \
765     _recMemCmpSIPv4((r), &((addr)->ip_ip.ipu_ipv4))
766 #define _recApplyMaskSIP(r, addr)                       \
767     _recApplyMaskSIPv4((r), (addr)->ip_ip.ipu_ipv4)
768 #else
769 #define _recMemGetSIP(r, out_addr)                              \
770     do {                                                        \
771         memcpy(out_addr, &((r)->sIP), sizeof(skIPUnion_t));     \
772         skipaddrSetVersion((out_addr), _recIsIPv6(r));          \
773     } while(0)
774 #define _recMemSetSIP(r, in_addr)                                       \
775     do {                                                                \
776         if (skipaddrIsV6(in_addr) == _recIsIPv6(r)) {                   \
777             /* both are either V4 or V6 */                              \
778             memcpy(&((r)->sIP), (in_addr), sizeof(skIPUnion_t));        \
779         } else if (_recIsIPv6(r)) {                                     \
780             /* convert V4 IP to V6 */                                   \
781             skIPUnion4to6(&((in_addr)->ip_ip), &((r)->sIP));            \
782         } else {                                                        \
783             /* must convert record to V6 */                             \
784             _recConvertToIPv6(r);                                       \
785             memcpy(&((r)->sIP), (in_addr), sizeof(skIPUnion_t));        \
786         }                                                               \
787     } while(0)
788 #define _recMemCmpSIP(r, addr)      rwrec_MemCmpSIP(r, addr)
789 #define _recApplyMaskSIP(r, addr)   rwrec_ApplyMaskSIP(r, addr)
790 #endif /* SK_ENABLE_IPV6 */
791 
792 #if RWREC_OPAQUE
793 #  define rwRecMemGetSIP(r, out_addr)   rwrec_MemGetSIP(r, out_addr)
794 #  define rwRecMemSetSIP(r, in_addr)    rwrec_MemSetSIP(r, in_addr)
795 #  define rwRecMemCmpSIP(r, addr)       rwrec_MemCmpSIP(r, addr)
796 #  define rwRecApplyMaskSIP(r, addr)    rwrec_ApplyMaskSIP(r, addr)
797 #else
798 #  define rwRecMemGetSIP(r, out_addr)   _recMemGetSIP(r, out_addr)
799 #  define rwRecMemSetSIP(r, in_addr)    _recMemSetSIP(r, in_addr)
800 #  define rwRecMemCmpSIP(r, addr)       _recMemCmpSIP(r, addr)
801 #  define rwRecApplyMaskSIP(r, addr)    _recApplyMaskSIP(r, addr)
802 #endif /* RWREC_OPAQUE */
803 
804 
805 /***  Destination IP Address (dIP)  ***/
806 
807 uint32_t rwrec_GetDIPv4(const rwRec *r);
808 void     rwrec_SetDIPv4(rwRec *r, uint32_t in_v);
809 void     rwrec_MemGetDIPv4(const rwRec *r, void *out_vp);
810 void     rwrec_MemSetDIPv4(rwRec *r, const void *in_vp);
811 int      rwrec_MemCmpDIPv4(const rwRec *r, const void *vp);
812 uint32_t rwrec_GetMaskDIPv4(const rwRec *r, uint32_t mask);
813 void     rwrec_ApplyMaskDIPv4(rwRec *r, uint32_t mask);
814 
815 #define _recGetDIPv4(r)                         \
816     ((r)->dIP.ipu_ipv4)
817 #define _recSetDIPv4(r, in_v)                   \
818     { ((r)->dIP.ipu_ipv4) = (in_v); }
819 #define _recMemGetDIPv4(r, out_vp)                              \
820     memcpy((out_vp), &((r)->dIP.ipu_ipv4), RWREC_SIZEOF_DIPv4)
821 #define _recMemSetDIPv4(r, in_vp)                               \
822     memcpy(&((r)->dIP.ipu_ipv4), (in_vp), RWREC_SIZEOF_DIPv4)
823 #define _recMemCmpDIPv4(r, vp)                          \
824     memcmp(&((r)->dIP.ipu_ipv4), (vp), RWREC_SIZEOF_DIPv4)
825 #define _recGetMaskDIPv4(r, mask)               \
826     (((r)->dIP.ipu_ipv4) & mask)
827 #define _recApplyMaskDIPv4(r, mask)             \
828     skIPUnionApplyMaskV4(&((r)->dIP), (mask))
829 
830 
831 #if RWREC_OPAQUE
832 #  define rwRecGetDIPv4(r)              rwrec_GetDIPv4(r)
833 #  define rwRecSetDIPv4(r, in_v)        rwrec_SetDIPv4(r, in_v)
834 #  define rwRecMemGetDIPv4(r, out_vp)   rwrec_MemGetDIPv4(r, out_vp)
835 #  define rwRecMemSetDIPv4(r, in_vp)    rwrec_MemSetDIPv4(r, in_vp)
836 #  define rwRecMemCmpDIPv4(r, vp)       rwrec_MemCmpDIPv4(r, vp)
837 #  define rwRecGetMaskDIPv4(r, mask)    rwrec_GetMaskDIPv4(r, mask)
838 #  define rwRecApplyMaskDIPv4(r, mask)  rwrec_ApplyMaskDIPv4(r, mask)
839 #else
840 #  define rwRecGetDIPv4(r)              _recGetDIPv4(r)
841 #  define rwRecSetDIPv4(r, in_v)        _recSetDIPv4(r, in_v)
842 #  define rwRecMemGetDIPv4(r, out_vp)   _recMemGetDIPv4(r, out_vp)
843 #  define rwRecMemSetDIPv4(r, in_vp)    _recMemSetDIPv4(r, in_vp)
844 #  define rwRecMemCmpDIPv4(r, vp)       _recMemCmpDIPv4(r, vp)
845 #  define rwRecGetMaskDIPv4(r, mask)    _recGetMaskDIPv4(r, mask)
846 #  define rwRecApplyMaskDIPv4(r, mask)  _recApplyMaskDIPv4(r, mask)
847 #endif /* RWREC_OPAQUE */
848 
849 
850 /***  Destination IPv6 Address (dIP)  ***/
851 
852 #if SK_ENABLE_IPV6
853 
854 void     rwrec_MemGetDIPv6(const rwRec *r, void *out_vp);
855 void     rwrec_MemSetDIPv6(rwRec *r, const void *in_vp);
856 int      rwrec_MemCmpDIPv6(const rwRec *r, const void *vp);
857 void     rwrec_ApplyMaskDIPv6(rwRec *r, const void *mask_vp);
858 
859 #define _recMemGetDIPv6(r, out_vp)                      \
860     if (_recIsIPv6(r)) {                                \
861         skIPUnionGetV6(&((r)->dIP), (out_vp));          \
862     } else {                                            \
863         skIPUnionGetV4AsV6(&((r)->dIP), (out_vp));      \
864     }
865 #define _recMemSetDIPv6(r, in_vp)                               \
866     memcpy(&((r)->dIP.ipu_ipv6), (in_vp), RWREC_SIZEOF_DIPv6)
867 #define _recMemCmpDIPv6(r, vp)                                  \
868     memcmp(&((r)->dIP.ipu_ipv6), (vp), RWREC_SIZEOF_DIPv6)
869 #define _recApplyMaskDIPv6(r, mask)             \
870     skIPUnionApplyMaskV6(&((r)->dIP), (mask))
871 
872 #if RWREC_OPAQUE
873 #  define rwRecMemGetDIPv6(r, out_vp)   rwrec_MemGetDIPv6(r, out_vp)
874 #  define rwRecMemSetDIPv6(r, in_vp)    rwrec_MemSetDIPv6(r, in_vp)
875 #  define rwRecMemCmpDIPv6(r, vp)       rwrec_MemCmpDIPv6(r, vp)
876 #  define rwRecApplyMaskDIPv6(r, mask)  rwrec_ApplyMaskDIPv6(r, mask)
877 #else
878 #  define rwRecMemGetDIPv6(r, out_vp)   _recMemGetDIPv6(r, out_vp)
879 #  define rwRecMemSetDIPv6(r, in_vp)    _recMemSetDIPv6(r, in_vp)
880 #  define rwRecMemCmpDIPv6(r, vp)       _recMemCmpDIPv6(r, vp)
881 #  define rwRecApplyMaskDIPv6(r, mask)  _recApplyMaskDIPv6(r, mask)
882 #endif /* RWREC_OPAQUE */
883 
884 #endif  /* SK_ENABLE_IPV6 */
885 
886 
887 /***  Destination IP Address (dIP) as skipaddr_t  ***/
888 
889 void     rwrec_MemGetDIP(const rwRec *r, skipaddr_t *out_addr);
890 void     rwrec_MemSetDIP(rwRec *r, const skipaddr_t *in_addr);
891 int      rwrec_MemCmpDIP(const rwRec *r, const skipaddr_t *addr);
892 void     rwrec_ApplyMaskDIP(rwRec *r, const skipaddr_t *mask_addr);
893 
894 #if !SK_ENABLE_IPV6
895 #define _recMemGetDIP _recMemGetDIPv4
896 #define _recMemSetDIP _recMemSetDIPv4
897 #define _recMemCmpDIP(r, addr)                          \
898     _recMemCmpDIPv4((r), &((addr)->ip_ip.ipu_ipv4))
899 #define _recApplyMaskDIP(r, addr)                       \
900     _recApplyMaskDIPv4((r), (addr)->ip_ip.ipu_ipv4)
901 #else
902 #define _recMemGetDIP(r, out_addr)                              \
903     do {                                                        \
904         memcpy(out_addr, &((r)->dIP), sizeof(skIPUnion_t));     \
905         skipaddrSetVersion((out_addr), _recIsIPv6(r));          \
906     } while(0)
907 #define _recMemSetDIP(r, in_addr)                                       \
908     do {                                                                \
909         if (skipaddrIsV6(in_addr) == _recIsIPv6(r)) {                   \
910             /* both are either V4 or V6 */                              \
911             memcpy(&((r)->dIP), (in_addr), sizeof(skIPUnion_t));        \
912         } else if (_recIsIPv6(r)) {                                     \
913             /* convert V4 IP to V6 */                                   \
914             skIPUnion4to6(&((in_addr)->ip_ip), &((r)->dIP));            \
915         } else {                                                        \
916             /* must convert record to V6 */                             \
917             _recConvertToIPv6(r);                                       \
918             memcpy(&((r)->dIP), (in_addr), sizeof(skIPUnion_t));        \
919         }                                                               \
920     } while(0)
921 #define _recMemCmpDIP(r, addr)      rwrec_MemCmpDIP(r, addr)
922 #define _recApplyMaskDIP(r, addr)   rwrec_ApplyMaskDIP(r, addr)
923 #endif /* SK_ENABLE_IPV6 */
924 
925 #if RWREC_OPAQUE
926 #  define rwRecMemGetDIP(r, out_addr)   rwrec_MemGetDIP(r, out_addr)
927 #  define rwRecMemSetDIP(r, in_addr)    rwrec_MemSetDIP(r, in_addr)
928 #  define rwRecMemCmpDIP(r, addr)       rwrec_MemCmpDIP(r, addr)
929 #  define rwRecApplyMaskDIP(r, addr)    rwrec_ApplyMaskDIP(r, addr)
930 #else
931 #  define rwRecMemGetDIP(r, out_addr)   _recMemGetDIP(r, out_addr)
932 #  define rwRecMemSetDIP(r, in_addr)    _recMemSetDIP(r, in_addr)
933 #  define rwRecMemCmpDIP(r, addr)       _recMemCmpDIP(r, addr)
934 #  define rwRecApplyMaskDIP(r, addr)    _recApplyMaskDIP(r, addr)
935 #endif /* RWREC_OPAQUE */
936 
937 
938 /***  Next Hop IP (nhIP) Address  ***/
939 
940 uint32_t rwrec_GetNhIPv4(const rwRec *r);
941 void     rwrec_SetNhIPv4(rwRec *r, uint32_t in_v);
942 void     rwrec_MemGetNhIPv4(const rwRec *r, void *out_vp);
943 void     rwrec_MemSetNhIPv4(rwRec *r, const void *in_vp);
944 int      rwrec_MemCmpNhIPv4(const rwRec *r, const void *vp);
945 uint32_t rwrec_GetMaskNhIPv4(const rwRec *r, uint32_t mask);
946 void     rwrec_ApplyMaskNhIPv4(rwRec *r, uint32_t mask);
947 
948 #define _recGetNhIPv4(r)                        \
949     ((r)->nhIP.ipu_ipv4)
950 #define _recSetNhIPv4(r, in_v)                  \
951     { ((r)->nhIP.ipu_ipv4) = (in_v); }
952 #define _recMemGetNhIPv4(r, out_vp)                             \
953     memcpy((out_vp), &((r)->nhIP.ipu_ipv4), RWREC_SIZEOF_NHIPv4)
954 #define _recMemSetNhIPv4(r, in_vp)                              \
955     memcpy(&((r)->nhIP.ipu_ipv4), (in_vp), RWREC_SIZEOF_NHIPv4)
956 #define _recMemCmpNhIPv4(r, vp)                         \
957     memcmp(&((r)->nhIP.ipu_ipv4), (vp), RWREC_SIZEOF_NHIPv4)
958 #define _recGetMaskNhIPv4(r, mask)              \
959     (((r)->nhIP.ipu_ipv4) & mask)
960 #define _recApplyMaskNhIPv4(r, mask)            \
961     skIPUnionApplyMaskV4(&((r)->nhIP), (mask))
962 
963 
964 #if RWREC_OPAQUE
965 #  define rwRecGetNhIPv4(r)             rwrec_GetNhIPv4(r)
966 #  define rwRecSetNhIPv4(r, in_v)       rwrec_SetNhIPv4(r, in_v)
967 #  define rwRecMemGetNhIPv4(r, out_vp)  rwrec_MemGetNhIPv4(r, out_vp)
968 #  define rwRecMemSetNhIPv4(r, in_vp)   rwrec_MemSetNhIPv4(r, in_vp)
969 #  define rwRecMemCmpNhIPv4(r, vp)      rwrec_MemCmpNhIPv4(r, vp)
970 #  define rwRecGetMaskNhIPv4(r, mask)   rwrec_GetMaskNhIPv4(r, mask)
971 #  define rwRecApplyMaskNhIPv4(r, mask) rwrec_ApplyMaskNhIPv4(r, mask)
972 #else
973 #  define rwRecGetNhIPv4(r)             _recGetNhIPv4(r)
974 #  define rwRecSetNhIPv4(r, in_v)       _recSetNhIPv4(r, in_v)
975 #  define rwRecMemGetNhIPv4(r, out_vp)  _recMemGetNhIPv4(r, out_vp)
976 #  define rwRecMemSetNhIPv4(r, in_vp)   _recMemSetNhIPv4(r, in_vp)
977 #  define rwRecMemCmpNhIPv4(r, vp)      _recMemCmpNhIPv4(r, vp)
978 #  define rwRecGetMaskNhIPv4(r, mask)   _recGetMaskNhIPv4(r, mask)
979 #  define rwRecApplyMaskNhIPv4(r, mask) _recApplyMaskNhIPv4(r, mask)
980 #endif /* RWREC_OPAQUE */
981 
982 
983 /***  Next Hop IPv6 Address (nhIP)  ***/
984 
985 #if SK_ENABLE_IPV6
986 
987 void     rwrec_MemGetNhIPv6(const rwRec *r, void *out_vp);
988 void     rwrec_MemSetNhIPv6(rwRec *r, const void *in_vp);
989 int      rwrec_MemCmpNhIPv6(const rwRec *r, const void *vp);
990 void     rwrec_ApplyMaskNhIPv6(rwRec *r, const void *mask_vp);
991 
992 #define _recMemGetNhIPv6(r, out_vp)                     \
993     if (_recIsIPv6(r)) {                                \
994         skIPUnionGetV6(&((r)->nhIP), (out_vp));         \
995     } else {                                            \
996         skIPUnionGetV4AsV6(&((r)->nhIP), (out_vp));     \
997     }
998 #define _recMemSetNhIPv6(r, in_vp)                              \
999     memcpy(&((r)->nhIP.ipu_ipv6), (in_vp), RWREC_SIZEOF_NHIPv6)
1000 #define _recMemCmpNhIPv6(r, vp)                                 \
1001     memcmp(&((r)->nhIP.ipu_ipv6), (vp), RWREC_SIZEOF_NHIPv6)
1002 #define _recApplyMaskNhIPv6(r, mask)            \
1003     skIPUnionApplyMaskV6(&((r)->nhIP), (mask))
1004 
1005 #if RWREC_OPAQUE
1006 #  define rwRecMemGetNhIPv6(r, out_vp)   rwrec_MemGetNhIPv6(r, out_vp)
1007 #  define rwRecMemSetNhIPv6(r, in_vp)    rwrec_MemSetNhIPv6(r, in_vp)
1008 #  define rwRecMemCmpNhIPv6(r, vp)       rwrec_MemCmpNhIPv6(r, vp)
1009 #  define rwRecApplyMaskNhIPv6(r, mask)  rwrec_ApplyMaskNhIPv6(r, mask)
1010 #else
1011 #  define rwRecMemGetNhIPv6(r, out_vp)   _recMemGetNhIPv6(r, out_vp)
1012 #  define rwRecMemSetNhIPv6(r, in_vp)    _recMemSetNhIPv6(r, in_vp)
1013 #  define rwRecMemCmpNhIPv6(r, vp)       _recMemCmpNhIPv6(r, vp)
1014 #  define rwRecApplyMaskNhIPv6(r, mask)  _recApplyMaskNhIPv6(r, mask)
1015 #endif /* RWREC_OPAQUE */
1016 
1017 #endif /* SK_ENABLE_IPV6 */
1018 
1019 
1020 /***  Next Hop IP Address (nhIP) as skipaddr_t  ***/
1021 
1022 void     rwrec_MemGetNhIP(const rwRec *r, skipaddr_t *out_addr);
1023 void     rwrec_MemSetNhIP(rwRec *r, const skipaddr_t *in_addr);
1024 int      rwrec_MemCmpNhIP(const rwRec *r, const skipaddr_t *addr);
1025 void     rwrec_ApplyMaskNhIP(rwRec *r, const skipaddr_t *mask_addr);
1026 
1027 #if !SK_ENABLE_IPV6
1028 #define _recMemGetNhIP    _recMemGetNhIPv4
1029 #define _recMemSetNhIP    _recMemSetNhIPv4
1030 #define _recMemCmpNhIP(r, addr)                         \
1031     _recMemCmpNhIPv4((r), &((addr)->ip_ip.ipu_ipv4))
1032 #define _recApplyMaskNhIP(r, addr)                      \
1033     _recApplyMaskNhIPv4((r), (addr)->ip_ip.ipu_ipv4)
1034 #else
1035 #define _recMemGetNhIP(r, out_addr)                             \
1036     do {                                                        \
1037         memcpy(out_addr, &((r)->nhIP), sizeof(skIPUnion_t));    \
1038         skipaddrSetVersion((out_addr), _recIsIPv6(r));          \
1039     } while(0)
1040 #define _recMemSetNhIP(r, in_addr)                                      \
1041     do {                                                                \
1042         if (skipaddrIsV6(in_addr) == _recIsIPv6(r)) {                   \
1043             /* both are either V4 or V6 */                              \
1044             memcpy(&((r)->nhIP), (in_addr), sizeof(skIPUnion_t));       \
1045         } else if (_recIsIPv6(r)) {                                     \
1046             /* convert V4 IP to V6 */                                   \
1047             skIPUnion4to6(&((in_addr)->ip_ip), &((r)->nhIP));           \
1048         } else {                                                        \
1049             /* must convert record to V6 */                             \
1050             _recConvertToIPv6(r);                                       \
1051             memcpy(&((r)->nhIP), (in_addr), sizeof(skIPUnion_t));       \
1052         }                                                               \
1053     } while(0)
1054 #define _recMemCmpNhIP(r, addr)     rwrec_MemCmpNhIP(r, addr)
1055 #define _recApplyMaskNhIP(r, addr)  rwrec_ApplyMaskNhIP(r, addr)
1056 #endif /* SK_ENABLE_IPV6 */
1057 
1058 #if RWREC_OPAQUE
1059 #  define rwRecMemGetNhIP(r, out_addr)  rwrec_MemGetNhIP(r, out_addr)
1060 #  define rwRecMemSetNhIP(r, in_addr)   rwrec_MemSetNhIP(r, in_addr)
1061 #  define rwRecMemCmpNhIP(r, addr)      rwrec_MemCmpNhIP(r, addr)
1062 #  define rwRecApplyMaskNhIP(r, addr)   rwrec_ApplyMaskNhIP(r, addr)
1063 #else
1064 #  define rwRecMemGetNhIP(r, out_addr)  _recMemGetNhIP(r, out_addr)
1065 #  define rwRecMemSetNhIP(r, in_addr)   _recMemSetNhIP(r, in_addr)
1066 #  define rwRecMemCmpNhIP(r, addr)      _recMemCmpNhIP(r, addr)
1067 #  define rwRecApplyMaskNhIP(r, addr)   _recApplyMaskNhIP(r, addr)
1068 #endif /* RWREC_OPAQUE */
1069 
1070 
1071 /***  Source Port (sPort)  ***/
1072 
1073 uint16_t rwrec_GetSPort(const rwRec *r);
1074 void     rwrec_SetSPort(rwRec *r, uint16_t in_v);
1075 void     rwrec_MemGetSPort(const rwRec *r, void *out_vp);
1076 void     rwrec_MemSetSPort(rwRec *r, const void *in_vp);
1077 int      rwrec_MemCmpSPort(const rwRec *r, const void *vp);
1078 
1079 #define _recGetSPort(r)                         \
1080     ((r)->sPort)
1081 #define _recSetSPort(r, in_v)                   \
1082     { ((r)->sPort) = (in_v); }
1083 #define _recMemGetSPort(r, out_vp)                      \
1084     memcpy((out_vp), &((r)->sPort), RWREC_SIZEOF_SPORT)
1085 #define _recMemSetSPort(r, in_vp)                       \
1086     memcpy(&((r)->sPort), (in_vp), RWREC_SIZEOF_SPORT)
1087 #define _recMemCmpSPort(r, vp)                          \
1088     memcmp(&((r)->sPort), (vp), RWREC_SIZEOF_SPORT)
1089 
1090 #if RWREC_OPAQUE
1091 #  define rwRecGetSPort(r)  rwrec_GetSPort(r)
1092 #  define rwRecSetSPort(r, in_v)  rwrec_SetSPort(r, in_v)
1093 #  define rwRecMemGetSPort(r, out_vp)  rwrec_MemGetSPort(r, out_vp)
1094 #  define rwRecMemSetSPort(r, in_vp)  rwrec_MemSetSPort(r, in_vp)
1095 #  define rwRecMemCmpSPort(r, vp)  rwrec_MemCmpSPort(r, vp)
1096 #else
1097 #  define rwRecGetSPort(r)  _recGetSPort(r)
1098 #  define rwRecSetSPort(r, in_v)  _recSetSPort(r, in_v)
1099 #  define rwRecMemGetSPort(r, out_vp)  _recMemGetSPort(r, out_vp)
1100 #  define rwRecMemSetSPort(r, in_vp)  _recMemSetSPort(r, in_vp)
1101 #  define rwRecMemCmpSPort(r, vp)  _recMemCmpSPort(r, vp)
1102 #endif /* RWREC_OPAQUE */
1103 
1104 
1105 /***  Destination Port (dPort)  ***/
1106 
1107 uint16_t rwrec_GetDPort(const rwRec *r);
1108 void     rwrec_SetDPort(rwRec *r, uint16_t in_v);
1109 void     rwrec_MemGetDPort(const rwRec *r, void *out_vp);
1110 void     rwrec_MemSetDPort(rwRec *r, const void *in_vp);
1111 int      rwrec_MemCmpDPort(const rwRec *r, const void *vp);
1112 
1113 #define _recGetDPort(r)                         \
1114     ((r)->dPort)
1115 #define _recSetDPort(r, in_v)                   \
1116     { ((r)->dPort) = (in_v); }
1117 #define _recMemGetDPort(r, out_vp)                      \
1118     memcpy((out_vp), &((r)->dPort), RWREC_SIZEOF_DPORT)
1119 #define _recMemSetDPort(r, in_vp)                       \
1120     memcpy(&((r)->dPort), (in_vp), RWREC_SIZEOF_DPORT)
1121 #define _recMemCmpDPort(r, vp)                          \
1122     memcmp(&((r)->dPort), (vp), RWREC_SIZEOF_DPORT)
1123 
1124 #if RWREC_OPAQUE
1125 #  define rwRecGetDPort(r)  rwrec_GetDPort(r)
1126 #  define rwRecSetDPort(r, in_v)  rwrec_SetDPort(r, in_v)
1127 #  define rwRecMemGetDPort(r, out_vp)  rwrec_MemGetDPort(r, out_vp)
1128 #  define rwRecMemSetDPort(r, in_vp)  rwrec_MemSetDPort(r, in_vp)
1129 #  define rwRecMemCmpDPort(r, vp)  rwrec_MemCmpDPort(r, vp)
1130 #else
1131 #  define rwRecGetDPort(r)  _recGetDPort(r)
1132 #  define rwRecSetDPort(r, in_v)  _recSetDPort(r, in_v)
1133 #  define rwRecMemGetDPort(r, out_vp)  _recMemGetDPort(r, out_vp)
1134 #  define rwRecMemSetDPort(r, in_vp)  _recMemSetDPort(r, in_vp)
1135 #  define rwRecMemCmpDPort(r, vp)  _recMemCmpDPort(r, vp)
1136 #endif /* RWREC_OPAQUE */
1137 
1138 
1139 /***  Protocol  ***/
1140 
1141 uint8_t  rwrec_GetProto(const rwRec *r);
1142 void     rwrec_SetProto(rwRec *r, uint8_t in_v);
1143 void     rwrec_MemGetProto(const rwRec *r, void *out_vp);
1144 void     rwrec_MemSetProto(rwRec *r, const void *in_vp);
1145 int      rwrec_MemCmpProto(const rwRec *r, const void *vp);
1146 
1147 #define _recGetProto(r)                         \
1148     ((r)->proto)
1149 #define _recSetProto(r, in_v)                   \
1150     { ((r)->proto) = (in_v); }
1151 #define _recMemGetProto(r, out_vp)                      \
1152     memcpy((out_vp), &((r)->proto), RWREC_SIZEOF_PROTO)
1153 #define _recMemSetProto(r, in_vp)                       \
1154     memcpy(&((r)->proto), (in_vp), RWREC_SIZEOF_PROTO)
1155 #define _recMemCmpProto(r, vp)                          \
1156     memcmp(&((r)->proto), (vp), RWREC_SIZEOF_PROTO)
1157 
1158 #if RWREC_OPAQUE
1159 #  define rwRecGetProto(r)  rwrec_GetProto(r)
1160 #  define rwRecSetProto(r, in_v)  rwrec_SetProto(r, in_v)
1161 #  define rwRecMemGetProto(r, out_vp)  rwrec_MemGetProto(r, out_vp)
1162 #  define rwRecMemSetProto(r, in_vp)  rwrec_MemSetProto(r, in_vp)
1163 #  define rwRecMemCmpProto(r, vp)  rwrec_MemCmpProto(r, vp)
1164 #else
1165 #  define rwRecGetProto(r)  _recGetProto(r)
1166 #  define rwRecSetProto(r, in_v)  _recSetProto(r, in_v)
1167 #  define rwRecMemGetProto(r, out_vp)  _recMemGetProto(r, out_vp)
1168 #  define rwRecMemSetProto(r, in_vp)  _recMemSetProto(r, in_vp)
1169 #  define rwRecMemCmpProto(r, vp)  _recMemCmpProto(r, vp)
1170 #endif /* RWREC_OPAQUE */
1171 
1172 
1173 /***  Packet Count (pkts)  ***/
1174 
1175 uint32_t rwrec_GetPkts(const rwRec *r);
1176 void     rwrec_SetPkts(rwRec *r, uint32_t in_v);
1177 void     rwrec_MemGetPkts(const rwRec *r, void *out_vp);
1178 void     rwrec_MemSetPkts(rwRec *r, const void *in_vp);
1179 int      rwrec_MemCmpPkts(const rwRec *r, const void *vp);
1180 
1181 #define _recGetPkts(r)                          \
1182     ((r)->pkts)
1183 #define _recSetPkts(r, in_v)                    \
1184     { ((r)->pkts) = (in_v); }
1185 #define _recMemGetPkts(r, out_vp)                       \
1186     memcpy((out_vp), &((r)->pkts), RWREC_SIZEOF_PKTS)
1187 #define _recMemSetPkts(r, in_vp)                        \
1188     memcpy(&((r)->pkts), (in_vp), RWREC_SIZEOF_PKTS)
1189 #define _recMemCmpPkts(r, vp)                           \
1190     memcmp(&((r)->pkts), (vp), RWREC_SIZEOF_PKTS)
1191 
1192 #if RWREC_OPAQUE
1193 #  define rwRecGetPkts(r)  rwrec_GetPkts(r)
1194 #  define rwRecSetPkts(r, in_v)  rwrec_SetPkts(r, in_v)
1195 #  define rwRecMemGetPkts(r, out_vp)  rwrec_MemGetPkts(r, out_vp)
1196 #  define rwRecMemSetPkts(r, in_vp)  rwrec_MemSetPkts(r, in_vp)
1197 #  define rwRecMemCmpPkts(r, vp)  rwrec_MemCmpPkts(r, vp)
1198 #else
1199 #  define rwRecGetPkts(r)  _recGetPkts(r)
1200 #  define rwRecSetPkts(r, in_v)  _recSetPkts(r, in_v)
1201 #  define rwRecMemGetPkts(r, out_vp)  _recMemGetPkts(r, out_vp)
1202 #  define rwRecMemSetPkts(r, in_vp)  _recMemSetPkts(r, in_vp)
1203 #  define rwRecMemCmpPkts(r, vp)  _recMemCmpPkts(r, vp)
1204 #endif /* RWREC_OPAQUE */
1205 
1206 
1207 /***  Byte count  ***/
1208 
1209 uint32_t rwrec_GetBytes(const rwRec *r);
1210 void     rwrec_SetBytes(rwRec *r, uint32_t in_v);
1211 void     rwrec_MemGetBytes(const rwRec *r, void *out_vp);
1212 void     rwrec_MemSetBytes(rwRec *r, const void *in_vp);
1213 int      rwrec_MemCmpBytes(const rwRec *r, const void *vp);
1214 
1215 #define _recGetBytes(r)                         \
1216     ((r)->bytes)
1217 #define _recSetBytes(r, in_v)                   \
1218     { ((r)->bytes) = (in_v); }
1219 #define _recMemGetBytes(r, out_vp)                      \
1220     memcpy((out_vp), &((r)->bytes), RWREC_SIZEOF_BYTES)
1221 #define _recMemSetBytes(r, in_vp)                       \
1222     memcpy(&((r)->bytes), (in_vp), RWREC_SIZEOF_BYTES)
1223 #define _recMemCmpBytes(r, vp)                          \
1224     memcmp(&((r)->bytes), (vp), RWREC_SIZEOF_BYTES)
1225 
1226 #if RWREC_OPAQUE
1227 #  define rwRecGetBytes(r)  rwrec_GetBytes(r)
1228 #  define rwRecSetBytes(r, in_v)  rwrec_SetBytes(r, in_v)
1229 #  define rwRecMemGetBytes(r, out_vp)  rwrec_MemGetBytes(r, out_vp)
1230 #  define rwRecMemSetBytes(r, in_vp)  rwrec_MemSetBytes(r, in_vp)
1231 #  define rwRecMemCmpBytes(r, vp)  rwrec_MemCmpBytes(r, vp)
1232 #else
1233 #  define rwRecGetBytes(r)  _recGetBytes(r)
1234 #  define rwRecSetBytes(r, in_v)  _recSetBytes(r, in_v)
1235 #  define rwRecMemGetBytes(r, out_vp)  _recMemGetBytes(r, out_vp)
1236 #  define rwRecMemSetBytes(r, in_vp)  _recMemSetBytes(r, in_vp)
1237 #  define rwRecMemCmpBytes(r, vp)  _recMemCmpBytes(r, vp)
1238 #endif /* RWREC_OPAQUE */
1239 
1240 
1241 /***  Bitwise OR of TCP Flags on ALL packets in flow  ***/
1242 
1243 uint8_t  rwrec_GetFlags(const rwRec *r);
1244 void     rwrec_SetFlags(rwRec *r, uint8_t in_v);
1245 void     rwrec_MemGetFlags(const rwRec *r, void *out_vp);
1246 void     rwrec_MemSetFlags(rwRec *r, const void *in_vp);
1247 int      rwrec_MemCmpFlags(const rwRec *r, const void *vp);
1248 
1249 #define _recGetFlags(r)                         \
1250     ((r)->flags)
1251 #define _recSetFlags(r, in_v)                   \
1252     { ((r)->flags) = (in_v); }
1253 #define _recMemGetFlags(r, out_vp)                      \
1254     memcpy((out_vp), &((r)->flags), RWREC_SIZEOF_FLAGS)
1255 #define _recMemSetFlags(r, in_vp)                       \
1256     memcpy(&((r)->flags), (in_vp), RWREC_SIZEOF_FLAGS)
1257 #define _recMemCmpFlags(r, vp)                          \
1258     memcmp(&((r)->flags), (vp), RWREC_SIZEOF_FLAGS)
1259 
1260 #if RWREC_OPAQUE
1261 #  define rwRecGetFlags(r)  rwrec_GetFlags(r)
1262 #  define rwRecSetFlags(r, in_v)  rwrec_SetFlags(r, in_v)
1263 #  define rwRecMemGetFlags(r, out_vp)  rwrec_MemGetFlags(r, out_vp)
1264 #  define rwRecMemSetFlags(r, in_vp)  rwrec_MemSetFlags(r, in_vp)
1265 #  define rwRecMemCmpFlags(r, vp)  rwrec_MemCmpFlags(r, vp)
1266 #else
1267 #  define rwRecGetFlags(r)  _recGetFlags(r)
1268 #  define rwRecSetFlags(r, in_v)  _recSetFlags(r, in_v)
1269 #  define rwRecMemGetFlags(r, out_vp)  _recMemGetFlags(r, out_vp)
1270 #  define rwRecMemSetFlags(r, in_vp)  _recMemSetFlags(r, in_vp)
1271 #  define rwRecMemCmpFlags(r, vp)  _recMemCmpFlags(r, vp)
1272 #endif /* RWREC_OPAQUE */
1273 
1274 
1275 /***  TCP Flags seen on initial packet of flow  ***/
1276 
1277 uint8_t  rwrec_GetInitFlags(const rwRec *r);
1278 void     rwrec_SetInitFlags(rwRec *r, uint8_t in_v);
1279 void     rwrec_MemGetInitFlags(const rwRec *r, void *out_vp);
1280 void     rwrec_MemSetInitFlags(rwRec *r, const void *in_vp);
1281 int      rwrec_MemCmpInitFlags(const rwRec *r, const void *vp);
1282 
1283 #define _recGetInitFlags(r)                     \
1284     ((r)->init_flags)
1285 #define _recSetInitFlags(r, in_v)               \
1286     { ((r)->init_flags) = (in_v); }
1287 #define _recMemGetInitFlags(r, out_vp)                                  \
1288     memcpy((out_vp), &((r)->init_flags), RWREC_SIZEOF_INIT_FLAGS)
1289 #define _recMemSetInitFlags(r, in_vp)                                   \
1290     memcpy(&((r)->init_flags), (in_vp), RWREC_SIZEOF_INIT_FLAGS)
1291 #define _recMemCmpInitFlags(r, vp)                              \
1292     memcmp(&((r)->init_flags), (vp), RWREC_SIZEOF_INIT_FLAGS)
1293 
1294 #if RWREC_OPAQUE
1295 #  define rwRecGetInitFlags(r)  rwrec_GetInitFlags(r)
1296 #  define rwRecSetInitFlags(r, in_v)  rwrec_SetInitFlags(r, in_v)
1297 #  define rwRecMemGetInitFlags(r, out_vp)  rwrec_MemGetInitFlags(r, out_vp)
1298 #  define rwRecMemSetInitFlags(r, in_vp)  rwrec_MemSetInitFlags(r, in_vp)
1299 #  define rwRecMemCmpInitFlags(r, vp)  rwrec_MemCmpInitFlags(r, vp)
1300 #else
1301 #  define rwRecGetInitFlags(r)  _recGetInitFlags(r)
1302 #  define rwRecSetInitFlags(r, in_v)  _recSetInitFlags(r, in_v)
1303 #  define rwRecMemGetInitFlags(r, out_vp)  _recMemGetInitFlags(r, out_vp)
1304 #  define rwRecMemSetInitFlags(r, in_vp)  _recMemSetInitFlags(r, in_vp)
1305 #  define rwRecMemCmpInitFlags(r, vp)  _recMemCmpInitFlags(r, vp)
1306 #endif /* RWREC_OPAQUE */
1307 
1308 
1309 /***  Bitwise OR of TCP Flags on all packets in session except first  ***/
1310 
1311 uint8_t  rwrec_GetRestFlags(const rwRec *r);
1312 void     rwrec_SetRestFlags(rwRec *r, uint8_t in_v);
1313 void     rwrec_MemGetRestFlags(const rwRec *r, void *out_vp);
1314 void     rwrec_MemSetRestFlags(rwRec *r, const void *in_vp);
1315 int      rwrec_MemCmpRestFlags(const rwRec *r, const void *vp);
1316 
1317 #define _recGetRestFlags(r)                     \
1318     ((r)->rest_flags)
1319 #define _recSetRestFlags(r, in_v)               \
1320     { ((r)->rest_flags) = (in_v); }
1321 #define _recMemGetRestFlags(r, out_vp)                                  \
1322     memcpy((out_vp), &((r)->rest_flags), RWREC_SIZEOF_REST_FLAGS)
1323 #define _recMemSetRestFlags(r, in_vp)                                   \
1324     memcpy(&((r)->rest_flags), (in_vp), RWREC_SIZEOF_REST_FLAGS)
1325 #define _recMemCmpRestFlags(r, vp)                              \
1326     memcmp(&((r)->rest_flags), (vp), RWREC_SIZEOF_REST_FLAGS)
1327 
1328 #if RWREC_OPAQUE
1329 #  define rwRecGetRestFlags(r)  rwrec_GetRestFlags(r)
1330 #  define rwRecSetRestFlags(r, in_v)  rwrec_SetRestFlags(r, in_v)
1331 #  define rwRecMemGetRestFlags(r, out_vp)  rwrec_MemGetRestFlags(r, out_vp)
1332 #  define rwRecMemSetRestFlags(r, in_vp)  rwrec_MemSetRestFlags(r, in_vp)
1333 #  define rwRecMemCmpRestFlags(r, vp)  rwrec_MemCmpRestFlags(r, vp)
1334 #else
1335 #  define rwRecGetRestFlags(r)  _recGetRestFlags(r)
1336 #  define rwRecSetRestFlags(r, in_v)  _recSetRestFlags(r, in_v)
1337 #  define rwRecMemGetRestFlags(r, out_vp)  _recMemGetRestFlags(r, out_vp)
1338 #  define rwRecMemSetRestFlags(r, in_vp)  _recMemSetRestFlags(r, in_vp)
1339 #  define rwRecMemCmpRestFlags(r, vp)  _recMemCmpRestFlags(r, vp)
1340 #endif /* RWREC_OPAQUE */
1341 
1342 
1343 /***  Start Time as milliseconds since UNIX epoch (sTime)  ***/
1344 
1345 sktime_t rwrec_GetStartTime(const rwRec *r);
1346 void     rwrec_SetStartTime(rwRec *r, sktime_t in_v);
1347 void     rwrec_MemGetStartTime(const rwRec *r, void *out_vp);
1348 void     rwrec_MemSetStartTime(rwRec *r, const void *in_vp);
1349 int      rwrec_MemCmpStartTime(const rwRec *r, const void *vp);
1350 uint32_t rwrec_GetStartSeconds(const rwRec *r);
1351 void     rwrec_MemGetStartSeconds(const rwRec *r, void *out_vp);
1352 
1353 #define _recGetStartTime(r)                     \
1354     ((r)->sTime)
1355 #define _recSetStartTime(r, in_v)               \
1356     { ((r)->sTime = (in_v)); }
1357 #define _recMemGetStartTime(r, out_vp)                  \
1358     memcpy((out_vp), &((r)->sTime), RWREC_SIZEOF_STIME)
1359 #define _recMemSetStartTime(r, in_vp)                   \
1360     memcpy(&((r)->sTime), (in_vp), RWREC_SIZEOF_STIME)
1361 #define _recMemCmpStartTime(r, vp)                      \
1362     memcmp(&((r)->sTime), (vp), RWREC_SIZEOF_STIME)
1363 
1364 #define _recGetStartSeconds(r)                  \
1365     ((uint32_t)((r)->sTime / 1000))
1366 #define _recMemGetStartSeconds(r, out_vp) {     \
1367         uint32_t _t = _recGetStartSeconds(r);   \
1368         memcpy((out_vp), &_t, sizeof(_t));      \
1369     }
1370 
1371 #if RWREC_OPAQUE
1372 #  define rwRecGetStartTime(r)  rwrec_GetStartTime(r)
1373 #  define rwRecSetStartTime(r, in_v)  rwrec_SetStartTime(r, in_v)
1374 #  define rwRecMemGetStartTime(r, out_vp)  rwrec_MemGetStartTime(r, out_vp)
1375 #  define rwRecMemSetStartTime(r, in_vp)  rwrec_MemSetStartTime(r, in_vp)
1376 #  define rwRecMemCmpStartTime(r, vp)  rwrec_MemCmpStartTime(r, vp)
1377 #  define rwRecGetStartSeconds(r)  rwrec_GetStartSeconds(r)
1378 #  define rwRecMemGetStartSeconds(r, out_vp)    \
1379     rwrec_MemGetStartSeconds(r, out_vp)
1380 #else
1381 #  define rwRecGetStartTime(r)  _recGetStartTime(r)
1382 #  define rwRecSetStartTime(r, in_v)  _recSetStartTime(r, in_v)
1383 #  define rwRecMemGetStartTime(r, out_vp)  _recMemGetStartTime(r, out_vp)
1384 #  define rwRecMemSetStartTime(r, in_vp)  _recMemSetStartTime(r, in_vp)
1385 #  define rwRecMemCmpStartTime(r, vp)  _recMemCmpStartTime(r, vp)
1386 #  define rwRecGetStartSeconds(r)  _recGetStartSeconds(r)
1387 #  define rwRecMemGetStartSeconds(r, out_vp)  _recMemGetStartSeconds(r, out_vp)
1388 #endif /* RWREC_OPAQUE */
1389 
1390 
1391 /***  Elapsed (duration) of the flow, in milliseconds  ***/
1392 
1393 uint32_t rwrec_GetElapsed(const rwRec *r);
1394 void     rwrec_SetElapsed(rwRec *r, sktime_t in_v);
1395 void     rwrec_MemGetElapsed(const rwRec *r, void *out_vp);
1396 void     rwrec_MemSetElapsed(rwRec *r, const void *in_vp);
1397 int      rwrec_MemCmpElapsed(const rwRec *r, const void *vp);
1398 uint32_t rwrec_GetElapsedSeconds(const rwRec *r);
1399 void     rwrec_MemGetElapsedSeconds(const rwRec *r, void *out_vp);
1400 
1401 #define _recGetElapsed(r)                       \
1402     ((r)->elapsed)
1403 #define _recSetElapsed(r, in_v)                 \
1404     { (r)->elapsed = (uint32_t)(in_v); }
1405 #define _recMemGetElapsed(r, out_vp)                            \
1406     memcpy((out_vp), &((r)->elapsed), RWREC_SIZEOF_ELAPSED)
1407 #define _recMemSetElapsed(r, in_vp)                             \
1408     memcpy(&((r)->elapsed), (in_vp), RWREC_SIZEOF_ELAPSED)
1409 #define _recMemCmpElapsed(r, vp)                                \
1410     memcmp(&((r)->elapsed), (vp), RWREC_SIZEOF_ELAPSED)
1411 
1412 #define _recGetElapsedSeconds(r)                \
1413     ((uint32_t)((r)->elapsed / 1000))
1414 #define _recMemGetElapsedSeconds(r, out_vp) {   \
1415         uint32_t _t = _recGetElapsedSeconds(r); \
1416         memcpy((out_vp), &_t, sizeof(_t));      \
1417     }
1418 
1419 #if RWREC_OPAQUE
1420 #  define rwRecGetElapsed(r)  rwrec_GetElapsed(r)
1421 #  define rwRecSetElapsed(r, in_v)  rwrec_SetElapsed(r, in_v)
1422 #  define rwRecMemGetElapsed(r, out_vp)  rwrec_MemGetElapsed(r, out_vp)
1423 #  define rwRecMemSetElapsed(r, in_vp)  rwrec_MemSetElapsed(r, in_vp)
1424 #  define rwRecMemCmpElapsed(r, vp)  rwrec_MemCmpElapsed(r, vp)
1425 #  define rwRecGetElapsedSeconds(r)  rwrec_GetElapsedSeconds(r)
1426 #  define rwRecMemGetElapsedSeconds(r, out_vp)  \
1427     rwrec_MemGetElapsedSeconds(r, out_vp)
1428 #else
1429 #  define rwRecGetElapsed(r)  _recGetElapsed(r)
1430 #  define rwRecSetElapsed(r, in_v)  _recSetElapsed(r, in_v)
1431 #  define rwRecMemGetElapsed(r, out_vp)  _recMemGetElapsed(r, out_vp)
1432 #  define rwRecMemSetElapsed(r, in_vp)  _recMemSetElapsed(r, in_vp)
1433 #  define rwRecMemCmpElapsed(r, vp)  _recMemCmpElapsed(r, vp)
1434 #  define rwRecGetElapsedSeconds(r)  _recGetElapsedSeconds(r)
1435 #  define rwRecMemGetElapsedSeconds(r, out_vp)  \
1436     _recMemGetElapsedSeconds(r, out_vp)
1437 #endif /* RWREC_OPAQUE */
1438 
1439 
1440 
1441 /***  End Time is derived from the sTime and duration (eTime)  ***/
1442 
1443 /* No Set macros/functions since this is a derived field */
1444 
1445 sktime_t rwrec_GetEndTime(const rwRec *r);
1446 void     rwrec_MemGetEndTime(const rwRec *r, void *out_vp);
1447 uint32_t rwrec_GetEndSeconds(const rwRec *r);
1448 void     rwrec_MemGetEndSeconds(const rwRec *r, void *out_vp);
1449 
1450 #define _recGetEndTime(r)                               \
1451     ((sktime_t)_recGetStartTime(r) + _recGetElapsed(r))
1452 #define _recMemGetEndTime(r, out_vp) {          \
1453         sktime_t _t = _recGetEndTime(r);        \
1454         memcpy((out_vp), &_t, sizeof(_t));      \
1455     }
1456 #define _recGetEndSeconds(r)                    \
1457     ((uint32_t)(_recGetEndTime(r) / 1000))
1458 #define _recMemGetEndSeconds(r, out_vp) {       \
1459         uint32_t _t = rwRecGetEndSeconds(r);    \
1460         memcpy((out_vp), &_t, sizeof(_t));      \
1461     }
1462 
1463 #if RWREC_OPAQUE
1464 #  define rwRecGetEndTime(r)  rwrec_GetEndTime(r)
1465 #  define rwRecMemGetEndTime(r, out_vp)  rwrec_MemGetEndTime(r, out_vp)
1466 #  define rwRecGetEndSeconds(r)  rwrec_GetEndSeconds(r)
1467 #  define rwRecMemGetEndSeconds(r, out_vp)  rwrec_MemGetEndSeconds(r, out_vp)
1468 #else
1469 #  define rwRecGetEndTime(r)  _recGetEndTime(r)
1470 #  define rwRecMemGetEndTime(r, out_vp)  _recMemGetEndTime(r, out_vp)
1471 #  define rwRecGetEndSeconds(r)  _recGetEndSeconds(r)
1472 #  define rwRecMemGetEndSeconds(r, out_vp)  _recMemGetEndSeconds(r, out_vp)
1473 #endif /* RWREC_OPAQUE */
1474 
1475 
1476 /***  Sensor ID (sID)  ***/
1477 
1478 sk_sensor_id_t  rwrec_GetSensor(const rwRec *r);
1479 void            rwrec_SetSensor(rwRec *r, sk_sensor_id_t in_v);
1480 void            rwrec_MemGetSensor(const rwRec *r, void *out_vp);
1481 void            rwrec_MemSetSensor(rwRec *r, const void *in_vp);
1482 int             rwrec_MemCmpSensor(const rwRec *r, const void *vp);
1483 
1484 #define _recGetSensor(r)                        \
1485     ((r)->sID)
1486 #define _recSetSensor(r, in_v)                  \
1487     { ((r)->sID) = (in_v); }
1488 #define _recMemGetSensor(r, out_vp)                     \
1489     memcpy((out_vp), &((r)->sID), RWREC_SIZEOF_SID)
1490 #define _recMemSetSensor(r, in_vp)                      \
1491     memcpy(&((r)->sID), (in_vp), RWREC_SIZEOF_SID)
1492 #define _recMemCmpSensor(r, vp)                 \
1493     memcmp(&((r)->sID), (vp), RWREC_SIZEOF_SID)
1494 
1495 #if RWREC_OPAQUE
1496 #  define rwRecGetSensor(r)  rwrec_GetSensor(r)
1497 #  define rwRecSetSensor(r, in_v)  rwrec_SetSensor(r, in_v)
1498 #  define rwRecMemGetSensor(r, out_vp)  rwrec_MemGetSensor(r, out_vp)
1499 #  define rwRecMemSetSensor(r, in_vp)  rwrec_MemSetSensor(r, in_vp)
1500 #  define rwRecMemCmpSensor(r, vp)  rwrec_MemCmpSensor(r, vp)
1501 #else
1502 #  define rwRecGetSensor(r)  _recGetSensor(r)
1503 #  define rwRecSetSensor(r, in_v)  _recSetSensor(r, in_v)
1504 #  define rwRecMemGetSensor(r, out_vp)  _recMemGetSensor(r, out_vp)
1505 #  define rwRecMemSetSensor(r, in_vp)  _recMemSetSensor(r, in_vp)
1506 #  define rwRecMemCmpSensor(r, vp)  _recMemCmpSensor(r, vp)
1507 #endif /* RWREC_OPAQUE */
1508 
1509 
1510 /***  FlowType holds Class and Type  ***/
1511 
1512 sk_flowtype_id_t    rwrec_GetFlowType(const rwRec *r);
1513 void                rwrec_SetFlowType(rwRec *r, sk_flowtype_id_t in_v);
1514 void                rwrec_MemGetFlowType(const rwRec *r, void *out_vp);
1515 void                rwrec_MemSetFlowType(rwRec *r, const void *in_vp);
1516 int                 rwrec_MemCmpFlowType(const rwRec *r, const void *vp);
1517 
1518 #define _recGetFlowType(r)                      \
1519     ((r)->flow_type)
1520 #define _recSetFlowType(r, in_v)                \
1521     { ((r)->flow_type) = (in_v); }
1522 #define _recMemGetFlowType(r, out_vp)                           \
1523     memcpy((out_vp), &((r)->flow_type), RWREC_SIZEOF_FLOW_TYPE)
1524 #define _recMemSetFlowType(r, in_vp)                            \
1525     memcpy(&((r)->flow_type), (in_vp), RWREC_SIZEOF_FLOW_TYPE)
1526 #define _recMemCmpFlowType(r, vp)                               \
1527     memcmp(&((r)->flow_type), (vp), RWREC_SIZEOF_FLOW_TYPE)
1528 
1529 #if RWREC_OPAQUE
1530 #  define rwRecGetFlowType(r)  rwrec_GetFlowType(r)
1531 #  define rwRecSetFlowType(r, in_v)  rwrec_SetFlowType(r, in_v)
1532 #  define rwRecMemGetFlowType(r, out_vp)  rwrec_MemGetFlowType(r, out_vp)
1533 #  define rwRecMemSetFlowType(r, in_vp)  rwrec_MemSetFlowType(r, in_vp)
1534 #  define rwRecMemCmpFlowType(r, vp)  rwrec_MemCmpFlowType(r, vp)
1535 #else
1536 #  define rwRecGetFlowType(r)  _recGetFlowType(r)
1537 #  define rwRecSetFlowType(r, in_v)  _recSetFlowType(r, in_v)
1538 #  define rwRecMemGetFlowType(r, out_vp)  _recMemGetFlowType(r, out_vp)
1539 #  define rwRecMemSetFlowType(r, in_vp)  _recMemSetFlowType(r, in_vp)
1540 #  define rwRecMemCmpFlowType(r, vp)  _recMemCmpFlowType(r, vp)
1541 #endif /* RWREC_OPAQUE */
1542 
1543 
1544 /***  SNMP Input Value (Router incoming/ingress interface)  ***/
1545 
1546 uint16_t rwrec_GetInput(const rwRec *r);
1547 void     rwrec_SetInput(rwRec *r, uint16_t in_v);
1548 void     rwrec_MemGetInput(const rwRec *r, void *out_vp);
1549 void     rwrec_MemSetInput(rwRec *r, const void *in_vp);
1550 int      rwrec_MemCmpInput(const rwRec *r, const void *vp);
1551 
1552 #define _recGetInput(r)                         \
1553     ((r)->input)
1554 #define _recSetInput(r, in_v)                   \
1555     { ((r)->input) = (in_v); }
1556 #define _recMemGetInput(r, out_vp)                      \
1557     memcpy((out_vp), &((r)->input), RWREC_SIZEOF_INPUT)
1558 #define _recMemSetInput(r, in_vp)                       \
1559     memcpy(&((r)->input), (in_vp), RWREC_SIZEOF_INPUT)
1560 #define _recMemCmpInput(r, vp)                          \
1561     memcmp(&((r)->input), (vp), RWREC_SIZEOF_INPUT)
1562 
1563 #if RWREC_OPAQUE
1564 #  define rwRecGetInput(r)  rwrec_GetInput(r)
1565 #  define rwRecSetInput(r, in_v)  rwrec_SetInput(r, in_v)
1566 #  define rwRecMemGetInput(r, out_vp)  rwrec_MemGetInput(r, out_vp)
1567 #  define rwRecMemSetInput(r, in_vp)  rwrec_MemSetInput(r, in_vp)
1568 #  define rwRecMemCmpInput(r, vp)  rwrec_MemCmpInput(r, vp)
1569 #else
1570 #  define rwRecGetInput(r)  _recGetInput(r)
1571 #  define rwRecSetInput(r, in_v)  _recSetInput(r, in_v)
1572 #  define rwRecMemGetInput(r, out_vp)  _recMemGetInput(r, out_vp)
1573 #  define rwRecMemSetInput(r, in_vp)  _recMemSetInput(r, in_vp)
1574 #  define rwRecMemCmpInput(r, vp)  _recMemCmpInput(r, vp)
1575 #endif /* RWREC_OPAQUE */
1576 
1577 
1578 /***  SNMP Output Value  (Router outgoing/egress interface)  ***/
1579 
1580 uint16_t rwrec_GetOutput(const rwRec *r);
1581 void     rwrec_SetOutput(rwRec *r, uint16_t in_v);
1582 void     rwrec_MemGetOutput(const rwRec *r, void *out_vp);
1583 void     rwrec_MemSetOutput(rwRec *r, const void *in_vp);
1584 int      rwrec_MemCmpOutput(const rwRec *r, const void *vp);
1585 
1586 #define _recGetOutput(r)                        \
1587     ((r)->output)
1588 #define _recSetOutput(r, in_v)                  \
1589     { ((r)->output) = (in_v); }
1590 #define _recMemGetOutput(r, out_vp)                             \
1591     memcpy((out_vp), &((r)->output), RWREC_SIZEOF_OUTPUT)
1592 #define _recMemSetOutput(r, in_vp)                              \
1593     memcpy(&((r)->output), (in_vp), RWREC_SIZEOF_OUTPUT)
1594 #define _recMemCmpOutput(r, vp)                         \
1595     memcmp(&((r)->output), (vp), RWREC_SIZEOF_OUTPUT)
1596 
1597 #if RWREC_OPAQUE
1598 #  define rwRecGetOutput(r)  rwrec_GetOutput(r)
1599 #  define rwRecSetOutput(r, in_v)  rwrec_SetOutput(r, in_v)
1600 #  define rwRecMemGetOutput(r, out_vp)  rwrec_MemGetOutput(r, out_vp)
1601 #  define rwRecMemSetOutput(r, in_vp)  rwrec_MemSetOutput(r, in_vp)
1602 #  define rwRecMemCmpOutput(r, vp)  rwrec_MemCmpOutput(r, vp)
1603 #else
1604 #  define rwRecGetOutput(r)  _recGetOutput(r)
1605 #  define rwRecSetOutput(r, in_v)  _recSetOutput(r, in_v)
1606 #  define rwRecMemGetOutput(r, out_vp)  _recMemGetOutput(r, out_vp)
1607 #  define rwRecMemSetOutput(r, in_vp)  _recMemSetOutput(r, in_vp)
1608 #  define rwRecMemCmpOutput(r, vp)  _recMemCmpOutput(r, vp)
1609 #endif /* RWREC_OPAQUE */
1610 
1611 
1612 /***  TCP State  ***/
1613 
1614 uint8_t  rwrec_GetTcpState(const rwRec *r);
1615 void     rwrec_SetTcpState(rwRec *r, uint8_t in_v);
1616 void     rwrec_MemGetTcpState(const rwRec *r, void *out_vp);
1617 void     rwrec_MemSetTcpState(rwRec *r, const void *in_vp);
1618 int      rwrec_MemCmpTcpState(const rwRec *r, const void *vp);
1619 
1620 #define _recGetTcpState(r)                              \
1621     ((uint8_t)((r)->tcp_state & SK_TCPSTATE_MASK))
1622 #define _recSetTcpState(r, in_v)                                       \
1623     { ((r)->tcp_state)                                                 \
1624             = ((r)->tcp_state & 0x80) | (SK_TCPSTATE_MASK & (in_v)); }
1625 #define _recMemGetTcpState(r, out_vp)                   \
1626     { *((uint8_t*)(out_vp)) = _recGetTcpState(r); }
1627 #define _recMemSetTcpState(r, in_vp)            \
1628     _recSetTcpState((r), *((uint8_t*)(in_vp)))
1629 #define _recMemCmpTcpState(r, vp)                               \
1630     ((int)(_recGetTcpState(r)                                   \
1631            - (uint8_t)(SK_TCPSTATE_MASK & *((uint8_t*)(vp)))))
1632 
1633 #if RWREC_OPAQUE
1634 #  define rwRecGetTcpState(r)  rwrec_GetTcpState(r)
1635 #  define rwRecSetTcpState(r, in_v)  rwrec_SetTcpState(r, in_v)
1636 #  define rwRecMemGetTcpState(r, out_vp)  rwrec_MemGetTcpState(r, out_vp)
1637 #  define rwRecMemSetTcpState(r, in_vp)  rwrec_MemSetTcpState(r, in_vp)
1638 #  define rwRecMemCmpTcpState(r, vp)  rwrec_MemCmpTcpState(r, vp)
1639 #else
1640 #  define rwRecGetTcpState(r)  _recGetTcpState(r)
1641 #  define rwRecSetTcpState(r, in_v)  _recSetTcpState(r, in_v)
1642 #  define rwRecMemGetTcpState(r, out_vp)  _recMemGetTcpState(r, out_vp)
1643 #  define rwRecMemSetTcpState(r, in_vp)  _recMemSetTcpState(r, in_vp)
1644 #  define rwRecMemCmpTcpState(r, vp)  _recMemCmpTcpState(r, vp)
1645 #endif /* RWREC_OPAQUE */
1646 
1647 
1648 /***  Application  ***/
1649 
1650 uint16_t rwrec_GetApplication(const rwRec *r);
1651 void     rwrec_SetApplication(rwRec *r, uint16_t in_v);
1652 void     rwrec_MemGetApplication(const rwRec *r, void *out_vp);
1653 void     rwrec_MemSetApplication(rwRec *r, const void *in_vp);
1654 int      rwrec_MemCmpApplication(const rwRec *r, const void *vp);
1655 
1656 #define _recGetApplication(r)                   \
1657     ((r)->application)
1658 #define _recSetApplication(r, in_v)             \
1659     { ((r)->application) = (in_v); }
1660 #define _recMemGetApplication(r, out_vp)                                \
1661     memcpy((out_vp), &((r)->application), RWREC_SIZEOF_APPLICATION)
1662 #define _recMemSetApplication(r, in_vp)                                 \
1663     memcpy(&((r)->application), (in_vp), RWREC_SIZEOF_APPLICATION)
1664 #define _recMemCmpApplication(r, vp)                            \
1665     memcmp(&((r)->application), (vp), RWREC_SIZEOF_APPLICATION)
1666 
1667 #if RWREC_OPAQUE
1668 #  define rwRecGetApplication(r)  rwrec_GetApplication(r)
1669 #  define rwRecSetApplication(r, in_v)  rwrec_SetApplication(r, in_v)
1670 #  define rwRecMemGetApplication(r, out_vp)  rwrec_MemGetApplication(r, out_vp)
1671 #  define rwRecMemSetApplication(r, in_vp)  rwrec_MemSetApplication(r, in_vp)
1672 #  define rwRecMemCmpApplication(r, vp)  rwrec_MemCmpApplication(r, vp)
1673 #else
1674 #  define rwRecGetApplication(r)  _recGetApplication(r)
1675 #  define rwRecSetApplication(r, in_v)  _recSetApplication(r, in_v)
1676 #  define rwRecMemGetApplication(r, out_vp)  _recMemGetApplication(r, out_vp)
1677 #  define rwRecMemSetApplication(r, in_vp)  _recMemSetApplication(r, in_vp)
1678 #  define rwRecMemCmpApplication(r, vp)  _recMemCmpApplication(r, vp)
1679 #endif /* RWREC_OPAQUE */
1680 
1681 
1682 /***  Memo  ***/
1683 
1684 uint16_t rwrec_GetMemo(const rwRec *r);
1685 void     rwrec_SetMemo(rwRec *r, uint16_t in_v);
1686 void     rwrec_MemGetMemo(const rwRec *r, void *out_vp);
1687 void     rwrec_MemSetMemo(rwRec *r, const void *in_vp);
1688 int      rwrec_MemCmpMemo(const rwRec *r, const void *vp);
1689 
1690 #define _recGetMemo(r)                          \
1691     ((r)->memo)
1692 #define _recSetMemo(r, in_v)                    \
1693     { ((r)->memo) = (in_v); }
1694 #define _recMemGetMemo(r, out_vp)                       \
1695     memcpy((out_vp), &((r)->memo), RWREC_SIZEOF_MEMO)
1696 #define _recMemSetMemo(r, in_vp)                        \
1697     memcpy(&((r)->memo), (in_vp), RWREC_SIZEOF_MEMO)
1698 #define _recMemCmpMemo(r, vp)                           \
1699     memcmp(&((r)->memo), (vp), RWREC_SIZEOF_MEMO)
1700 
1701 #if RWREC_OPAQUE
1702 #  define rwRecGetMemo(r)  rwrec_GetMemo(r)
1703 #  define rwRecSetMemo(r, in_v)  rwrec_SetMemo(r, in_v)
1704 #  define rwRecMemGetMemo(r, out_vp)  rwrec_MemGetMemo(r, out_vp)
1705 #  define rwRecMemSetMemo(r, in_vp)  rwrec_MemSetMemo(r, in_vp)
1706 #  define rwRecMemCmpMemo(r, vp)  rwrec_MemCmpMemo(r, vp)
1707 #else
1708 #  define rwRecGetMemo(r)  _recGetMemo(r)
1709 #  define rwRecSetMemo(r, in_v)  _recSetMemo(r, in_v)
1710 #  define rwRecMemGetMemo(r, out_vp)  _recMemGetMemo(r, out_vp)
1711 #  define rwRecMemSetMemo(r, in_vp)  _recMemSetMemo(r, in_vp)
1712 #  define rwRecMemCmpMemo(r, vp)  _recMemCmpMemo(r, vp)
1713 #endif /* RWREC_OPAQUE */
1714 
1715 
1716 /***  ICMP Type and Code is derived from the DPort  ***/
1717 
1718 /*
1719  *    In NetFlow, Cisco has traditionally encoded the ICMP type and
1720  *    code in the destination port field as (type << 8 | code).
1721  *    The following macros assume this Cisco-encoding.
1722  *
1723  *    Due to various issues, sometimes the ICMP type and code is
1724  *    encoded in the source port instead of the destination port.  As
1725  *    of SiLK-3.4.0, libsilk (skstream.c) handles these incorrect
1726  *    encodings when the record is read and modifies the record to use
1727  *    the traditional Cisco encoding.
1728  *
1729  *    The following functions/macros do not check the protocol.
1730  */
1731 uint8_t  rwrec_GetIcmpType(const rwRec *r);
1732 void     rwrec_SetIcmpType(rwRec *r, uint8_t in_v);
1733 void     rwrec_MemGetIcmpType(const rwRec *r, void *out_vp);
1734 uint8_t  rwrec_GetIcmpCode(const rwRec *r);
1735 void     rwrec_SetIcmpCode(rwRec *r, uint8_t in_v);
1736 void     rwrec_MemGetIcmpCode(const rwRec *r, void *out_vp);
1737 
1738 uint16_t rwrec_GetIcmpTypeAndCode(const rwRec *r);
1739 void     rwrec_SetIcmpTypeAndCode(rwRec *r, uint16_t in_v);
1740 void     rwrec_MemGetIcmpTypeAndCode(const rwRec *r, void *out_vp);
1741 void     rwrec_MemSetIcmpTypeAndCode(rwRec *r, const void *in_vp);
1742 int      rwrec_MemCmpIcmpTypeAndCode(const rwRec *r, const void *vp);
1743 
1744 #define _recGetIcmpTypeAndCode(r)  _recGetDPort(r)
1745 #define _recSetIcmpTypeAndCode(r, in_v)  _recSetDPort(r, in_v)
1746 #define _recMemGetIcmpTypeAndCode(r, out_vp)  _recMemGetDPort(r, out_vp)
1747 #define _recMemSetIcmpTypeAndCode(r, in_vp)  _recMemSetDPort(r, in_vp)
1748 #define _recMemCmpIcmpTypeAndCode(r, vp)  _recMemCmpDPort(r, vp)
1749 
1750 #define _recGetIcmpType(r)                                      \
1751     ((uint8_t)(0xFF & (_recGetIcmpTypeAndCode(r) >> 8)))
1752 #define _recSetIcmpType(r, in_v)                                        \
1753     _recSetIcmpTypeAndCode(r, ((_recGetIcmpTypeAndCode(r) & 0x00FF)     \
1754                                | (((in_v) & 0xFF) << 8)))
1755 #define _recMemGetIcmpType(r, out_vp)           \
1756     { *out_vp = _recGetIcmpType(r); }
1757 
1758 #define _recGetIcmpCode(r)                              \
1759     ((uint8_t)(0xFF & _recGetIcmpTypeAndCode(r)))
1760 #define _recSetIcmpCode(r, in_v)                                        \
1761     _recSetIcmpTypeAndCode(r, ((_recGetIcmpTypeAndCode(r) & 0xFF00)     \
1762                                | ((in_v) & 0xFF)))
1763 #define _recMemGetIcmpCode(r, out_vp)           \
1764     { *out_vp = _recGetIcmpCode(r); }
1765 
1766 #if RWREC_OPAQUE
1767 #  define rwRecGetIcmpType(r)  rwrec_GetIcmpType(r)
1768 #  define rwRecSetIcmpType(r, in_v)  rwrec_SetIcmpType(r, in_v)
1769 #  define rwRecMemGetIcmpType(r, out_vp)  rwrec_MemGetIcmpType(r, out_vp)
1770 
1771 #  define rwRecGetIcmpCode(r)  rwrec_GetIcmpCode(r)
1772 #  define rwRecSetIcmpCode(r, in_v)  rwrec_SetIcmpCode(r, in_v)
1773 #  define rwRecMemGetIcmpCode(r, out_vp)  rwrec_MemGetIcmpCode(r, out_vp)
1774 
1775 #  define rwRecGetIcmpTypeAndCode(r)  rwrec_GetIcmpTypeAndCode(r)
1776 #  define rwRecSetIcmpTypeAndCode(r, in_v)  rwrec_SetIcmpTypeAndCode(r, in_v)
1777 #  define rwRecMemGetIcmpTypeAndCode(r, out_vp) \
1778     rwrec_MemGetIcmpTypeAndCode(r, out_vp)
1779 #  define rwRecMemSetIcmpTypeAndCode(r, in_vp)  \
1780     rwrec_MemSetIcmpTypeAndCode(r, in_vp)
1781 #  define rwRecMemCmpIcmpTypeAndCode(r, vp)     \
1782     rwrec_MemCmpIcmpTypeAndCode(r, vp)
1783 #else /* RWREC_OPAQUE */
1784 #  define rwRecGetIcmpType(r)  _recGetIcmpType(r)
1785 #  define rwRecSetIcmpType(r, in_v)  _recSetIcmpType(r, in_v)
1786 #  define rwRecMemGetIcmpType(r, out_vp)  _recMemGetIcmpType(r, out_vp)
1787 
1788 #  define rwRecGetIcmpCode(r)  _recGetIcmpCode(r)
1789 #  define rwRecSetIcmpCode(r, in_v)  _recSetIcmpCode(r, in_v)
1790 #  define rwRecMemGetIcmpCode(r, out_vp)  _recMemGetIcmpCode(r, out_vp)
1791 
1792 #  define rwRecGetIcmpTypeAndCode(r)  _recGetIcmpTypeAndCode(r)
1793 #  define rwRecSetIcmpTypeAndCode(r, in_v)  _recSetIcmpTypeAndCode(r, in_v)
1794 #  define rwRecMemGetIcmpTypeAndCode(r, out_vp) \
1795     _recMemGetIcmpTypeAndCode(r, out_vp)
1796 #  define rwRecMemSetIcmpTypeAndCode(r, in_vp)  \
1797     _recMemSetIcmpTypeAndCode(r, in_vp)
1798 #  define rwRecMemCmpIcmpTypeAndCode(r, vp)     \
1799     _recMemCmpIcmpTypeAndCode(r, vp)
1800 #endif /* RWREC_OPAQUE */
1801 
1802 
1803 #ifdef __cplusplus
1804 }
1805 #endif
1806 #endif /* _RWREC_H */
1807 
1808 /*
1809 ** Local Variables:
1810 ** mode:c
1811 ** indent-tabs-mode:nil
1812 ** c-basic-offset:4
1813 ** End:
1814 */
1815