const struct token * match_token(const char *word, const struct token *table) { u_int i, match; const char *errstr; const struct token *t = NULL; match = 0; for (i = 0; table[i].type != ENDTOKEN; i++) { switch (table[i].type) { case NOTOKEN: if (word == NULL || strlen(word) == 0) { match++; t = &table[i]; } break; case BRFLAGS: if (parse_brflags(word, &res.flags)) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case FLAGS: if (parse_flags(word, &res.flags)) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case KEYWORD: if (word != NULL && strcmp(word, table[i].keyword) == 0) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case PROTO: if (word != NULL && strcmp(word, table[i].keyword) == 0) { res.proto = word; match++; t = &table[i]; if (t->value) res.action = t->value; } break; case ADDRESS: if (parse_addr(word, &res.addr)) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case HOSTNAME: if (parse_hostname(word, res.hostname)) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case FQDN: if (parse_target_hostname(word, res.hostname)) { match++; t = &table[i]; if (t->value) res.action = t->value; } break; case APPPROTO: if (word != NULL && *word != '-') { res.app = word; match++; t = &table[i]; if (t->value) res.action = t->value; } break; case SRVNAME: /* match anything */ if (word != NULL) { res.srvname = word; match++; t = &table[i]; if (t->value) res.action = t->value; } break; case TXTSTRING: if (word != NULL) { res.txtstring = word; match++; t = &table[i]; if (t->value) res.action = t->value; } break; case PORT: if (word != NULL) { res.port = strtonum(word, 0, UINT16_MAX, &errstr); if (errstr) errx(1, "strtonum: %s", errstr); match++; t = &table[i]; if (t->value) res.action = t->value; } break; case ENDTOKEN: break; } } if (match != 1) { if (word == NULL) fprintf(stderr, "missing argument:\n"); else if (match > 1) fprintf(stderr, "ambiguous argument: %s\n", word); else if (match < 1) fprintf(stderr, "unknown argument: %s\n", word); return (NULL); } return (t); }
int parse_request() { int result = 0; if ( sscanf(request, "%31s %1023s %15s", req.method, req.url, req.http_ver) != 3) { ERR("sscanf() fail", 0); goto end; }; DBG("- method: '%s'", req.method); DBG("- url: '%s'", req.url); DBG("- http_ver: '%s'", req.http_ver); char *headers = strstr(request, "\r\n"); char *end_of_req = strstr(headers, "\r\n\r\n"); if (!end_of_req) { ERR("CRLFCRLF does not found", 0); goto end; } end_of_req[4] = '\0'; // terminate request by 0 char if (headers) { strncpy(req.headers, headers, sizeof(req.headers)-1); DBG("- headers: '%s'", req.headers); } if ( strcmp("CONNECT", req.method) == 0 ) { if (sscanf(req.url, "%s", req.url_host) < 1) { ERR("sscanf() fail", 0); goto end; } req.connect = 1; } else { req.port = 80; if (sscanf(req.url, "%[^:]://%[^/]%[^\r\n]", req.scheme, req.url_host, req.url_path) < 2) { ERR("sscanf() fail", 0); goto end; } } char *colon; if ((colon = strchr(req.url_host, ':'))) { colon++; req.port = atoi(colon); if ( req.port <= 0 ) { ERR("bad port %d", req.port); goto end; } } if (!parse_hostname()) { ERR("parse_hostname() fail", 0); goto end; } result = 1; DBG("- req.scheme: '%s'", req.scheme); DBG("- req.url_host: '%s'", req.url_host); DBG("- req.url_path: '%s'", req.url_path); DBG("- req.port: '%d'", req.port); DBG("- req.hostname: '%s'", req.hostname); end: if (!result) { LOG_HEXDUMP("BAD REQUEST", (unsigned char*)request, strlen(request)+1); } return result; }