1 /*- 2 * Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org> 3 * Copyright (c) 2001-2003 Roman V. Palagin <romanp@unshadow.net> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $SourceForge: ng_netflow.h,v 1.26 2004/09/04 15:44:55 glebius Exp $ 28 * $FreeBSD$ 29 */ 30 31 #ifndef _NG_NETFLOW_H_ 32 #define _NG_NETFLOW_H_ 33 34 #define NG_NETFLOW_NODE_TYPE "netflow" 35 #define NGM_NETFLOW_COOKIE 1137078102 36 37 #define NG_NETFLOW_MAXIFACES USHRT_MAX 38 39 /* Hook names */ 40 41 #define NG_NETFLOW_HOOK_DATA "iface" 42 #define NG_NETFLOW_HOOK_OUT "out" 43 #define NG_NETFLOW_HOOK_EXPORT "export" 44 45 /* Netgraph commands understood by netflow node */ 46 enum { 47 NGM_NETFLOW_INFO = 1|NGM_READONLY|NGM_HASREPLY, /* get node info */ 48 NGM_NETFLOW_IFINFO = 2|NGM_READONLY|NGM_HASREPLY, /* get iface info */ 49 NGM_NETFLOW_SHOW = 3|NGM_READONLY|NGM_HASREPLY, /* show ip cache flow */ 50 NGM_NETFLOW_SETDLT = 4, /* set data-link type */ 51 NGM_NETFLOW_SETIFINDEX = 5, /* set interface index */ 52 NGM_NETFLOW_SETTIMEOUTS = 6, /* set active/inactive flow timeouts */ 53 NGM_NETFLOW_SETCONFIG = 7, /* set flow generation options */ 54 }; 55 56 /* This structure is returned by the NGM_NETFLOW_INFO message */ 57 struct ng_netflow_info { 58 uint64_t nfinfo_bytes; /* accounted bytes */ 59 uint32_t nfinfo_packets; /* accounted packets */ 60 uint32_t nfinfo_used; /* used cache records */ 61 uint32_t nfinfo_alloc_failed; /* failed allocations */ 62 uint32_t nfinfo_export_failed; /* failed exports */ 63 uint32_t nfinfo_act_exp; /* active expiries */ 64 uint32_t nfinfo_inact_exp; /* inactive expiries */ 65 uint32_t nfinfo_inact_t; /* flow inactive timeout */ 66 uint32_t nfinfo_act_t; /* flow active timeout */ 67 }; 68 69 /* This structure is returned by the NGM_NETFLOW_IFINFO message */ 70 struct ng_netflow_ifinfo { 71 uint32_t ifinfo_packets; /* number of packets for this iface */ 72 uint8_t ifinfo_dlt; /* Data Link Type, DLT_XXX */ 73 #define MAXDLTNAMELEN 20 74 u_int16_t ifinfo_index; /* connected iface index */ 75 uint32_t conf; 76 }; 77 78 79 /* This structure is passed to NGM_NETFLOW_SETDLT message */ 80 struct ng_netflow_setdlt { 81 uint16_t iface; /* which iface dlt change */ 82 uint8_t dlt; /* DLT_XXX from bpf.h */ 83 }; 84 85 /* This structure is passed to NGM_NETFLOW_SETIFINDEX */ 86 struct ng_netflow_setifindex { 87 u_int16_t iface; /* which iface index change */ 88 u_int16_t index; /* new index */ 89 }; 90 91 /* This structure is passed to NGM_NETFLOW_SETTIMEOUTS */ 92 struct ng_netflow_settimeouts { 93 uint32_t inactive_timeout; /* flow inactive timeout */ 94 uint32_t active_timeout; /* flow active timeout */ 95 }; 96 97 #define NG_NETFLOW_CONF_INGRESS 1 98 #define NG_NETFLOW_CONF_EGRESS 2 99 #define NG_NETFLOW_CONF_ONCE 4 100 #define NG_NETFLOW_CONF_THISONCE 8 101 102 /* This structure is passed to NGM_NETFLOW_SETCONFIG */ 103 struct ng_netflow_setconfig { 104 u_int16_t iface; /* which iface config change */ 105 u_int32_t conf; /* new config */ 106 }; 107 108 /* This is unique data, which identifies flow */ 109 struct flow_rec { 110 struct in_addr r_src; 111 struct in_addr r_dst; 112 union { 113 struct { 114 uint16_t s_port; /* source TCP/UDP port */ 115 uint16_t d_port; /* destination TCP/UDP port */ 116 } dir; 117 uint32_t both; 118 } ports; 119 union { 120 struct { 121 u_char prot; /* IP protocol */ 122 u_char tos; /* IP TOS */ 123 uint16_t i_ifx; /* input interface index */ 124 } i; 125 uint32_t all; 126 } misc; 127 }; 128 129 #define r_ip_p misc.i.prot 130 #define r_tos misc.i.tos 131 #define r_i_ifx misc.i.i_ifx 132 #define r_misc misc.all 133 #define r_ports ports.both 134 #define r_sport ports.dir.s_port 135 #define r_dport ports.dir.d_port 136 137 /* A flow entry which accumulates statistics */ 138 struct flow_entry_data { 139 struct flow_rec r; 140 struct in_addr next_hop; 141 uint16_t fle_o_ifx; /* output interface index */ 142 #define fle_i_ifx r.misc.i.i_ifx 143 uint8_t dst_mask; /* destination route mask bits */ 144 uint8_t src_mask; /* source route mask bits */ 145 u_long packets; 146 u_long bytes; 147 long first; /* uptime on first packet */ 148 long last; /* uptime on last packet */ 149 u_char tcp_flags; /* cumulative OR */ 150 }; 151 152 /* 153 * How many flow records we will transfer at once 154 * without overflowing socket receive buffer 155 */ 156 #define NREC_AT_ONCE 1000 157 #define NGRESP_SIZE (sizeof(struct ngnf_flows) + (NREC_AT_ONCE * \ 158 sizeof(struct flow_entry_data))) 159 #define SORCVBUF_SIZE (NGRESP_SIZE + 2 * sizeof(struct ng_mesg)) 160 161 /* This struct is returned to userland, when "show cache ip flow" */ 162 struct ngnf_flows { 163 uint32_t nentries; 164 uint32_t last; 165 struct flow_entry_data entries[0]; 166 }; 167 168 /* Everything below is for kernel */ 169 170 #ifdef _KERNEL 171 172 struct flow_entry { 173 struct flow_entry_data f; 174 TAILQ_ENTRY(flow_entry) fle_hash; /* entries in hash slot */ 175 }; 176 177 /* Parsing declarations */ 178 179 /* Parse the info structure */ 180 #define NG_NETFLOW_INFO_TYPE { \ 181 { "Bytes", &ng_parse_uint64_type }, \ 182 { "Packets", &ng_parse_uint32_type }, \ 183 { "Records used", &ng_parse_uint32_type },\ 184 { "Failed allocations", &ng_parse_uint32_type },\ 185 { "Failed exports", &ng_parse_uint32_type },\ 186 { "Active expiries", &ng_parse_uint32_type },\ 187 { "Inactive expiries", &ng_parse_uint32_type },\ 188 { "Inactive timeout", &ng_parse_uint32_type },\ 189 { "Active timeout", &ng_parse_uint32_type },\ 190 { NULL } \ 191 } 192 193 /* Parse the ifinfo structure */ 194 #define NG_NETFLOW_IFINFO_TYPE { \ 195 { "packets", &ng_parse_uint32_type }, \ 196 { "data link type", &ng_parse_uint8_type }, \ 197 { "index", &ng_parse_uint16_type }, \ 198 { "conf", &ng_parse_uint32_type }, \ 199 { NULL } \ 200 } 201 202 /* Parse the setdlt structure */ 203 #define NG_NETFLOW_SETDLT_TYPE { \ 204 { "iface", &ng_parse_uint16_type }, \ 205 { "dlt", &ng_parse_uint8_type }, \ 206 { NULL } \ 207 } 208 209 /* Parse the setifindex structure */ 210 #define NG_NETFLOW_SETIFINDEX_TYPE { \ 211 { "iface", &ng_parse_uint16_type }, \ 212 { "index", &ng_parse_uint16_type }, \ 213 { NULL } \ 214 } 215 216 /* Parse the settimeouts structure */ 217 #define NG_NETFLOW_SETTIMEOUTS_TYPE { \ 218 { "inactive", &ng_parse_uint32_type }, \ 219 { "active", &ng_parse_uint32_type }, \ 220 { NULL } \ 221 } 222 223 /* Parse the setifindex structure */ 224 #define NG_NETFLOW_SETCONFIG_TYPE { \ 225 { "iface", &ng_parse_uint16_type }, \ 226 { "conf", &ng_parse_uint32_type }, \ 227 { NULL } \ 228 } 229 230 /* Private hook data */ 231 struct ng_netflow_iface { 232 hook_p hook; /* NULL when disconnected */ 233 hook_p out; /* NULL when no bypass hook */ 234 struct ng_netflow_ifinfo info; 235 }; 236 237 typedef struct ng_netflow_iface *iface_p; 238 typedef struct ng_netflow_ifinfo *ifinfo_p; 239 240 /* Structure describing our flow engine */ 241 struct netflow { 242 node_p node; /* link to the node itself */ 243 hook_p export; /* export data goes there */ 244 245 struct ng_netflow_info info; 246 struct callout exp_callout; /* expiry periodic job */ 247 248 /* 249 * Flow entries are allocated in uma(9) zone zone. They are 250 * indexed by hash hash. Each hash element consist of tailqueue 251 * head and mutex to protect this element. 252 */ 253 #define CACHESIZE (65536*4) 254 #define CACHELOWAT (CACHESIZE * 3/4) 255 #define CACHEHIGHWAT (CACHESIZE * 9/10) 256 uma_zone_t zone; 257 struct flow_hash_entry *hash; 258 259 /* 260 * NetFlow data export 261 * 262 * export_item is a data item, it has an mbuf with cluster 263 * attached to it. A thread detaches export_item from priv 264 * and works with it. If the export is full it is sent, and 265 * a new one is allocated. Before exiting thread re-attaches 266 * its current item back to priv. If there is item already, 267 * current incomplete datagram is sent. 268 * export_mtx is used for attaching/detaching. 269 */ 270 item_p export_item; 271 struct mtx export_mtx; 272 uint32_t flow_seq; /* current flow sequence */ 273 274 struct ng_netflow_iface ifaces[NG_NETFLOW_MAXIFACES]; 275 }; 276 277 typedef struct netflow *priv_p; 278 279 /* Header of a small list in hash cell */ 280 struct flow_hash_entry { 281 struct mtx mtx; 282 TAILQ_HEAD(fhead, flow_entry) head; 283 }; 284 285 #define ERROUT(x) { error = (x); goto done; } 286 287 #define MTAG_NETFLOW 1221656444 288 #define MTAG_NETFLOW_CALLED 0 289 290 /* Prototypes for netflow.c */ 291 int ng_netflow_cache_init(priv_p); 292 void ng_netflow_cache_flush(priv_p); 293 void ng_netflow_copyinfo(priv_p, struct ng_netflow_info *); 294 timeout_t ng_netflow_expire; 295 int ng_netflow_flow_add(priv_p, struct ip *, unsigned int src_if_index); 296 int ng_netflow_flow_show(priv_p, uint32_t last, struct ng_mesg *); 297 298 #endif /* _KERNEL */ 299 #endif /* _NG_NETFLOW_H_ */ 300