int connection_tracking(packetinfo *pi) { struct in6_addr *ip_src; struct in6_addr *ip_dst; struct in6_addr ips; struct in6_addr ipd; uint16_t src_port = pi->s_port; uint16_t dst_port = pi->d_port; int af = pi->af; connection *cxt = NULL; connection *head = NULL; uint32_t hash; if(af == AF_INET6){ ip_src = &PI_IP6SRC(pi); ip_dst = &PI_IP6DST(pi); } else { ips.s6_addr32[0] = pi->ip4->ip_src; ipd.s6_addr32[0] = pi->ip4->ip_dst; ip_src = &ips; ip_dst = &ipd; } /* Find the right connection bucket */ if (af == AF_INET) { hash = CXT_HASH4(IP4ADDR(ip_src), IP4ADDR(ip_dst), src_port, dst_port, pi->proto); } else if (af == AF_INET6) { hash = CXT_HASH6(ip_src, ip_dst, src_port, dst_port, pi->proto); } else { dlog("[D] Only CTX with AF_INET and AF_INET6 are supported: %d\n", af); return 0; } cxt = bucket[hash]; head = cxt; /* Search through the bucket */ while (cxt != NULL) { /* Two-way compare of given connection against connection table */ if (af == AF_INET) { if (CMP_CXT4(cxt, IP4ADDR(ip_src), src_port, IP4ADDR(ip_dst), dst_port)) { /* Client sends first packet (TCP/SYN - UDP?) hence this is a client */ dlog("[D] Found existing v4 client connection.\n"); return cxt_update_client(cxt, pi); } else if (CMP_CXT4(cxt, IP4ADDR(ip_dst), dst_port, IP4ADDR(ip_src), src_port)) { if (pi->sc == SC_SERVER) { /* This is a server */ dlog("[D] Found existing v4 server connection.\n"); return cxt_update_server(cxt, pi); } else { /* This is a client, where we saw a mid-stream DNS response first */ dlog("[D] Found existing unknown v4 server connection.\n"); return cxt_update_client(cxt, pi); } } } else if (af == AF_INET6) { if (CMP_CXT6(cxt, ip_src, src_port, ip_dst, dst_port)) { dlog("[D] Found existing v6 client connection.\n"); return cxt_update_client(cxt, pi); } else if (CMP_CXT6(cxt, ip_dst, dst_port, ip_src, src_port)) { dlog("[D] Found existing v6 client connection.\n"); return cxt_update_server(cxt, pi); } } cxt = cxt->next; } /* Bucket turned upside down didn't yield anything. New connection */ dlog("[D] New connection.\n"); cxt = cxt_new(pi); /* New connections are pushed on to the head of bucket[s_hash] */ cxt->next = head; if (head != NULL) { /* Are we double linked? */ head->prev = cxt; } bucket[hash] = cxt; pi->cxt = cxt; return cxt_update_unknown(cxt, pi); }
int cx_track(packetinfo *pi) { struct in6_addr *ip_src; struct in6_addr *ip_dst; struct in6_addr ips; struct in6_addr ipd; uint16_t src_port = pi->s_port; uint16_t dst_port = pi->d_port; int af = pi->af; connection *cxt = NULL; connection *head = NULL; uint32_t hash; if(af== AF_INET6){ ip_src = &PI_IP6SRC(pi); ip_dst = &PI_IP6DST(pi); }else { // ugly hack :( // the way we do ip4/6 is DIRTY // FIX IT?!!? ips.s6_addr32[0] = pi->ip4->ip_src; ipd.s6_addr32[0] = pi->ip4->ip_dst; ip_src = &ips; ip_dst = &ipd; } // find the right connection bucket if (af == AF_INET) { hash = CXT_HASH4(IP4ADDR(ip_src),IP4ADDR(ip_dst)); } else if (af == AF_INET6) { hash = CXT_HASH6(ip_src,ip_dst); } cxt = bucket[hash]; head = cxt; // search through the bucket while (cxt != NULL) { // Two-way compare of given connection against connection table if (af == AF_INET) { if (CMP_CXT4(cxt,IP4ADDR(ip_src),src_port,IP4ADDR(ip_dst),dst_port)){ // Client sends first packet (TCP/SYN - UDP?) hence this is a client return cxt_update_client(cxt, pi); } else if (CMP_CXT4(cxt,IP4ADDR(ip_dst),dst_port,IP4ADDR(ip_src),src_port)) { // This is a server (Maybe not when we start up but in the long run) return cxt_update_server(cxt, pi); } } else if (af == AF_INET6) { if (CMP_CXT6(cxt,ip_src,src_port,ip_dst,dst_port)){ return cxt_update_client(cxt, pi); } else if (CMP_CXT6(cxt,ip_dst,dst_port,ip_src,src_port)){ return cxt_update_server(cxt, pi); } } cxt = cxt->next; } // bucket turned upside down didn't yeild anything. new connection cxt = cxt_new(pi); if(config.cflags & CONFIG_CXWRITE) log_connection(cxt, stdout, CX_NEW); /* * New connections are pushed on to the head of bucket[s_hash] */ cxt->next = head; if (head != NULL) { // are we doubly linked? head->prev = cxt; } bucket[hash] = cxt; pi->cxt = cxt; /* * Return value should be 1, telling to do client service fingerprinting */ return 1; }
int connection_tracking(packetinfo *pi) { struct in6_addr *ip_src; struct in6_addr *ip_dst; struct in6_addr ips; struct in6_addr ipd; uint16_t src_port = pi->s_port; uint16_t dst_port = pi->d_port; int af = pi->af; connection *cxt = NULL; connection *head = NULL; uint32_t hash; if(af== AF_INET6){ ip_src = &PI_IP6SRC(pi); ip_dst = &PI_IP6DST(pi); }else { ips.s6_addr32[0] = pi->ip4->ip_src; ipd.s6_addr32[0] = pi->ip4->ip_dst; ip_src = &ips; ip_dst = &ipd; } // find the right connection bucket if (af == AF_INET) { hash = CXT_HASH4(IP4ADDR(ip_src),IP4ADDR(ip_dst),src_port,dst_port,pi->proto); } else if (af == AF_INET6) { hash = CXT_HASH6(ip_src,ip_dst,src_port,dst_port,pi->proto); } cxt = bucket[hash]; head = cxt; // search through the bucket while (cxt != NULL) { // Two-way compare of given connection against connection table if (af == AF_INET) { if (CMP_CXT4(cxt,IP4ADDR(ip_src),src_port,IP4ADDR(ip_dst),dst_port)){ // Client sends first packet (TCP/SYN - UDP?) hence this is a client return cxt_update_client(cxt, pi); } else if (CMP_CXT4(cxt,IP4ADDR(ip_dst),dst_port,IP4ADDR(ip_src),src_port)) { // This is a server (Maybe not when we start up but in the long run) return cxt_update_server(cxt, pi); } } else if (af == AF_INET6) { if (CMP_CXT6(cxt,ip_src,src_port,ip_dst,dst_port)){ return cxt_update_client(cxt, pi); } else if (CMP_CXT6(cxt,ip_dst,dst_port,ip_src,src_port)){ return cxt_update_server(cxt, pi); } } cxt = cxt->next; } // bucket turned upside down didn't yeild anything. new connection cxt = cxt_new(pi); /* New connections are pushed on to the head of bucket[s_hash] */ cxt->next = head; if (head != NULL) { // are we doubly linked? head->prev = cxt; } bucket[hash] = cxt; pi->cxt = cxt; return cxt_update_client(cxt, pi); }
inline void cxt_update (packetinfo *pi, uint32_t hash) { connection *cxt = NULL; int ret = 0; /* get our hash bucket and lock it */ cxtbucket *cb = &cxt_hash[hash]; /* see if the bucket already has a connection */ if (cb->cxt == NULL) { /* no, so get a new one */ cxt = cb->cxt = cxt_dequeue(&cxt_spare_q); if (cxt == NULL) { cxt = cb->cxt = connection_alloc(); if (cxt == NULL) { return; } } /* these are protected by the bucket lock */ cxt->hnext = NULL; cxt->hprev = NULL; /* got one, initialize and return */ cxt_new(cxt,pi); cxt_requeue(cxt, NULL, &cxt_est_q); cxt->cb = cb; cxt_update_src(cxt, pi); pi->cxt = cxt; return; } /* ok, we have a flow in the bucket. Let's find out if it is our flow */ cxt = cb->cxt; /* see if this is the flow we are looking for */ if (pi->af == AF_INET) { if (CMP_CXT4(cxt, PI_IP4SRC(pi), pi->s_port, PI_IP4DST(pi), pi->d_port)) { cxt_update_src(cxt, pi); ret = 1; } else if (CMP_CXT4(cxt, PI_IP4DST(pi), pi->d_port, PI_IP4SRC(pi), pi->s_port)) { cxt_update_dst(cxt, pi); ret = 1; } } else if (pi->af == AF_INET6){ if (CMP_CXT6(cxt, &PI_IP6SRC(pi), pi->s_port, &PI_IP6DST(pi), pi->d_port)) { cxt_update_src(cxt, pi); ret = 1; } else if (CMP_CXT6(cxt, &PI_IP6DST(pi), pi->d_port, &PI_IP6SRC(pi), pi->s_port)) { cxt_update_dst(cxt, pi); ret = 1; } } if (ret == 0) { connection *pcxt = NULL; /* previous connection */ while (cxt != NULL) { pcxt = cxt; /* pf is not locked at this point */ cxt = cxt->hnext; if (cxt == NULL) { /* get us a new one and put it and the list tail */ cxt = pcxt->hnext = cxt_dequeue(&cxt_spare_q); if (cxt == NULL) { cxt = cb->cxt = connection_alloc(); if (cxt == NULL) { return; } } cxt->hnext = NULL; cxt->hprev = pcxt; /* initialize and return */ cxt_new(cxt,pi); cxt_requeue(cxt, NULL, &cxt_est_q); cxt->cb = cb; cxt_update_src(cxt, pi); pi->cxt = cxt; return; } if (pi->af == AF_INET) { if (CMP_CXT4(cxt, PI_IP4SRC(pi), pi->s_port, PI_IP4DST(pi), pi->d_port)) { cxt_update_src(cxt, pi); ret = 1; } else if (CMP_CXT4(cxt, PI_IP4DST(pi), pi->d_port, PI_IP4SRC(pi), pi->s_port)) { cxt_update_dst(cxt, pi); ret = 1; } } else if (pi->af == AF_INET6) { if (CMP_CXT6(cxt, &PI_IP6SRC(pi), pi->s_port, &PI_IP6DST(pi), pi->d_port)) { cxt_update_src(cxt, pi); ret = 1; } else if (CMP_CXT6(cxt, &PI_IP6DST(pi), pi->d_port, &PI_IP6SRC(pi), pi->s_port)) { cxt_update_dst(cxt, pi); ret = 1; } } if ( ret != 0) { /* we found our flow, lets put it on top of the * hash list -- this rewards active flows */ if (cxt->hnext) cxt->hnext->hprev = cxt->hprev; if (cxt->hprev) cxt->hprev->hnext = cxt->hnext; cxt->hnext = cb->cxt; cxt->hprev = NULL; cb->cxt->hprev = cxt; cb->cxt = cxt; /* found our connection */ pi->cxt = cxt; return; } /* not found, try the next... */ } } pi->cxt = cxt; /* The 'root' connection was our connection, return it. */ return; }