Changeset View
Standalone View
sys/netinet/siftr.c
Show First 20 Lines • Show All 266 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
DPCPU_DEFINE_STATIC(struct siftr_stats, ss); | DPCPU_DEFINE_STATIC(struct siftr_stats, ss); | ||||
static volatile unsigned int siftr_exit_pkt_manager_thread = 0; | static volatile unsigned int siftr_exit_pkt_manager_thread = 0; | ||||
static unsigned int siftr_enabled = 0; | static unsigned int siftr_enabled = 0; | ||||
static unsigned int siftr_pkts_per_log = 1; | static unsigned int siftr_pkts_per_log = 1; | ||||
static unsigned int siftr_generate_hashes = 0; | static unsigned int siftr_generate_hashes = 0; | ||||
static unsigned int siftr_port_filter = 0; | |||||
/* static unsigned int siftr_binary_log = 0; */ | /* static unsigned int siftr_binary_log = 0; */ | ||||
static char siftr_logfile[PATH_MAX] = "/var/log/siftr.log"; | static char siftr_logfile[PATH_MAX] = "/var/log/siftr.log"; | ||||
static char siftr_logfile_shadow[PATH_MAX] = "/var/log/siftr.log"; | static char siftr_logfile_shadow[PATH_MAX] = "/var/log/siftr.log"; | ||||
static u_long siftr_hashmask; | static u_long siftr_hashmask; | ||||
STAILQ_HEAD(pkthead, pkt_node) pkt_queue = STAILQ_HEAD_INITIALIZER(pkt_queue); | STAILQ_HEAD(pkthead, pkt_node) pkt_queue = STAILQ_HEAD_INITIALIZER(pkt_queue); | ||||
LIST_HEAD(listhead, flow_hash_node) *counter_hash; | LIST_HEAD(listhead, flow_hash_node) *counter_hash; | ||||
static int wait_for_pkt; | static int wait_for_pkt; | ||||
static struct alq *siftr_alq = NULL; | static struct alq *siftr_alq = NULL; | ||||
Show All 29 Lines | |||||
SYSCTL_UINT(_net_inet_siftr, OID_AUTO, ppl, CTLFLAG_RW, | SYSCTL_UINT(_net_inet_siftr, OID_AUTO, ppl, CTLFLAG_RW, | ||||
&siftr_pkts_per_log, 1, | &siftr_pkts_per_log, 1, | ||||
"number of packets between generating a log message"); | "number of packets between generating a log message"); | ||||
SYSCTL_UINT(_net_inet_siftr, OID_AUTO, genhashes, CTLFLAG_RW, | SYSCTL_UINT(_net_inet_siftr, OID_AUTO, genhashes, CTLFLAG_RW, | ||||
&siftr_generate_hashes, 0, | &siftr_generate_hashes, 0, | ||||
"enable packet hash generation"); | "enable packet hash generation"); | ||||
SYSCTL_UINT(_net_inet_siftr, OID_AUTO, port_filter, CTLFLAG_RW, | |||||
&siftr_port_filter, 0, | |||||
"enable packet filter on a TCP port"); | |||||
/* XXX: TODO | /* XXX: TODO | ||||
SYSCTL_UINT(_net_inet_siftr, OID_AUTO, binary, CTLFLAG_RW, | SYSCTL_UINT(_net_inet_siftr, OID_AUTO, binary, CTLFLAG_RW, | ||||
&siftr_binary_log, 0, | &siftr_binary_log, 0, | ||||
"write log files in binary instead of ascii"); | "write log files in binary instead of ascii"); | ||||
*/ | */ | ||||
/* Begin functions. */ | /* Begin functions. */ | ||||
▲ Show 20 Lines • Show All 574 Lines • ▼ Show 20 Lines | if (tp == NULL || inp->inp_flags & INP_TIMEWAIT) { | ||||
if (dir == PFIL_IN) | if (dir == PFIL_IN) | ||||
ss->nskip_in_tcpcb++; | ss->nskip_in_tcpcb++; | ||||
else | else | ||||
ss->nskip_out_tcpcb++; | ss->nskip_out_tcpcb++; | ||||
goto inp_unlock; | goto inp_unlock; | ||||
} | } | ||||
/* | |||||
* Only pkts selected by the tcp port filter | |||||
* can be inserted into the pkt_queue | |||||
*/ | |||||
if (siftr_port_filter && (siftr_port_filter != ntohs(inp->inp_lport)) && | |||||
(siftr_port_filter != ntohs(inp->inp_fport))) { | |||||
goto inp_unlock; | |||||
} | |||||
pn = malloc(sizeof(struct pkt_node), M_SIFTR_PKTNODE, M_NOWAIT|M_ZERO); | pn = malloc(sizeof(struct pkt_node), M_SIFTR_PKTNODE, M_NOWAIT|M_ZERO); | ||||
if (pn == NULL) { | if (pn == NULL) { | ||||
if (dir == PFIL_IN) | if (dir == PFIL_IN) | ||||
ss->nskip_in_malloc++; | ss->nskip_in_malloc++; | ||||
else | else | ||||
ss->nskip_out_malloc++; | ss->nskip_out_malloc++; | ||||
▲ Show 20 Lines • Show All 276 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
siftr_manage_ops(uint8_t action) | siftr_manage_ops(uint8_t action) | ||||
{ | { | ||||
struct siftr_stats totalss; | struct siftr_stats totalss; | ||||
struct timeval tval; | struct timeval tval; | ||||
struct flow_hash_node *counter, *tmp_counter; | struct flow_hash_node *counter, *tmp_counter; | ||||
struct sbuf *s; | struct sbuf *s; | ||||
int i, key_index, error; | int i, key_index, error = 0; | ||||
uint32_t bytes_to_write, total_skipped_pkts; | uint32_t bytes_to_write, total_skipped_pkts = 0; | ||||
brooks: Looking again, both of these initializations are performed a few lines down and should not be… | |||||
struct sbuf sb; | |||||
char buf[480]; | |||||
Done Inline ActionsYou can submit the changes in this function in a separate patch. cc: You can submit the changes in this function in a separate patch. | |||||
impUnsubmitted Done Inline ActionsDon't allocate 480-byte structures on the stack. That's a problem. imp: Don't allocate 480-byte structures on the stack. That's a problem. | |||||
uint16_t lport, fport; | uint16_t lport, fport; | ||||
uint8_t *key, ipver __unused; | uint8_t *key, ipver __unused; | ||||
#ifdef SIFTR_IPV6 | #ifdef SIFTR_IPV6 | ||||
uint32_t laddr[4]; | uint32_t laddr[4]; | ||||
uint32_t faddr[4]; | uint32_t faddr[4]; | ||||
#else | #else | ||||
uint8_t laddr[4]; | uint8_t laddr[4]; | ||||
uint8_t faddr[4]; | uint8_t faddr[4]; | ||||
#endif | #endif | ||||
error = 0; | error = 0; | ||||
total_skipped_pkts = 0; | total_skipped_pkts = 0; | ||||
/* Init an autosizing sbuf that initially holds 200 chars. */ | /* Init an autosizing sbuf that initially holds 200 chars. */ | ||||
impUnsubmitted Done Inline Actionsthis doesn't match any more. why make the change? The stack space used is problematic. imp: this doesn't match any more. why make the change? The stack space used is problematic.
| |||||
if ((s = sbuf_new(NULL, NULL, 200, SBUF_AUTOEXTEND)) == NULL) | if ((s = sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN)) == NULL) | ||||
return (-1); | return (-1); | ||||
if (action == SIFTR_ENABLE) { | if (action == SIFTR_ENABLE) { | ||||
/* | /* | ||||
* Create our alq | * Create our alq | ||||
* XXX: We should abort if alq_open fails! | * XXX: We should abort if alq_open fails! | ||||
*/ | */ | ||||
alq_open(&siftr_alq, siftr_logfile, curthread->td_ucred, | alq_open(&siftr_alq, siftr_logfile, curthread->td_ucred, | ||||
rscheffAuthorUnsubmitted Done Inline ActionsWhile we are at it, shouldn't there be a check to avoid potentially leaking memory by running twice over SIFTR_ENABLE? rscheff: While we are at it, shouldn't there be a check to avoid potentially leaking memory by running… | |||||
SIFTR_LOG_FILE_MODE, SIFTR_ALQ_BUFLEN, 0); | SIFTR_LOG_FILE_MODE, SIFTR_ALQ_BUFLEN, 0); | ||||
STAILQ_INIT(&pkt_queue); | STAILQ_INIT(&pkt_queue); | ||||
DPCPU_ZERO(ss); | DPCPU_ZERO(ss); | ||||
siftr_exit_pkt_manager_thread = 0; | siftr_exit_pkt_manager_thread = 0; | ||||
▲ Show 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | #endif | ||||
do { | do { | ||||
bytes_to_write = min(SIFTR_ALQ_BUFLEN, sbuf_len(s)-i); | bytes_to_write = min(SIFTR_ALQ_BUFLEN, sbuf_len(s)-i); | ||||
alq_writen(siftr_alq, sbuf_data(s)+i, bytes_to_write, ALQ_WAITOK); | alq_writen(siftr_alq, sbuf_data(s)+i, bytes_to_write, ALQ_WAITOK); | ||||
i += bytes_to_write; | i += bytes_to_write; | ||||
} while (i < sbuf_len(s)); | } while (i < sbuf_len(s)); | ||||
alq_close(siftr_alq); | alq_close(siftr_alq); | ||||
siftr_alq = NULL; | siftr_alq = NULL; | ||||
} | } | ||||
brooksUnsubmitted Done Inline ActionsThere should almost certainly be an: else error = EINVAL; just in case someone messes up a future caller's implementation. Alternatively a KASSERT() at the top. brooks: There should almost certainly be an:
```
else
error = EINVAL;
```
just in case someone… | |||||
sbuf_delete(s); | sbuf_delete(s); | ||||
/* | /* | ||||
* XXX: Should be using ret to check if any functions fail | * XXX: Should be using ret to check if any functions fail | ||||
* and set error appropriately | * and set error appropriately | ||||
*/ | */ | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
siftr_sysctl_enabled_handler(SYSCTL_HANDLER_ARGS) | siftr_sysctl_enabled_handler(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
int error; | int error; | ||||
uint32_t new; | uint32_t new; | ||||
new = siftr_enabled; | new = siftr_enabled; | ||||
error = sysctl_handle_int(oidp, &new, 0, req); | error = sysctl_handle_int(oidp, &new, 0, req); | ||||
if (error != 0 && req->newptr != NULL) { | if (error == 0 && req->newptr != NULL) { | ||||
if (new > 1) | if (new > 1) | ||||
return (EINVAL); | return (EINVAL); | ||||
Done Inline ActionsYes, no need to check for <0 here, the sysctl checks for positive values only apparently. rscheff: Yes, no need to check for <0 here, the sysctl checks for positive values only apparently. | |||||
else if (new != siftr_enabled) { | else if (new != siftr_enabled) { | ||||
error = siftr_manage_ops(new); | if ((error = siftr_manage_ops(new)) == 0) { | ||||
if (error != 0) | siftr_enabled = new; | ||||
Not Done Inline ActionsThe "new" variable type is uint32_t. cc: The "new" variable type is uint32_t.
This fixes the broke part. However, I don't know why the… | |||||
Not Done Inline Actionsthe user could choose to set it to any arbitrary value between 0..(2^32-1); the alternative would be to normalize any non-zero value to SIFTR_ENABLE. rscheff: the user could choose to set it to any arbitrary value between 0..(2^32-1); the alternative… | |||||
} else { | |||||
siftr_manage_ops(SIFTR_DISABLE); | siftr_manage_ops(SIFTR_DISABLE); | ||||
} | } | ||||
} | } | ||||
} | |||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
siftr_shutdown_handler(void *arg) | siftr_shutdown_handler(void *arg) | ||||
{ | { | ||||
if (siftr_enabled == 1) { | |||||
siftr_manage_ops(SIFTR_DISABLE); | siftr_manage_ops(SIFTR_DISABLE); | ||||
} | |||||
} | } | ||||
/* | /* | ||||
* Module is being unloaded or machine is shutting down. Take care of cleanup. | * Module is being unloaded or machine is shutting down. Take care of cleanup. | ||||
*/ | */ | ||||
static int | static int | ||||
deinit_siftr(void) | deinit_siftr(void) | ||||
▲ Show 20 Lines • Show All 93 Lines • Show Last 20 Lines |
Looking again, both of these initializations are performed a few lines down and should not be done here.