size_t lookup_token(const struct CF_Token *token) { unsigned offset = 0; unsigned state = 0; return smack_search_next( statement_names, &state, token->name, &offset, (unsigned)token->name_length + 1); }
size_t lookup_name(const struct CF_Child *node) { unsigned offset = 0; unsigned state = 0; return smack_search_next( statement_names, &state, node->name, &offset, (unsigned)node->name_length + 1); }
static void do_haystack(const struct SMACK *smack, const char *buffer, size_t sizeof_buffer, unsigned long long iterations) { unsigned long long start, stop; unsigned long long cycle1, cycle2; unsigned i; unsigned found_count = 0; start = pixie_nanotime(); cycle1 = __rdtsc(); for (i=0; i<iterations; i++) { unsigned state = 0; unsigned offset = 0; while (offset < sizeof_buffer) { size_t x; x = smack_search_next(smack, &state, buffer, &offset, sizeof_buffer); if (x != SMACK_NOT_FOUND) found_count++; } } cycle2 = __rdtsc(); stop = pixie_nanotime(); { double elapsed = ((double)(stop - start))/(1000000000.0); double rate = (sizeof_buffer*iterations*8ULL)/elapsed; double cycles = (sizeof_buffer*iterations*1.0)/(1.0*(cycle2-cycle1)); rate /= 1000000.0; printf("Found count = %u\n", (unsigned)(found_count/iterations)); printf("Search speed = %5.3f-gbps (%3.2f-Hz/byte)\n", rate/1000.0, (1.0/cycles)); printf("CPU speed = %5.3f-GHz\n", ((cycle2-cycle1)*1.0/elapsed)/1000000000.0); } }
unsigned banner1_parse( const struct Banner1 *banner1, struct ProtocolState *tcb_state, const unsigned char *px, size_t length, struct BannerOutput *banout) { size_t x; unsigned offset = 0; switch (tcb_state->app_proto) { case PROTO_NONE: case PROTO_HEUR: x = smack_search_next( banner1->smack, &tcb_state->state, px, &offset, (unsigned)length); if (x != SMACK_NOT_FOUND && !(x == PROTO_SSL3 && !tcb_state->is_sent_sslhello)) { unsigned i; /* re-read the stuff that we missed */ for (i=0; patterns[i].id && patterns[i].id != tcb_state->app_proto; i++) ; /* Kludge: patterns look confusing, so add port info to the * pattern */ switch (x) { case PROTO_FTP2: if (tcb_state->port == 25 || tcb_state->port == 587) x = PROTO_SMTP; break; } tcb_state->app_proto = (unsigned short)x; /* reset the state back again */ tcb_state->state = 0; /* If there is any data from a previous packet, re-parse that */ { const unsigned char *s = banout_string(banout, PROTO_HEUR); unsigned s_len = banout_string_length(banout, PROTO_HEUR); if (s && s_len) banner1_parse( banner1, tcb_state, s, s_len, banout); } banner1_parse( banner1, tcb_state, px, length, banout); } else { banout_append(banout, PROTO_HEUR, px, length); } break; case PROTO_SSH1: case PROTO_SSH2: case PROTO_FTP1: case PROTO_FTP2: case PROTO_SMTP: case PROTO_POP3: case PROTO_IMAP4: /* generic text-based parser * TODO: in future, need to split these into separate protocols, * especially when binary parsing is added to SSH */ banner_ssh.parse( banner1, banner1->http_fields, tcb_state, px, length, banout); break; case PROTO_HTTP: banner_http.parse( banner1, banner1->http_fields, tcb_state, px, length, banout); break; case PROTO_SSL3: banner_ssl.parse( banner1, banner1->http_fields, tcb_state, px, length, banout); break; default: fprintf(stderr, "banner1: internal error\n"); break; } return tcb_state->app_proto; }
void banner1_parse( struct Banner1 *banner1, struct Banner1State *pstate, unsigned *proto, const unsigned char *px, size_t length, char *banner, unsigned *banner_offset, size_t banner_max) { size_t x; unsigned offset = 0; switch (*proto) { case PROTO_UNKNOWN: x = smack_search_next( banner1->smack, &pstate->state, px, &offset, (unsigned)length); if (x != SMACK_NOT_FOUND && !(x == PROTO_SSL3 && !pstate->is_sent_sslhello)) { unsigned i; /* Kludge: patterns look confusing, so add port info to the * pattern */ switch (*proto) { case PROTO_FTP2: if (pstate->port == 25 || pstate->port == 587) *proto = PROTO_SMTP; break; } *proto = (unsigned)x; /* reset the state back again */ pstate->state = 0; /* re-read the stuff that we missed */ for (i=0; patterns[i].id != *proto; i++) ; *banner_offset = 0; banner1_parse( banner1, pstate, proto, (const unsigned char*)patterns[i].pattern, patterns[i].pattern_length, banner, banner_offset, banner_max); banner1_parse( banner1, pstate, proto, px+offset, length-offset, banner, banner_offset, banner_max); } else { size_t len = length; if (len > banner_max - *banner_offset) len = banner_max - *banner_offset; memcpy(banner + *banner_offset, px, len); (*banner_offset) += (unsigned)len; } break; case PROTO_SSH1: case PROTO_SSH2: case PROTO_FTP1: case PROTO_FTP2: banner_ssh.parse( banner1, banner1->http_fields, pstate, px, length, banner, banner_offset, banner_max); break; case PROTO_HTTP: banner_http.parse( banner1, banner1->http_fields, pstate, px, length, banner, banner_offset, banner_max); break; case PROTO_SSL3: banner_ssl.parse( banner1, banner1->http_fields, pstate, px, length, banner, banner_offset, banner_max); break; default: fprintf(stderr, "banner1: internal error\n"); break; } }