/* * restrict_source - maintains dynamic "restrict source ..." entries as * peers come and go. */ void restrict_source( sockaddr_u * addr, int farewell, /* 0 to add, 1 to remove */ u_long expire /* 0 is infinite, valid until */ ) { sockaddr_u onesmask; restrict_u * res; int found_specific; if (!restrict_source_enabled || SOCK_UNSPEC(addr) || IS_MCAST(addr) || ISREFCLOCKADR(addr)) return; REQUIRE(AF_INET == AF(addr) || AF_INET6 == AF(addr)); SET_HOSTMASK(&onesmask, AF(addr)); if (farewell) { hack_restrict(RESTRICT_REMOVE, addr, &onesmask, 0, 0, 0); DPRINTF(1, ("restrict_source: %s removed", stoa(addr))); return; } /* * If there is a specific entry for this address, hands * off, as it is condidered more specific than "restrict * server ...". * However, if the specific entry found is a fleeting one * added by pool_xmit() before soliciting, replace it * immediately regardless of the expire value to make way * for the more persistent entry. */ if (IS_IPV4(addr)) { res = match_restrict4_addr(SRCADR(addr), SRCPORT(addr)); INSIST(res != NULL); found_specific = (SRCADR(&onesmask) == res->u.v4.mask); } else { res = match_restrict6_addr(&SOCK_ADDR6(addr), SRCPORT(addr)); INSIST(res != NULL); found_specific = ADDR6_EQ(&res->u.v6.mask, &SOCK_ADDR6(&onesmask)); } if (!expire && found_specific && res->expire) { found_specific = 0; free_res(res, IS_IPV6(addr)); } if (found_specific) return; hack_restrict(RESTRICT_FLAGS, addr, &onesmask, restrict_source_mflags, restrict_source_flags, expire); DPRINTF(1, ("restrict_source: %s host restriction added\n", stoa(addr))); }
/* * restrictions - return restrictions for this host */ u_short restrictions( sockaddr_u *srcadr ) { restrict_u *match; struct in6_addr *pin6; u_short flags; res_calls++; flags = 0; /* IPv4 source address */ if (IS_IPV4(srcadr)) { /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * not later!) */ if (IN_CLASSD(SRCADR(srcadr))) return (int)RES_IGNORE; match = match_restrict4_addr(SRCADR(srcadr), SRCPORT(srcadr)); match->count++; /* * res_not_found counts only use of the final default * entry, not any "restrict default ntpport ...", which * would be just before the final default. */ if (&restrict_def4 == match) res_not_found++; else res_found++; flags = match->flags; } /* IPv6 source address */ if (IS_IPV6(srcadr)) { pin6 = PSOCK_ADDR6(srcadr); /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * not later!) */ if (IN6_IS_ADDR_MULTICAST(pin6)) return (int)RES_IGNORE; match = match_restrict6_addr(pin6, SRCPORT(srcadr)); match->count++; if (&restrict_def6 == match) res_not_found++; else res_found++; flags = match->flags; } return (flags); }
const char * sockporttoa( const sockaddr_u *sock ) { int saved_errno; const char * atext; char * buf; saved_errno = errno; atext = socktoa(sock); LIB_GETBUF(buf); snprintf(buf, LIB_BUFLENGTH, (IS_IPV6(sock)) ? "[%s]:%hu" : "%s:%hu", atext, SRCPORT(sock)); errno = saved_errno; return buf; }
/* Receive data from broadcast. Couldn't finish that. Need to do some digging * here, especially for protocol independence and IPv6 multicast */ int recv_bcst_data ( SOCKET rsock, char *rdata, int rdata_len, sockaddr_u *sas, sockaddr_u *ras ) { char *buf; int btrue = 1; int recv_bytes = 0; int rdy_socks; GETSOCKNAME_SOCKLEN_TYPE ss_len; struct timeval timeout_tv; fd_set bcst_fd; #ifdef MCAST struct ip_mreq mdevadr; TYPEOF_IP_MULTICAST_LOOP mtrue = 1; #endif #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT struct ipv6_mreq mdevadr6; #endif setsockopt(rsock, SOL_SOCKET, SO_REUSEADDR, &btrue, sizeof(btrue)); if (IS_IPV4(sas)) { if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: Couldn't bind() address %s:%d.\n", stoa(sas), SRCPORT(sas)); } #ifdef MCAST if (setsockopt(rsock, IPPROTO_IP, IP_MULTICAST_LOOP, &mtrue, sizeof(mtrue)) < 0) { /* some error message regarding setting up multicast loop */ return BROADCAST_FAILED; } mdevadr.imr_multiaddr.s_addr = NSRCADR(sas); mdevadr.imr_interface.s_addr = htonl(INADDR_ANY); if (mdevadr.imr_multiaddr.s_addr == ~(unsigned)0) { if (ENABLED_OPT(NORMALVERBOSE)) { printf("sntp recv_bcst_data: %s:%d is not a broad-/multicast address, aborting...\n", stoa(sas), SRCPORT(sas)); } return BROADCAST_FAILED; } if (setsockopt(rsock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mdevadr, sizeof(mdevadr)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: Couldn't add IP membership for %s\n", buf); free(buf); } } #endif /* MCAST */ } #ifdef ISC_PLATFORM_HAVEIPV6 else if (IS_IPV6(sas)) { if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: Couldn't bind() address.\n"); } #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (setsockopt(rsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &btrue, sizeof (btrue)) < 0) { /* some error message regarding setting up multicast loop */ return BROADCAST_FAILED; } memset(&mdevadr6, 0, sizeof(mdevadr6)); mdevadr6.ipv6mr_multiaddr = SOCK_ADDR6(sas); if (!IN6_IS_ADDR_MULTICAST(&mdevadr6.ipv6mr_multiaddr)) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: %s is not a broad-/multicast address, aborting...\n", buf); free(buf); } return BROADCAST_FAILED; } if (setsockopt(rsock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mdevadr6, sizeof(mdevadr6)) < 0) { if (ENABLED_OPT(NORMALVERBOSE)) { buf = ss_to_str(sas); printf("sntp recv_bcst_data: Couldn't join group for %s\n", buf); free(buf); } } #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ } #endif /* ISC_PLATFORM_HAVEIPV6 */ FD_ZERO(&bcst_fd); FD_SET(rsock, &bcst_fd); if (ENABLED_OPT(TIMEOUT)) timeout_tv.tv_sec = (int) atol(OPT_ARG(TIMEOUT)); else timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */ timeout_tv.tv_usec = 0; rdy_socks = select(rsock + 1, &bcst_fd, 0, 0, &timeout_tv); switch (rdy_socks) { case -1: if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recv_bcst_data: select()"); return BROADCAST_FAILED; break; case 0: if (ENABLED_OPT(NORMALVERBOSE)) printf("sntp recv_bcst_data: select() reached timeout (%u sec), aborting.\n", (unsigned)timeout_tv.tv_sec); return BROADCAST_FAILED; break; default: ss_len = sizeof(*ras); recv_bytes = recvfrom(rsock, rdata, rdata_len, 0, &ras->sa, &ss_len); break; } if (recv_bytes == -1) { if (ENABLED_OPT(NORMALVERBOSE)) perror("sntp recv_bcst_data: recvfrom:"); recv_bytes = BROADCAST_FAILED; } #ifdef MCAST if (IS_IPV4(sas)) setsockopt(rsock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &btrue, sizeof(btrue)); #endif #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (IS_IPV6(sas)) setsockopt(rsock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &btrue, sizeof(btrue)); #endif return recv_bytes; }
/* * restrictions - return restrictions for this host */ int restrictions( struct sockaddr_storage *srcadr, int at_listhead ) { struct restrictlist *rl; struct restrictlist *match = NULL; struct restrictlist6 *rl6; struct restrictlist6 *match6 = NULL; struct in6_addr hostaddr6; struct in6_addr hostservaddr6; u_int32 hostaddr; int flags = 0; int isntpport; res_calls++; if (srcadr->ss_family == AF_INET) { /* * We need the host address in host order. Also need to * know whether this is from the ntp port or not. */ hostaddr = SRCADR(srcadr); isntpport = (SRCPORT(srcadr) == NTP_PORT); /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * later!) */ if (IN_CLASSD(SRCADR(srcadr))) return (int)RES_IGNORE; /* * Set match to first entry, which is default entry. * Work our way down from there. */ match = restrictlist; for (rl = match->next; rl != NULL && rl->addr <= hostaddr; rl = rl->next) if ((hostaddr & rl->mask) == rl->addr) { if ((rl->mflags & RESM_NTPONLY) && !isntpport) continue; match = rl; } match->count++; if (match == restrictlist) res_not_found++; else res_found++; flags = match->flags; } /* IPv6 source address */ if (srcadr->ss_family == AF_INET6) { /* * Need to know whether this is from the ntp port or * not. */ hostaddr6 = GET_INADDR6(*srcadr); isntpport = (ntohs(( (struct sockaddr_in6 *)srcadr)->sin6_port) == NTP_PORT); /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * later!) */ if (IN6_IS_ADDR_MULTICAST(&hostaddr6)) return (int)RES_IGNORE; /* * Set match to first entry, which is default entry. * Work our way down from there. */ match6 = restrictlist6; for (rl6 = match6->next; rl6 != NULL && (memcmp(&(rl6->addr6), &hostaddr6, sizeof(hostaddr6)) <= 0); rl6 = rl6->next) { SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6, &rl6->mask6); if (memcmp(&hostservaddr6, &(rl6->addr6), sizeof(hostservaddr6)) == 0) { if ((rl6->mflags & RESM_NTPONLY) && !isntpport) continue; match6 = rl6; } } match6->count++; if (match6 == restrictlist6) res_not_found++; else res_found++; flags = match6->flags; } /* * The following implements a generalized call gap facility. * Douse the RES_LIMITED bit only if the interval since the last * packet is greater than res_min_interval and the average is * greater thatn res_avg_interval. */ if (!at_listhead || mon_enabled == MON_OFF) { flags &= ~RES_LIMITED; } else { struct mon_data *md; /* * At this poin the most recent arrival is first in the * MRU list. Let the first 10 packets in for free until * the average stabilizes. */ md = mon_mru_list.mru_next; if (md->avg_interval == 0) md->avg_interval = md->drop_count; else md->avg_interval += (md->drop_count - md->avg_interval) / RES_AVG; if (md->count < 10 || (md->drop_count > res_min_interval && md->avg_interval > res_avg_interval)) flags &= ~RES_LIMITED; md->drop_count = flags; } return (flags); }
/* * restrictions - return restrictions for this host */ int restrictions( struct sockaddr_in *srcadr ) { register struct restrictlist *rl; register struct restrictlist *match; register u_int32 hostaddr; register int isntpport; res_calls++; /* * We need the host address in host order. Also need to know * whether this is from the ntp port or not. */ hostaddr = SRCADR(srcadr); isntpport = (SRCPORT(srcadr) == NTP_PORT); /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, later!) */ if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr))) return (int)RES_IGNORE; /* * Set match to first entry, which is default entry. Work our * way down from there. */ match = restrictlist; for (rl = match->next; rl != 0 && rl->addr <= hostaddr; rl = rl->next) if ((hostaddr & rl->mask) == rl->addr) { if ((rl->mflags & RESM_NTPONLY) && !isntpport) continue; match = rl; } match->count++; if (match == restrictlist) res_not_found++; else res_found++; /* * The following implements limiting the number of clients * accepted from a given network. The notion of "same network" * is determined by the mask and addr fields of the restrict * list entry. The monitor mechanism has to be enabled for * collecting info on current clients. * * The policy is as follows: * - take the list of clients recorded * from the given "network" seen within the last * client_limit_period seconds * - if there are at most client_limit entries: * --> access allowed * - otherwise sort by time first seen * - current client among the first client_limit seen * hosts? * if yes: access allowed * else: eccess denied */ if (match->flags & RES_LIMITED) { int lcnt; struct mon_data *md, *this_client; #ifdef DEBUG if (debug > 2) printf("limited clients check: %ld clients, period %ld seconds, net is 0x%lX\n", client_limit, client_limit_period, (u_long)netof(hostaddr)); #endif /*DEBUG*/ if (mon_enabled == MON_OFF) { #ifdef DEBUG if (debug > 4) printf("no limit - monitoring is off\n"); #endif return (int)(match->flags & ~RES_LIMITED); } /* * How nice, MRU list provides our current client as the * first entry in the list. * Monitoring was verified to be active above, thus we * know an entry for our client must exist, or some * brain dead set the memory limit for mon entries to ZERO!!! */ this_client = mon_mru_list.mru_next; for (md = mon_fifo_list.fifo_next,lcnt = 0; md != &mon_fifo_list; md = md->fifo_next) { if ((current_time - md->lasttime) > client_limit_period) { #ifdef DEBUG if (debug > 5) printf("checking: %s: ignore: too old: %ld\n", numtoa(md->rmtadr), current_time - md->lasttime); #endif continue; } if (md->mode == MODE_BROADCAST || md->mode == MODE_CONTROL || md->mode == MODE_PRIVATE) { #ifdef DEBUG if (debug > 5) printf("checking: %s: ignore mode %d\n", numtoa(md->rmtadr), md->mode); #endif continue; } if (netof(md->rmtadr) != netof(hostaddr)) { #ifdef DEBUG if (debug > 5) printf("checking: %s: different net 0x%lX\n", numtoa(md->rmtadr), (u_long)netof(md->rmtadr)); #endif continue; } lcnt++; if (lcnt > (int) client_limit || md->rmtadr == hostaddr) { #ifdef DEBUG if (debug > 5) printf("considering %s: found host\n", numtoa(md->rmtadr)); #endif break; } #ifdef DEBUG else { if (debug > 5) printf("considering %s: same net\n", numtoa(md->rmtadr)); } #endif } #ifdef DEBUG if (debug > 4) printf("this one is rank %d in list, limit is %lu: %s\n", lcnt, client_limit, (lcnt <= (int) client_limit) ? "ALLOW" : "REJECT"); #endif if (lcnt <= (int) client_limit) { this_client->lastdrop = 0; return (int)(match->flags & ~RES_LIMITED); } else { this_client->lastdrop = current_time; } } return (int)match->flags; }
/* * restrictions - return restrictions for this host in *r4a */ void restrictions( sockaddr_u *srcadr, r4addr *r4a ) { restrict_u *match; struct in6_addr *pin6; REQUIRE(NULL != r4a); res_calls++; r4a->rflags = RES_IGNORE; r4a->ippeerlimit = 0; DPRINTF(1, ("restrictions: looking up %s\n", stoa(srcadr))); /* IPv4 source address */ if (IS_IPV4(srcadr)) { /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * not later!) */ if (IN_CLASSD(SRCADR(srcadr))) { DPRINTF(1, ("restrictions: srcadr %s is multicast\n", stoa(srcadr))); r4a->ippeerlimit = 2; /* XXX: we should use a better value */ return; } match = match_restrict4_addr(SRCADR(srcadr), SRCPORT(srcadr)); INSIST(match != NULL); match->count++; /* * res_not_found counts only use of the final default * entry, not any "restrict default ntpport ...", which * would be just before the final default. */ if (&restrict_def4 == match) res_not_found++; else res_found++; r4a->rflags = match->rflags; r4a->ippeerlimit = match->ippeerlimit; } /* IPv6 source address */ if (IS_IPV6(srcadr)) { pin6 = PSOCK_ADDR6(srcadr); /* * Ignore any packets with a multicast source address * (this should be done early in the receive process, * not later!) */ if (IN6_IS_ADDR_MULTICAST(pin6)) return; match = match_restrict6_addr(pin6, SRCPORT(srcadr)); INSIST(match != NULL); match->count++; if (&restrict_def6 == match) res_not_found++; else res_found++; r4a->rflags = match->rflags; r4a->ippeerlimit = match->ippeerlimit; } return; }
/* * Write captured packet to file * * uint8_t *flag : filter is set or not * const uint8_t *packet : captured packet * char *fltrload : filter for payload * cosnt int payloadlen : length of captured payload */ static void printfile(uint8_t *flag, const uint8_t *packet, char *fltrload, const int payloadlen) { FILE *fp = fopen(LOGFILE, "a"); const uint8_t *http = NULL; char *timestamp; struct ether_header *eth; struct ip *iphdr; struct tcphdr *tcphdr; struct udphdr *udphdr; uint8_t prot; int hdrlen, i; flag += 2; // remove unused member eth = (struct ether_header *)packet; hdrlen = sizeof(struct ether_header); iphdr = (struct ip *)(packet + hdrlen); hdrlen += sizeof(struct ip); prot = iphdr->ip_p; if( prot == 17 ) { udphdr = (struct udphdr *)(packet + hdrlen); hdrlen += sizeof(struct udphdr); }else { tcphdr = (struct tcphdr *)(packet + hdrlen); hdrlen += sizeof(struct tcphdr); // HTTP request check if( PROTOCOL(flag) ) { if( prot == 3 ) { if( HTTPTEST("GET",3) == false ) return; }else if( prot == 5 ) { if( HTTPTEST("PUT",3) == false ) return; }else if(prot == 7) { if( HTTPTEST("POST",4) == false ) return; } } } // Timestamp timestamp = (char *)gettime(); fprintf(fp, "%s ------\n", timestamp); free(timestamp); /* Ethernet Header */ i = 0; if( DSTMAC(flag) ) { fprintf(fp, "\x1b[45mDestination MAC\x1b[0m\t: \x1b[45m"); while( i < 5 ) fprintf(fp, "%02X:", eth->ether_dhost[i++]); fprintf(fp, "%02X\x1b[0m\n", eth->ether_dhost[i]); }else { fprintf(fp, "Destination MAC\t: "); while( i < 5 ) fprintf(fp, "%02X:", eth->ether_dhost[i++]); fprintf(fp, "%02X\n", eth->ether_dhost[i]); } i = 0; if( SRCMAC(flag) ) { fprintf(fp, "\x1b[45mSource MAC\x1b[0m\t: \x1b[45m"); while( i < 5 ) fprintf(fp, "%02X:", eth->ether_shost[i++]); fprintf(fp, "%02X\x1b[0m\n", eth->ether_shost[i]); }else { fprintf(fp, "Source MAC\t: "); while( i < 5 ) fprintf(fp, "%02X:", eth->ether_shost[i++]); fprintf(fp, "%02X\n", eth->ether_shost[i]); } if( ETHERTYPE(flag) ) fprintf(fp, "\x1b[45mEthernet Type\x1b[0m\t: \x1b[45m%s\x1b[0m\n", gettype(eth->ether_type)); else fprintf(fp, "Ethernet Type\t: %s\n", gettype(eth->ether_type)); /* IP Header */ if( VERSION(flag) & 0xf0 ) fprintf(fp, "\x1b[44mVersion\x1b[0m\t\t: \x1b[44m%d\x1b[0m\n", iphdr->ip_v); else fprintf(fp, "Version\t\t: %d\n", iphdr->ip_v); if( IPHLEN(flag) & 0x0f ) fprintf(fp, "\x1b[44mIP Header length\x1b[0m: \x1b[44m%d\x1b[0m\n", iphdr->ip_hl); else fprintf(fp, "IP Header length: %d\n", iphdr->ip_hl); if( TOS(flag) ) fprintf(fp, "\x1b[44mType of Service\x1b[0m\t: \x1b[44m%s\x1b[0m\n", gettos(iphdr->ip_tos)); else fprintf(fp, "Type of Service\t: %s\n", gettos(iphdr->ip_tos)); if( IPLEN(flag) ) fprintf(fp, "\x1b[44mTotal length\x1b[0m\t: \x1b[44m%d\x1b[0m\n", ntohs(iphdr->ip_len)); else fprintf(fp, "Total length\t: %d\n", ntohs(iphdr->ip_len)); if( IPID(flag) ) fprintf(fp, "\x1b[44mIdentification\x1b[0m\t: \x1b[44m%d\x1b[0m\n", ntohs(iphdr->ip_id)); else fprintf(fp, "Identification\t: %d\n", ntohs(iphdr->ip_id)); if( FRAGMENT(flag) ) fprintf(fp, "\x1b[44mFragment\x1b[0m\t: \x1b[44m%d\x1b[0m\n", iphdr->ip_off); else fprintf(fp, "Fragment\t: %d\n", iphdr->ip_off); if( TTL(flag) ) fprintf(fp, "\x1b[44mTime to live\x1b[0m\t: \x1b[44m%d\x1b[0m\n", iphdr->ip_ttl); else fprintf(fp, "Time to live\t: %d\n", iphdr->ip_ttl); if( PROTOCOL(flag) ) fprintf(fp, "\x1b[44mProtocol\x1b[0m\t: \x1b[44m%s\x1b[0m\n", getprot(iphdr->ip_p)); else fprintf(fp, "Protocol\t: %s\n", getprot(iphdr->ip_p)); if( IPCKSUM(flag) ) fprintf(fp, "\x1b[44mChecksum\x1b[0m\t: \x1b[44m%d\x1b[0m\n", ntohs(iphdr->ip_sum)); else fprintf(fp, "Checksum\t: %d\n", ntohs(iphdr->ip_sum)); if( SRCIP(flag) ) fprintf(fp, "\x1b[44mSource IP\x1b[0m\t: \x1b[44m%s\x1b[0m\n", inet_ntoa(iphdr->ip_src)); else fprintf(fp, "Source IP\t: %s\n", inet_ntoa(iphdr->ip_src)); if( DSTIP(flag) ) fprintf(fp, "\x1b[44mDestination IP\x1b[0m\t: \x1b[44m%s\x1b[0m\n", inet_ntoa(iphdr->ip_dst)); else fprintf(fp, "Destination IP\t: %s\n", inet_ntoa(iphdr->ip_dst)); if( iphdr->ip_p == 17 ) { /* UDP Header */ if( SRCPORT(flag) ) fprintf(fp, "\x1b[42mSource Port\x1b[0m\t: \x1b[42m%d\x1b[0m\n", ntohs(udphdr->source)); else fprintf(fp, "Source Port\t: %d\n", ntohs(udphdr->source)); if( DSTPORT(flag) ) fprintf(fp, "\x1b[42mDestination Port\x1b[0m: \x1b[42m%d\x1b[0m\n", ntohs(udphdr->dest)); else fprintf(fp, "Destination Port: %d\n", ntohs(udphdr->dest)); if( UDPLEN(flag) ) fprintf(fp, "\x1b[42mTotal length\x1b[0m\t: \x1b[42m%d\x1b[0m\n", ntohs(udphdr->len)); else fprintf(fp, "Total length\t: %d\n", ntohs(udphdr->len)); if( UDPCKSUM(flag) ) fprintf(fp, "\x1b[42mCheckSum\x1b[0m\t: \x1b[42m%d\x1b[0m\n", ntohs(udphdr->check)); else fprintf(fp, "Checksum\t: %d\n", ntohs(udphdr->check)); }else { /* TCP Header */ if( SRCPORT(flag) ) fprintf(fp, "\x1b[31;43mSource Port\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->source)); else fprintf(fp, "Source Port\t: %d\n", ntohs(tcphdr->source)); if( DSTPORT(flag) ) fprintf(fp, "\x1b[31;43mDestination Port\x1b[0m: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->dest)); else fprintf(fp, "Destination Port: %d\n", ntohs(tcphdr->dest)); if( SEQ(flag) ) fprintf(fp, "\x1b[31;43mSequence Number\x1b[0m\t: \x1b[31;43m%u\x1b[0m\n", ntohl(tcphdr->seq)); else fprintf(fp, "Sequence Number\t: %u\n", ntohl(tcphdr->seq)); if( ACK(flag) ) fprintf(fp, "\x1b[31;43mAcknowledgement\x1b[0m\t: \x1b[31;43m%u\x1b[0m\n", ntohl(tcphdr->ack)); else fprintf(fp, "Acknowledgement\t: %u\n", ntohl(tcphdr->ack)); if( TCPOFF(flag) & 0x0f ) fprintf(fp, "\x1b[31;43mOffset\x1b[0m\t\t: \x1b[31;43m%d\x1b[0m\n", tcphdr->doff); else fprintf(fp, "Offset\t\t: %d\n", tcphdr->doff); if( TCPRES(flag) & 0xf0 ) fprintf(fp, "\x1b[31;43mReserved\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", tcphdr->res1); else fprintf(fp, "Reserved\t: %d\n", tcphdr->res1); char *tmp = getflag(*(packet + 47), tcphdr->res1, tcphdr->res2); if( TCPFLAG(flag) ) fprintf(fp, "\x1b[31;43mFlags\x1b[0m\t\t: \x1b[31;43m%s\x1b[0m\n", tmp); else fprintf(fp, "Flags\t\t: %s\n", tmp); free(tmp); if( WINDOW(flag) ) fprintf(fp, "\x1b[31;43mWindow size\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->window)); else fprintf(fp, "Window size\t: %d\n", ntohs(tcphdr->window)); if( TCPCKSUM(flag) ) fprintf(fp, "\x1b[31;43mChecksum\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->check)); else fprintf(fp, "Checksum\t: %d\n", ntohs(tcphdr->check)); if( URGPTR(flag) ) fprintf(fp, "\x1b[31;43mUrgent Pointer\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->urg_ptr)); else fprintf(fp, "Urgent Pointer\t: %d\n", ntohs(tcphdr->urg_ptr)); } /* Payload */ if( fltrload != NULL ) { const uint8_t *match = NULL; uint8_t highlight[MAXPAYLOAD]; int fltrloadlen, unmatchlen = 0; int colorhex = 0, colorstr = 0; int i = 0, str = 0, colorlen = 0, highlen = 0; char ch; memset(highlight, 0, MAXPAYLOAD); packet += hdrlen; fltrloadlen = strlen(fltrload); fprintf(fp, "*** Payload ***\n"); if( http != NULL ) { if( prot == 3 ) { memcpy(highlight, HTTPCOLOR, 5); memcpy(highlight + 5, "GET\x1b[0m", 7); highlen += 12; i += 3; }else if( prot == 5 ) { memcpy(highlight, HTTPCOLOR, 5); memcpy(highlight + 5, "PUT\x1b[0m", 7); highlen += 12; i += 3; }else if( prot == 7 ) { memcpy(highlight, HTTPCOLOR, 5); memcpy(highlight + 5, "POST\x1b[0m", 8); highlen += 13; i += 4; } } while( i < payloadlen ) { // move to next matching string match = memcmp_cont(packet + i, fltrload, fltrloadlen, payloadlen - i); if( match == NULL ) { unmatchlen = payloadlen - i; memcpy(highlight + highlen, packet + i, unmatchlen); highlen += unmatchlen; break; }else { if( http != NULL && match - packet > http - packet ) { // HTTP/1.1 unmatchlen = http - (packet + i); memcpy(highlight + highlen, packet + i, unmatchlen); highlen += unmatchlen; i += unmatchlen; memcpy(highlight + highlen, "\x1b[46mHTTP/1.1\x1b[0m", 17); highlen += 17; i += 8; http = NULL; }else { unmatchlen = match - (packet + i); memcpy(highlight + highlen, packet + i, unmatchlen); highlen += unmatchlen; i += unmatchlen; memcpy(highlight + highlen, PAYLOADCOLOR, 5); highlen += 5; memcpy(highlight + highlen, packet + i, fltrloadlen); highlen += fltrloadlen; i += fltrloadlen; memcpy(highlight + highlen, NORMALCOLOR, 4); highlen += 4; } } } i = 0; while( i < highlen ) { ch = *(highlight + i); if( ch == '\x1b' ) { if( COLORTEST(i, PAYLOADCOLOR) == true ) { fprintf(fp, PAYLOADCOLOR); colorhex = 41; i += 5; colorlen += 5; continue; }else if( COLORTEST(i, HTTPCOLOR) == true ) { fprintf(fp, HTTPCOLOR); colorhex = 46; i += 5; colorlen += 5; continue; }else if( COLORTEST(i, NORMALCOLOR) == true ) { fprintf(fp, NORMALCOLOR); colorhex = 0; i += 4; colorlen += 4; continue; } } fprintf(fp, "%02X ", ch); i++; if( ++str == 16 ) { if( colorhex != 0 ) fprintf(fp, NORMALCOLOR); fprintf(fp, " "); if( colorstr == 41 ) { fprintf(fp, PAYLOADCOLOR); colorstr = 0; }else if( colorstr == 46 ) { fprintf(fp, HTTPCOLOR); colorstr = 0; } while( colorlen > 0 ) { ch = *(highlight + i - colorlen - str); if( ch > 126 || ch < 32 ) { if( ch == 27 ) { if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true ) colorstr = 41; else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true ) colorstr = 46; else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true ) colorstr = 0; else ch = '.'; }else ch = '.'; } fprintf(fp, "%c", ch); colorlen--; } while( str > 0 ) { ch = *(highlight + i - str); if( ch > 126 || ch < 32 ) { if( ch == 27 ) { if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true ) colorstr = 41; else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true ) colorstr = 46; else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true ) colorstr = 0; else ch = '.'; }else ch = '.'; } fprintf(fp, "%c", ch); str--; } if( colorstr != 0 ) fprintf(fp, NORMALCOLOR); fprintf(fp, "\n"); if( colorhex == 41 ) { fprintf(fp, PAYLOADCOLOR); colorhex = 0; }else if( colorhex == 46 ) { fprintf(fp, HTTPCOLOR); colorhex = 0; } } } if( str != 0 ) { int padd = 17; if( colorhex != 0 ) fprintf(fp, NORMALCOLOR); while( str < padd-- ) fprintf(fp, " "); if( colorstr == 41 ) { fprintf(fp, PAYLOADCOLOR); colorstr = 0; }else if( colorstr == 46 ) { fprintf(fp, HTTPCOLOR); colorstr = 0; } while( colorlen > 0 ) { ch = *(highlight + i - colorlen - str); if( ch > 126 || ch < 32 ) { if( ch == 27 ) { if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true ) colorstr = 41; else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true ) colorstr = 46; else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true ) colorstr = 0; else ch = '.'; }else ch = '.'; } fprintf(fp, "%c", ch); colorlen--; } while( str > 0 ) { ch = *(highlight + i - str); if( ch > 126 || ch < 32 ) { if( ch == 27 ) { if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true ) colorstr = 41; else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true ) colorstr = 46; else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true ) colorstr = 0; else ch = '.'; }else ch = '.'; } fprintf(fp, "%c", ch); str--; } fprintf(fp, "\x1b[0m\n"); } }else { // fltrload == NULL uint8_t highlight[MAXPAYLOAD]; int unmatchlen = 0; int colorhex = 0, colorstr = 0; int i = 0, str = 0, colorlen = 0, highlen = 0; char ch; memset(highlight, 0, MAXPAYLOAD); packet += hdrlen; fprintf(fp, "*** Payload ***\n"); if( http != NULL ) { if( prot == 3 ) { memcpy(highlight, HTTPCOLOR, 5); memcpy(highlight + 5, "GET\x1b[0m", 7); highlen += 12; i += 3; }else if( prot == 5 ) { memcpy(highlight, HTTPCOLOR, 5); memcpy(highlight + 5, "PUT\x1b[0m", 7); highlen += 12; i += 3; }else if( prot == 7 ) { memcpy(highlight, HTTPCOLOR, 5); memcpy(highlight + 5, "POST\x1b[0m", 8); highlen += 13; i += 4; } } while( i < payloadlen ) { // move to next matching string if( http != NULL ) { // HTTP/1.1 unmatchlen = http - (packet + i); memcpy(highlight + highlen, packet + i, unmatchlen); highlen += unmatchlen; i += unmatchlen; memcpy(highlight + highlen, "\x1b[46mHTTP/1.1\x1b[0m", 17); highlen += 17; i += 8; http = NULL; }else { memcpy(highlight + highlen, packet + i, payloadlen - i); highlen += unmatchlen; i += unmatchlen; } } i = 0; while( i < highlen ) { ch = *(highlight + i); if( ch == '\x1b' ) { if( COLORTEST(i, PAYLOADCOLOR) == true ) { fprintf(fp, PAYLOADCOLOR); colorhex = 41; i += 5; colorlen += 5; continue; }else if( COLORTEST(i, HTTPCOLOR) == true ) { fprintf(fp, HTTPCOLOR); colorhex = 46; i += 5; colorlen += 5; continue; }else if( COLORTEST(i, NORMALCOLOR) == true ) { fprintf(fp, NORMALCOLOR); colorhex = 0; i += 4; colorlen += 4; continue; } } fprintf(fp, "%02X ", ch); i++; if( ++str == 16 ) { if( colorhex != 0 ) fprintf(fp, NORMALCOLOR); fprintf(fp, " "); if( colorstr == 41 ) { fprintf(fp, PAYLOADCOLOR); colorstr = 0; }else if( colorstr == 46 ) { fprintf(fp, HTTPCOLOR); colorstr = 0; } while( colorlen > 0 ) { ch = *(highlight + i - colorlen - str); if( ch > 126 || ch < 32 ) { if( ch == 27 ) { if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true ) colorstr = 41; else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true ) colorstr = 46; else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true ) colorstr = 0; else ch = '.'; }else ch = '.'; } fprintf(fp, "%c", ch); colorlen--; } while( str > 0 ) { ch = *(highlight + i - str); if( ch > 126 || ch < 32 ) { if( ch == 27 ) { if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true ) colorstr = 41; else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true ) colorstr = 46; else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true ) colorstr = 0; else ch = '.'; }else ch = '.'; } fprintf(fp, "%c", ch); str--; } if( colorstr != 0 ) fprintf(fp, NORMALCOLOR); fprintf(fp, "\n"); if( colorhex == 41 ) { fprintf(fp, PAYLOADCOLOR); colorhex = 0; }else if( colorhex == 46 ) { fprintf(fp, HTTPCOLOR); colorhex = 0; } } } if( str != 0 ) { int padd = 17; if( colorhex != 0 ) fprintf(fp, NORMALCOLOR); while( str < padd-- ) fprintf(fp, " "); if( colorstr == 41 ) { fprintf(fp, PAYLOADCOLOR); colorstr = 0; }else if( colorstr == 46 ) { fprintf(fp, HTTPCOLOR); colorstr = 0; } while( colorlen > 0 ) { ch = *(highlight + i - colorlen - str); if( ch > 126 || ch < 32 ) { if( ch == 27 ) { if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true ) colorstr = 41; else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true ) colorstr = 46; else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true ) colorstr = 0; else ch = '.'; }else ch = '.'; } fprintf(fp, "%c", ch); colorlen--; } while( str > 0 ) { ch = *(highlight + i - str); if( ch > 126 || ch < 32 ) { if( ch == 27 ) { if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true ) colorstr = 41; else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true ) colorstr = 46; else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true ) colorstr = 0; else ch = '.'; }else ch = '.'; } fprintf(fp, "%c", ch); str--; } fprintf(fp, "\x1b[0m\n"); } } fprintf(fp, "----------------------------\n"); fclose(fp); }