summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Fankhauser hiddenalpha.ch2023-09-08 15:39:54 +0200
committerAndreas Fankhauser hiddenalpha.ch2023-09-08 15:39:54 +0200
commit7ebf105a444aba301476ae34677075b25f14523f (patch)
tree6f0fa2d3c8b902a9f76c49c05c3dc44b83253eea
parent850ecbddaf846c2bc19920ab9c37377b63418fc1 (diff)
downloadUnspecifiedGarbage-7ebf105a444aba301476ae34677075b25f14523f.zip
UnspecifiedGarbage-7ebf105a444aba301476ae34677075b25f14523f.tar.gz
(pcap) Add simplified copy of Pcapit from CeeMiscLib.
-rw-r--r--configure11
-rw-r--r--src/main/c/PcapOne/PcapOne.c302
2 files changed, 313 insertions, 0 deletions
diff --git a/configure b/configure
index 500e8ba..f59f7af 100644
--- a/configure
+++ b/configure
@@ -66,6 +66,16 @@ printTarget_Asn1Digger () {
}
+printTarget_PcapOne () {
+ printf '\n'
+ printf 'build/bin/pcap-one$(BINEXT):\n'
+ printf 'build/bin/pcap-one$(BINEXT): src/main/c/PcapOne/PcapOne.c\n'
+ printf ' @echo " LN $@"\n'
+ printf ' @$(MKDIR_P) build/bin\n'
+ printf ' @$(CC) -o $@ $(CFLAGS) $^ $(INCDIRS)\n'
+}
+
+
main () {
(
printMakefileHdr
@@ -73,6 +83,7 @@ main () {
printTarget_link
printTarget_PemCodec
printTarget_Asn1Digger
+ printTarget_PcapOne
) > "${MF:?}"
}
diff --git a/src/main/c/PcapOne/PcapOne.c b/src/main/c/PcapOne/PcapOne.c
new file mode 100644
index 0000000..634d01c
--- /dev/null
+++ b/src/main/c/PcapOne/PcapOne.c
@@ -0,0 +1,302 @@
+/* TODO fix this bullshit */
+typedef unsigned u_int;
+typedef unsigned short u_short;
+typedef unsigned char u_char;
+#include <pcap/pcap.h>
+/* endOf TODO */
+
+
+/* System */
+#include <assert.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+static char const*const DEV_STDIN = "/dev/stdin";
+
+#define FLG_isHelp (1<<0)
+#define FLG_isTcpPsh (1<<3)
+#define FLG_isTcpRst (1<<4)
+#define FLG_isTcpSyn (1<<5)
+#define FLG_isTcpFin (1<<6)
+#define FLG_isHttpReq (1<<7)
+#define FLG_isLlLinux (1<<12)
+#define FLG_INIT (0)
+
+typedef struct PcapOne PcapOne;
+
+
+struct PcapOne {
+ uint_least16_t flg;
+ char *dumpFilePath;
+ char *pcapErrbuf;
+ pcap_t *pcap;
+ unsigned long frameNr;
+ struct/*most recent frame*/{
+ int_fast32_t llProto;
+ int llHdrEnd;
+ };
+ struct/*most recent packet*/{
+ int_fast16_t netProto;
+ int netBodyLen;
+ int netHdrEnd;
+ int_fast32_t netTotLen;
+ uint_least32_t ipSrcAddr, ipDstAddr;
+ };
+ struct/*most recent segment*/{
+ int trspBodyLen;
+ int_fast32_t trspSrcPort, trspDstPort;
+ int trspHdrEnd;
+ };
+ struct/*most recent http requst*/{
+ const char *httpReqHeadline;
+ int httpReqHeadline_len;
+ int httpReq_off; /* pkg offset from begin of most recent request */
+ };
+};
+
+
+/*BEG func fwd decl*/
+static void parse_ll_LINUX_SLL( PcapOne*, const struct pcap_pkthdr*, const u_char* );
+static void parse_net_IPv4( PcapOne*, const struct pcap_pkthdr*, const u_char* );
+static void parse_trsp_TCP( PcapOne*, const struct pcap_pkthdr*, const u_char* );
+static void parse_appl_HTTP_req( PcapOne*, const struct pcap_pkthdr*, const u_char* );
+static void printParsingResults( PcapOne* );
+/*END func fwd decl*/
+
+static void printHelp(){
+ #define STRQUOT_21a9ffbe344c0792ed88688d6c676359(s) #s
+ #define STRQUOT(s) STRQUOT_21a9ffbe344c0792ed88688d6c676359(s)
+ const char *basename = "/"__FILE__ + sizeof("/"__FILE__);
+ for(; basename[-1] != '/'; --basename );
+ printf("%s%s%s", " \n"
+ " ", basename, " " STRQUOT(PROJECT_VERSION) "\n"
+ " \n"
+ " Options:\n"
+ " \n"
+ " --pcap-stdin\n"
+ " Like --pcap but reading from stdin.\n"
+ " \n"
+ " --pcap <path>\n"
+ " Pcap file to operate on. Compressed files are NOT supported.\n"
+ " \n");
+ #undef STRQUOT_21a9ffbe344c0792ed88688d6c676359
+ #undef STRQUOT
+}
+
+
+static int parseArgs( PcapOne*app, int argc, char**argv ){
+ app->flg = FLG_INIT;
+ app->dumpFilePath = NULL;
+ for( int iA = 1 ; iA < argc ; ++iA ){
+ const char *arg = argv[iA];
+ if(0){
+ }else if( !strcmp(arg,"--help") ){
+ app->flg |= FLG_isHelp; return 0;
+ }else if( !strcmp(arg,"--pcap") ){
+ arg = argv[++iA];
+ if( arg == NULL ){ fprintf(stderr, "EINVAL --pcap needs value\n"); return -1; }
+ app->dumpFilePath = arg;
+ }else if( !strcmp(arg,"--pcap-stdin") ){
+ app->dumpFilePath = DEV_STDIN;
+ }else{
+ fprintf(stderr, "EINVAL: %s\n", arg); return -1;
+ }
+ }
+ if( app->dumpFilePath == NULL ){
+ fprintf(stderr, "EINVAL Arg missing: --pcap <path>\n"); return -1; }
+ return 0;
+}
+
+
+static void onPcapPkg( u_char*user, const struct pcap_pkthdr*hdr, const u_char*buf ){
+ int err;
+ PcapOne *const app = (void*)user;
+
+ /* prepare for this new packet */
+ app->frameNr += 1;
+ app->flg &= ~(FLG_isTcpPsh | FLG_isTcpRst | FLG_isTcpSyn | FLG_isTcpFin | FLG_isHttpReq);
+
+ /* data-link layer */
+ switch( pcap_datalink(app->pcap) ){
+ case 0x71: parse_ll_LINUX_SLL(app, hdr, buf); break;
+ default: assert(!fprintf(stderr,"pcap_datalink() -> 0x%02X\n", pcap_datalink(app->pcap)));
+ }
+
+ /* network layer */
+ switch( app->llProto ){
+ case 0x0800: parse_net_IPv4(app, hdr, buf); break;
+ default: printf("???, proto=0x%04X, network-layer\n", app->llProto); return;
+ }
+
+ /* transport layer */
+ switch( app->netProto ){
+ case 0x06: parse_trsp_TCP(app, hdr, buf); break;
+ default: printf("???, proto=0x%02X, transport-layer\n", app->netProto); return;
+ }
+
+ assert(app->trspBodyLen >= 0);
+
+ /* application layer, towards server */
+ switch( app->trspDstPort ){
+ case 80: parse_appl_HTTP_req(app, hdr, buf); break;
+ case 7012: parse_appl_HTTP_req(app, hdr, buf); break;
+ case 8080: parse_appl_HTTP_req(app, hdr, buf); break;
+ }
+
+ printParsingResults(app);
+}
+
+
+static void parse_ll_LINUX_SLL( PcapOne*app, const struct pcap_pkthdr*hdr, const u_char*buf ){
+ assert(hdr->caplen >= 15);
+ app->llProto = buf[14]<<8 | buf[15];
+ app->llHdrEnd = 16;
+}
+
+
+static void parse_net_IPv4( PcapOne*app, const struct pcap_pkthdr*hdr, const u_char*buf ){
+ assert(hdr->caplen >= app->llHdrEnd+19 && "TODO_775afde7f19010220e9df8d5e2924c3e");
+ int_fast8_t netHdrLen = (buf[app->llHdrEnd+0] & 0x0F) * 4;
+ app->netTotLen = buf[app->llHdrEnd+2] << 8 | buf[app->llHdrEnd+3];
+ app->netProto = buf[app->llHdrEnd+9];
+ app->ipSrcAddr = 0
+ | ((uint_least32_t)buf[app->llHdrEnd+12]) << 24
+ | ((uint_least32_t)buf[app->llHdrEnd+13]) << 16
+ | buf[app->llHdrEnd+14] << 8
+ | buf[app->llHdrEnd+15] ;
+ app->ipDstAddr = 0
+ | ((uint_least32_t)buf[app->llHdrEnd+16]) << 24
+ | ((uint_least32_t)buf[app->llHdrEnd+17]) << 16
+ | buf[app->llHdrEnd+18] << 8
+ | buf[app->llHdrEnd+19] ;
+ app->netHdrEnd = app->llHdrEnd + netHdrLen;
+ app->netBodyLen = app->netTotLen - netHdrLen;
+}
+
+
+static void parse_trsp_TCP( PcapOne*app, const struct pcap_pkthdr*hdr, const u_char*buf ){
+ assert(hdr->caplen >= app->netHdrEnd+12 && "TODO_058d5f41043d383e1ba2c492d0db4b6a");
+ app->trspSrcPort = buf[app->netHdrEnd+0] << 8 | buf[app->netHdrEnd+1];
+ app->trspDstPort = buf[app->netHdrEnd+2] << 8 | buf[app->netHdrEnd+3];
+ int tcpHdrLen = (buf[app->netHdrEnd+12] >> 4) * 4;
+ app->trspHdrEnd = app->netHdrEnd + tcpHdrLen;
+ app->trspBodyLen = app->netBodyLen - tcpHdrLen;
+}
+
+
+static void parse_appl_HTTP_req( PcapOne*app, const struct pcap_pkthdr*hdr, const u_char*buf ){
+ app->flg |= FLG_isHttpReq;
+ app->httpReqHeadline = buf + app->trspHdrEnd;
+ app->httpReqHeadline_len = 0;
+ for(;; ++app->httpReqHeadline_len ){
+ if( (app->trspHdrEnd + app->httpReqHeadline_len) > hdr->caplen ) break;
+ if( app->httpReqHeadline[app->httpReqHeadline_len] == '\r' ) break;
+ if( app->httpReqHeadline[app->httpReqHeadline_len] == '\n' ) break;
+ }
+ /* TODO improve, as now its like a guess only */
+ int isNewRequest = 0
+ | !memcmp(buf + app->trspHdrEnd, "GET ", 4)
+ | !memcmp(buf + app->trspHdrEnd, "PUT ", 4)
+ | !memcmp(buf + app->trspHdrEnd, "POST ", 5)
+ | !memcmp(buf + app->trspHdrEnd, "DELETE ", 7)
+ ;
+ if( isNewRequest ){
+ app->httpReq_off = 0;
+ }else{
+ app->httpReq_off = 42; /*TODO make more accurate*/
+ }
+}
+
+
+static void printParsingResults( PcapOne*app ){
+ int err;
+
+ int isHttpRequest = (app->flg & FLG_isHttpReq);
+ int isHttpReqBegin = isHttpRequest && app->httpReq_off == 0;
+
+ if( isHttpRequest && isHttpReqBegin ){
+ /* find http method */
+ const char *method = app->httpReqHeadline;
+ int method_len = 0;
+ for(;; ++method_len ){
+ if( method_len > app->httpReqHeadline_len ) break;
+ if( method[method_len] == ' ' ) break;
+ }
+ /* find http uri */
+ const char *uri = method + method_len + 1;
+ int uri_len = 0;
+ for(;; ++uri_len ){
+ if( method_len + uri_len > app->httpReqHeadline_len ) break;
+ if( uri[uri_len] == ' ' ) break;
+ }
+ /* print it as a quick-n-dirty CSV record */
+ printf("r;HTTP req;%.*s;%.*s\n", method_len, method, uri_len, uri);
+ }
+}
+
+
+static int run( PcapOne*app ){
+ int err;
+ err = pcap_init(PCAP_CHAR_ENC_UTF_8, app->pcapErrbuf);
+ if( err == PCAP_ERROR ){
+ fprintf(stderr, "libpcap: %s\n", app->pcapErrbuf); err = -1; goto endFn; }
+ app->pcap = pcap_open_offline(
+ (app->dumpFilePath == DEV_STDIN) ? "-" : app->dumpFilePath,
+ app->pcapErrbuf);
+ if( app->pcap == NULL ){
+ fprintf(stderr, "libpcap: %s\n", app->pcapErrbuf); err = -1; goto endFn; }
+ for(;;){
+ err = pcap_dispatch(app->pcap, -1, onPcapPkg, (void*)app);
+ switch( err ){
+ case PCAP_ERROR:
+ fprintf(stderr, "pcap_dispatch(): %s\n", pcap_geterr(app->pcap));
+ err = -1; goto endFn;
+ case PCAP_ERROR_BREAK:
+ case PCAP_ERROR_NOT_ACTIVATED:
+ fprintf(stderr, "pcap_dispatch() -> %d\n", err);
+ err = -1; goto endFn;
+ }
+ if( err > 0 ){
+ fprintf(stderr, "Processed %d packages in this turn.\n", err);
+ continue;
+ }
+ break;
+ }
+ err = 0;
+endFn:
+ if( app->pcap != NULL ){ pcap_close(app->pcap); app->pcap = NULL; }
+ return err;
+}
+
+
+int main( int argc, char**argv ){
+ int err;
+ static char errbuf[PCAP_ERRBUF_SIZE];
+ errbuf[0] = '\0';
+ PcapOne app = {
+ .flg = FLG_INIT,
+ .pcapErrbuf = errbuf,
+ .pcap = NULL,
+ .frameNr = 0,
+ .trspBodyLen = 0,
+ };
+ #define app (&app)
+
+ err = parseArgs(app, argc, argv);
+ if( err ){ goto endFn; }
+
+ if( app->flg & FLG_isHelp ){
+ printHelp(); goto endFn; }
+
+ err = run(app);
+
+endFn:
+ if( err < 0 ) err = -err;
+ if( err > 0x7F ) err = 1;
+ return err;
+ #undef app
+}
+
+