/* Return per-thread consumed CPU time. */ double SNetThreadTime(void) { struct timespec ts = { 0, 0 }; int r = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); CHECK(r); return TS2SEC(ts); }
static int update(pkt_t *pkt, void *fh, int isnew) { FLOWDESC *x = F(fh); if (isnew) { x->ts = TS2SEC(pkt->ts); x->bytes = 0; x->pkts = 0; x->proto = IP(proto); x->src_ip = IP(src_ip); x->dst_ip = IP(dst_ip); N16(x->src_port) = N16(x->dst_port) = 0; if (IP(proto) == IPPROTO_TCP || IP(proto) == IPPROTO_UDP) { x->src_port = UDP(src_port); x->dst_port = UDP(dst_port); } } x->bytes += H16(IP(len)); x->pkts++; return 0; }
/* Return per-process consumed CPU time. */ double SNetProcessTime(void) { struct timespec ts = { 0, 0 }; int r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); CHECK(r); return TS2SEC(ts); }
static int update(pkt_t *pkt, void *fh, int isnew) { FLOWDESC *x = F(fh); if (isnew) { x->ts = TS2SEC(pkt->ts); x->bytes = 0; x->bytes_ivl = 0; x->hi_watermark = 0; x->last_watermark = pkt->ts; } x->bytes += H16(IP(len)); if (pkt->ts - x->last_watermark > WATERMARK_IVL) { x->last_watermark = pkt->ts; x->bytes_ivl = 0; } x->bytes_ivl += pkt->len; if (x->bytes_ivl > x->hi_watermark) x->hi_watermark = x->bytes_ivl; return 0; }
static char * print(__unused void * self, char *buf, size_t *len, char * const args[]) { static char s[512]; static char * fmt; FLOWDESC *x; timestamp_t ts; time_t t; char ssid[34]; uint8_t sig, noise; if (buf == NULL && args != NULL) { int n; /* first call of print, process the arguments and return */ for (n = 0; args[n]; n++) { if (!strcmp(args[n], "format=plain")) { *len = 0; fmt = PLAINFMT; return s; } } /* by default, pretty print */ *len = sprintf(s, PRETTYHDR); fmt = PRETTYFMT; return s; } if (buf == NULL && args == NULL) { *len = 0; return s; } x = (FLOWDESC *) buf; ts = NTOHLL(x->ts); t = (time_t) TS2SEC(ts); snprintf(ssid, x->len+1, x->ssid); sig = (uint8_t)(ntohl(x->signal) / x->samples); noise = (uint8_t)(ntohl(x->noise) / x->samples); /* print according to the requested format */ if (fmt == PRETTYFMT) { char * wepmode = x->wepmode? "Y": "N"; *len = sprintf(s, fmt, asctime(localtime(&t)), (sig-256), (noise-256), x->channel, x->samples, wepmode, ssid); } else { *len = sprintf(s, fmt, (long int) t, x->wepmode, x->channel, (sig-256), (noise-256), x->samples); } return s; }
/* Return wall-clock time. */ double SNetRealTime(void) { #ifdef CLOCK_REALTIME struct timespec ts = { 0, 0 }; int r = clock_gettime(CLOCK_REALTIME, &ts); CHECK(r); return TS2SEC(ts); #else /* __APPLE__ || __MACH__ */ struct timeval tv = { 0, 0 }; int r = gettimeofday(&tv, NULL); \ CHECK(r); return TV2SEC(&tv); #endif }
static char * print(void * self, char *buf, size_t *len, char * const args[]) { static char s[512]; static char * fmt; static int granularity = 1; static int no_records = 0; static uint64_t bytes = 0; static uint64_t pkts = 0; CONFIGDESC * config = CONFIG(self); FLOWDESC *x; timestamp_t ts; time_t t; int n; if (buf == NULL && args != NULL) { /* by default, pretty print */ *len = sprintf(s, PRETTYHDR); fmt = PRETTYFMT; /* first call of print, process the arguments and return */ for (n = 0; args[n]; n++) { if (!strcmp(args[n], "format=plain")) { *len = 0; fmt = PLAINFMT; } else if (!strcmp(args[n], "format=gnuplot")) { *len = sprintf(s, GNUPLOTHDR); fmt = GNUPLOTFMT; } else if (!strncmp(args[n], "granularity=", 10)) { char * val = index(args[n], '=') + 1; /* aggregate multiple records into one to reduce * communication messages. */ granularity = MAX(atoi(val) / config->meas_ivl, 1); } else if (!strcmp(args[n], "format=mbps")) { *len = 0; fmt = MBPSFMT; } } return s; } if (buf == NULL && args == NULL) { *len = 0; if (fmt == GNUPLOTFMT) *len = sprintf(s, GNUPLOTFOOTER); return s; } x = (FLOWDESC *) buf; ts = NTOHLL(x->ts); t = (time_t) TS2SEC(ts); /* aggregate records if needed */ pkts += ntohl(x->pkts); bytes += NTOHLL(x->bytes); no_records++; if (no_records % granularity != 0) { *len = 0; return s; } bytes /= granularity; pkts /= granularity; /* print according to the requested format */ if (fmt == PRETTYFMT) { *len = sprintf(s, fmt, asctime(localtime(&t)), TS2SEC(ts), TS2USEC(ts), bytes, pkts); } else if (fmt == GNUPLOTFMT) { float mbps = 8.0 * (float) bytes / 1000000.0; *len = sprintf(s, fmt, (long int)t, mbps, pkts); } else if (fmt == MBPSFMT) { float mbps = 8.0 * (float) bytes / 1000000.0; *len = sprintf(s, fmt, mbps); } else { *len = sprintf(s, fmt, (long int)t, ts, bytes, pkts); } pkts = bytes = 0; return s; }
static char * print(void * self, char *buf, size_t *len, char * const args[]) { static char s[512]; static char * fmt; static int granularity = 1; static int use_bytes = 0; static int no_records = 0; static int64_t count[2] = {0, 0}; config_t * cf = CONFIG(self); FLOWDESC *x; timestamp_t ts; time_t t; int n; if (buf == NULL && args != NULL) { /* by default, pretty print */ *len = sprintf(s, PRETTYHDR); fmt = prettyfmt; /* first call of print, process the arguments and return */ for (n = 0; args[n]; n++) { if (!strcmp(args[n], "format=plain")) { *len = 0; fmt = plainfmt; } else if (!strcmp(args[n], "format=gnuplot")) { fmt = gnuplotfmt; } else if (!strcmp(args[n], "use-bytes")) { use_bytes = 1; } else if (!strncmp(args[n], "granularity=", 10)) { char * val = index(args[n], '=') + 1; /* aggregate multiple records into one to reduce * communication messages. */ granularity = MAX(atoi(val) / cf->meas_ivl, 1); } } if (fmt == gnuplotfmt) { *len = sprintf(s, GNUPLOTHDR, use_bytes? "Mbps" : "packets/sec"); } return s; } if (buf == NULL && args == NULL) { *len = 0; if (fmt == gnuplotfmt) *len = sprintf(s, GNUPLOTFOOTER); return s; } x = (FLOWDESC *) buf; ts = NTOHLL(x->ts); t = (time_t) TS2SEC(ts); /* aggregate records if needed */ count[0] += use_bytes? NTOHLL(x->bytes[0]) : ntohl(x->pkts[0]); count[1] -= use_bytes? NTOHLL(x->bytes[1]) : ntohl(x->pkts[1]); no_records++; if (no_records % granularity != 0) { *len = 0; return s; } count[0] /= granularity; count[1] /= granularity; /* print according to the requested format */ if (fmt == prettyfmt) { *len = sprintf(s, fmt, asctime(localtime(&t)), TS2SEC(ts), TS2USEC(ts), count[0], count[1]); } else if (fmt == gnuplotfmt) { if (use_bytes) { float mbps_in = 8.0 * (float) count[0] / 1000000.0; float mbps_out = 8.0 * (float) count[1] / 1000000.0; *len = sprintf(s, "%ld %f %f\n", (long int) t, mbps_in, mbps_out); } else { *len = sprintf(s, "%ld %u %u\n", (long int) t, (uint32_t) count[0], (uint32_t) count[1]); } } else { *len = sprintf(s, fmt, (long int)t, ts, count[0], count[1]); } count[0] = count[1] = 0; return s; }
void print_rec(mdl_t *self, int format_id, record_t *rec, qstate_t *s) { char *t_str; time_t t; int i; /* aggregate records */ if (s->record_count % s->granularity == 0) { s->ts = rec->ts; memset(s->aggr_pkts, 0, sizeof(s->aggr_pkts)); memset(s->aggr_bytes, 0, sizeof(s->aggr_bytes)); } for (i = 0; i < s->classes; i++) { s->aggr_pkts[i] += rec->pkts[i]; s->aggr_bytes[i] += rec->bytes[i]; } s->record_count++; if (s->record_count % s->granularity != 0) return; /* next record still belongs to aggregation interval */ /* normalize to pkts and bytes per second */ for (i = 0; i < s->classes; i++) s->aggr_pkts[i] /= s->meas_ivl * s->granularity; /* print */ t = (time_t) TS2SEC(s->ts); t_str = asctime(localtime(&t)); if (format_id == FORMAT_PLAIN) { mdl_printf(self, "%12llu", (uint) t); for (i = 0; i < s->classes; i++) mdl_printf(self, " %8llu %8u", s->aggr_bytes[i], s->aggr_pkts[i]); mdl_printf(self, "\n"); } else if (format_id == FORMAT_PRETTY) { mdl_printf(self, "%.24s", asctime(localtime(&t))); for (i = 0; i < s->classes; i++) mdl_printf(self, " %8llu %8u", s->aggr_bytes[i], s->aggr_pkts[i]); mdl_printf(self, "\n"); } else if (format_id == FORMAT_GNUPLOT && s->relative) { double total_bytes, total_pkts, b, p; time_t t; for (i = 0; i < s->classes; i++) { total_pkts += s->aggr_pkts[i]; total_bytes += s->aggr_bytes[i]; } t = (time_t) TS2SEC(s->ts); mdl_printf(self, "%u", (uint) t); for (i = 0; i < s->classes - 1; i++) { b = total_bytes == 0 ? 0 : ((double)s->aggr_bytes[i]) / total_bytes; p = total_pkts == 0 ? 0 : ((double)s->aggr_pkts[i]) / total_pkts; b *= 100; p *= 100; mdl_printf(self, " %.2f %.2f", b, p); } if (total_pkts == 0) b = p = 0; else b = p = 100; mdl_printf(self, " %.2f %.2f\n", b, p); } else if (format_id == FORMAT_GNUPLOT) { double mbps = 0; uint32_t pkts = 0; mdl_printf(self, "%u", (uint) t); /* print the ts */ for (i = 0; i < s->classes; i++) { mbps += ((double) s->aggr_bytes[i]) * 8.0 / 1000000.0; pkts += s->aggr_pkts[i]; mdl_printf(self, " %.2f %u", mbps, pkts); } mdl_printf(self, "\n"); } }
static char * print(char *buf, size_t *len, char * const args[]) { static char s[512]; static char * fmt; FLOWDESC *x; timestamp_t ts; time_t t; char ssid[34]; int hh, mm, ss; if (buf == NULL && args != NULL) { int n; /* first call of print, process the arguments and return */ for (n = 0; args[n]; n++) { if (!strcmp(args[n], "format=plain")) { *len = 0; fmt = PLAINFMT; return s; } } /* by default, pretty print */ *len = sprintf(s, PRETTYHDR); fmt = PRETTYFMT; return s; } if (buf == NULL && args == NULL) { *len = 0; return s; } x = (FLOWDESC *) buf; ts = NTOHLL(x->ts); hh = (TS2SEC(ts) % 86400) /3600; mm = (TS2SEC(ts) % 3600) / 60; ss = TS2SEC(ts) % 60; t = (time_t) TS2SEC(ts); snprintf(ssid, x->len+1, x->ssid); if (fmt == PRETTYFMT) { int n; *len = sprintf(s, fmt, hh, mm, ss, TS2USEC(ts), ntohl(x->signal)-256, ntohl(x->noise)-256); for (n = 0; n < MAC_ADDR_SIZE; n++) *len += sprintf(s + *len, "%02x%s", x->addr[n], n < (MAC_ADDR_SIZE-1) ? ":": " "); switch (ntohl(x->phytype)) { case PHYTYPE_FHSS_DOT11_97: *len += sprintf(s + *len, "%-15s", "FHSS 802.11 97"); break; case PHYTYPE_DSSS_DOT11_97: *len += sprintf(s + *len, "%-15s", "DSSS 802.11 97"); break; case PHYTYPE_IRBASEBAND: *len += sprintf(s + *len, "%-15s", "IR BASEBAND"); break; case PHYTYPE_DSSS_DOT11_B: *len += sprintf(s + *len, "%-15s", "DSSS 802.11b"); break; case PHYTYPE_PBCC_DOT11_B: *len += sprintf(s + *len, "%-15s", "PBCC 802.11b"); break; case PHYTYPE_OFDM_DOT11_G: *len += sprintf(s + *len, "%-15s", "OFDM 802.11g"); break; case PHYTYPE_PBCC_DOT11_G: *len += sprintf(s + *len, "%-15s", "PBCC 802.11g"); break; case PHYTYPE_OFDM_DOT11_A: *len += sprintf(s + *len, "%-15s", "OFDM 802.11a"); break; default: *len += sprintf(s + *len, "%-15s", "FOREIGN"); break; } switch(ntohl(x->encoding)) { case UNKNOWN_ENCODING: *len += sprintf(s + *len, "%-10s", "UNKNOWN"); break; case CCK_ENCODING: *len += sprintf(s + *len, "%-10s", "CCK"); break; case PBCC_ENCODING: *len += sprintf(s + *len, "%-10s", "PBCC"); break; case OFDM_ENCODING: *len += sprintf(s + *len, "%-10s", "OFDM"); break; default: *len += sprintf(s + *len, "%-10s", "FOREIGN"); break; } *len += sprintf(s + *len, " %-3d%-7s %-5d %-32s", x->bivl, "ms", x->channel, ssid); *len += sprintf(s + *len, "\n"); } else { *len = sprintf(s, fmt, (long int) t, (ntohl(x->signal)-256), (ntohl(x->noise)-256), x->bivl, x->channel, ssid); } return s; }
/* * -- query_parse() * * Takes an http-like request and formats a message in the standard format * GET ?module=xxx&start=xxx&end=xxx&other HTTP/1.x */ static qreq_t * query_parse(char *buf, timestamp_t now) { static qreq_t q; int max_args, nargs; char *p, *p1, *end; /* * do a first pass to figure out how much space we need * to store all the request parameters (i.e. args strings) * * NOTE: max_args will always be at least one (i.e., the NULL entry * to indicate end of the arguments). */ max_args = 0; p = buf; do { p = strchr(p+1, '&'); max_args++; } while (p != NULL && strlen(p) > 1); /* allocate a new request data structures */ q.args = safe_calloc(max_args, sizeof(char *)); nargs = 0; /* provide some default values */ q.len = sizeof(q); q.start = TS2SEC(now) - 50; q.end = TS2SEC(now) + 20; q.format = Q_OTHER; q.wait = 1; q.source = NULL; /* * check if the request is valid. look for GET and HTTP/1 * somewhere in the string. */ if (strstr(buf, "GET") != buf) { logmsg(LOGQUERY, "Malformed request %s\n", buf); return NULL; } end = strstr(buf, "HTTP/1"); if (end == NULL) { logmsg(LOGQUERY, "Malformed request %s\n", buf); return NULL; } /* mark the end of the useful string. walk backwards and * remove any space at the end of the HTTP request. */ *end = '\0'; for (; end > buf && index(" \t", *end) != NULL; end--) *end = '\0'; /* after GET we expect whitespace then a string */ for (p = buf + 3; *p && index(" \t", *p) != NULL; p++) ; if (p == buf+3 || *p == '\0') { logmsg(LOGQUERY, "Malformed request %s\n", buf); return NULL; } for (; *p > ' ' && *p != '?'; p++) ; if (*p != '?') { /* invalid module, but do not fail so we return a 'not found' */ logmsg(LOGQUERY, "Malformed request %s\n", buf); return NULL; } logmsg(V_LOGQUERY, "Good request %s\n", p); p = urldecode(p); while ( (p1 = strsep(&p, "?&")) != NULL) { logmsg(V_LOGQUERY, "Token %s %s\n", p1, p); if (p == p1+1) /* empty string */ ; else if (strstr(p1, "module=") == p1) { char * s = strchr(p1, '='); asprintf(&q.module, "%s", s + 1); } else if (strstr(p1, "filter=") == p1) { char * s = strchr(p1, '='); q.filter_str = strdup(s + 1); parse_filter(s + 1, NULL, &(q.filter_cmp)); } else if (strstr(p1, "start=") == p1) { q.start = atoi(p1+6); } else if (strstr(p1, "end=") == p1) { q.end = atoi(p1+4); } else if (strstr(p1, "format=raw") == p1) { q.format = Q_RAW; } else if (strstr(p1, "format=como") == p1) { q.format = Q_COMO; } else if (strstr(p1, "format=html") == p1) { q.format = Q_HTML; /* we forward this to the module */ q.args[nargs] = strdup(p1); nargs++; assert(nargs < max_args); } else if (strstr(p1, "wait=no") == p1) { q.wait = 0; } else if (strstr(p1, "status") == p1) { q.format = Q_STATUS; } else if (strstr(p1, "time=") == p1) { timestamp_t current; char * str; current = now; str = index(p1, '=') + 1; q.start = parse_timestr(str, ¤t); str = index(p1, ':') + 1; q.end = parse_timestr(str, ¤t); } else if (strstr(p1, "source=") == p1) { char * s = strchr(p1, '='); q.source = strdup(s + 1); } else { logmsg(V_LOGQUERY, "custom argument: %s\n", p1); q.args[nargs] = strdup(p1); nargs++; assert(nargs < max_args); } } return &q; }
/* * -- parse_timestr() * * This function parse the time string of a query. The string is made of * two parts representing the two extreme of the time window. They two * parts are separated by a colon (:). * Valid formats for the start and end times are as follows: * * . 0, to indicate the time the query is received; * . @[cc[yy[mm[dd[hhmmss]]]]], to indicate an exact time; * . [+|-][[^0-9]d][[^0-9]h][[^0-9]m][[^0-9]s], to indicate an offset * from the time the query is received. * */ static uint32_t parse_timestr(char * str, timestamp_t * base) { struct tm timeinfo; time_t ts; char * wh; size_t len; int adding; assert(str != NULL); assert(base != NULL); ts = TS2SEC(*base); gmtime_r(&ts, &timeinfo); /* look if this is a start or end */ wh = index(str, ':'); len = (wh == NULL)? strlen(str) : (size_t) (wh - str); adding = 0; switch (str[0]) { case '@': /* absolute timestamp */ for (str++, len--; len > 0; str += 2, len -= 2) { char val[3] = {0}; /* get two digits */ bcopy(str, val, 2); if (len == 14) /* century */ timeinfo.tm_year = (atoi(val) * 100) - 1900; else if (len == 12) /* year */ timeinfo.tm_year = atoi(val) + 100*(timeinfo.tm_year/100); else if (len == 10) /* month */ timeinfo.tm_mon = atoi(val) - 1; else if (len == 8) /* day */ timeinfo.tm_mday = atoi(val); else if (len == 6) /* hour */ timeinfo.tm_hour = atoi(val); else if (len == 4) /* minute */ timeinfo.tm_min = atoi(val); else if (len == 2) /* second */ timeinfo.tm_sec = atoi(val); else /* error */ break; } if (len > 0) { logmsg(LOGWARN, "time %s incorrect, using current time\n", str); return TS2SEC(*base); } ts = timegm(&timeinfo); *base = TIME2TS(ts, 0); break; case '+': /* relative timestamp (after current time) */ adding = 2; /* pass thru */ case '-': /* relative timestamp (before current time) */ adding--; /* skip first character */ str++; len--; /* check for one letter (in [dhms]) at a time */ while (len > 0) { int x; int val; val = atoi(str); x = strspn(str, "1234567890"); str += x; len -= x; if (str[0] == 'd') /* day */ timeinfo.tm_mday += adding*val; else if (str[0] == 'h') /* hour */ timeinfo.tm_hour += adding*val; else if (str[0] == 'm') /* minute */ timeinfo.tm_min += adding*val; else if (str[0] == 's') /* seconds */ timeinfo.tm_sec += adding*val; else /* error */ break; /* skip letter */ str++; len--; } if (len > 0) { logmsg(LOGWARN, "time %s incorrect, using current time\n", str); return (uint32_t) timegm(&timeinfo); } ts = timegm(&timeinfo); break; default: /* nothing set, use current time */ break; } return (uint32_t) ts; }