head 1.7; access; symbols; locks; strict; comment @ * @; 1.7 date 2006.11.02.17.23.06; author wessels; state Exp; branches; next 1.6; 1.6 date 2006.11.02.17.21.15; author wessels; state Exp; branches; next 1.5; 1.5 date 2006.11.02.17.20.39; author wessels; state Exp; branches; next 1.4; 1.4 date 2002.11.13.20.16.04; author wessels; state Exp; branches; next 1.3; 1.3 date 2002.11.13.19.58.09; author wessels; state Exp; branches; next 1.2; 1.2 date 2002.11.13.18.19.37; author wessels; state Exp; branches; next 1.1; 1.1 date 2000.08.24.04.09.43; author wessels; state Exp; branches; next ; desc @@ 1.7 log @add memory.h to remove compiler warnings @ text @/* $Id: netcount.c,v 1.6 2006/11/02 17:21:15 wessels Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SNAPLEN 68 #define NETCOUNT_PORT 2345 #define INOUT_IN 0 #define INOUT_OUT 1 #define INOUT_ERR 2 #define INDEX_PKTS 0 #define INDEX_BYTES 1 #define INDEX_LOCAL 0 #define INDEX_REMOTE 1 #define MAX_N_ADDRS 10 static struct in_addr my_addr[MAX_N_ADDRS]; static int n_addrs = 0; static int Listen = -1; static unsigned int ethertypes[65536][2]; static unsigned int ipprotos[256][2]; /* portnum bytes,pkts local,remote */ static unsigned int tcpports[65536][2][2]; static unsigned int udpports[65536][2][2]; int (*datalink_handle) (const unsigned char * pkt, int len) = NULL; int find_inout(struct ip *ip) { int i; char p1[128]; char p2[128]; for (i=0; iip_dst.s_addr) return INOUT_IN; if (my_addr[i].s_addr == ip->ip_src.s_addr) return INOUT_OUT; if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) return INOUT_IN; } inet_ntop(AF_INET, &ip->ip_src, p1, sizeof(p1)); inet_ntop(AF_INET, &ip->ip_dst, p2, sizeof(p1)); syslog(LOG_WARNING, "IP packet not to/from here (src %s, dst %s)", p1, p2); return INOUT_ERR; } int ip_handle(const unsigned char * p, int length) { struct ip *ip; unsigned int hlen; unsigned short lport; unsigned short rport; int inout; /* L3 */ if (length < sizeof(*ip)) { syslog(LOG_WARNING, "truncated IP packet (%d)", length); return 0; } ip = (struct ip *) p; ipprotos[ip->ip_p][INDEX_PKTS]++; ipprotos[ip->ip_p][INDEX_BYTES] += length; inout = find_inout(ip); if (INOUT_ERR == inout) return 0; hlen = ip->ip_hl * 4; p += hlen; length -= hlen; if (IPPROTO_TCP == ip->ip_p) { struct tcphdr *tcp; if (length < sizeof(*tcp)) { syslog(LOG_WARNING, "truncated TCP packet (%d)", length); return 0; } tcp = (struct tcphdr *) p; if (INOUT_OUT == inout) { lport = ntohs(tcp->th_sport); rport = ntohs(tcp->th_dport); } else { lport = ntohs(tcp->th_dport); rport = ntohs(tcp->th_sport); } tcpports[lport][INDEX_PKTS][INDEX_LOCAL]++; tcpports[lport][INDEX_BYTES][INDEX_LOCAL] += length; tcpports[rport][INDEX_PKTS][INDEX_REMOTE]++; tcpports[rport][INDEX_BYTES][INDEX_REMOTE] += length; } else if (IPPROTO_UDP == ip->ip_p) { struct udphdr *udp; if (length < sizeof(*udp)) { syslog(LOG_WARNING, "truncated UDP packet (%d)", length); return 0; } udp = (struct udphdr *) p; if (INOUT_OUT == inout) { lport = ntohs(udp->uh_sport); rport = ntohs(udp->uh_dport); } else { lport = ntohs(udp->uh_dport); rport = ntohs(udp->uh_sport); } udpports[lport][INDEX_PKTS][INDEX_LOCAL]++; udpports[lport][INDEX_BYTES][INDEX_LOCAL] += length; udpports[rport][INDEX_PKTS][INDEX_REMOTE]++; udpports[rport][INDEX_BYTES][INDEX_REMOTE] += length; } return 1; } int ether_handle(const unsigned char *p, int length) { const struct ether_header *ep = (struct ether_header *) p; unsigned short ethertype = ntohs(ep->ether_type); /* L2 */ ethertypes[ethertype][INDEX_PKTS]++; ethertypes[ethertype][INDEX_BYTES] += length; if (ETHERTYPE_IP != ethertype) return 0; p += sizeof(*ep); length -= sizeof(*ep); return ip_handle(p, length); } int null_handle(const unsigned char *p, int length) { unsigned int family; memcpy(&family, p, sizeof(family)); if (AF_INET != family) return 0; return ip_handle(p + 4, length - 4); } void packet_handle(unsigned char *user, const struct pcap_pkthdr *h, const unsigned char *p) { if (h->caplen < ETHER_HDR_LEN) return; if (0 == datalink_handle(p, h->caplen)) return; } static void check_connect(void) { unsigned int i; char buf[128]; int s; int flags; int dummy = 0; s = accept(Listen, NULL, NULL); if (s < 0) return; if (fork()) { close(s); return; } if ((flags = fcntl(s, F_GETFL, dummy)) < 0) { syslog(LOG_ERR, "fcntl F_GETFL: %s", strerror(errno)); close(s); _exit(1); } if (fcntl(s, F_SETFL, flags & (~O_NONBLOCK)) < 0) { syslog(LOG_ERR, "fcntl F_SETFL: %s", strerror(errno)); close(s); _exit(1); } for (i = 0; i < 65536; i++) { if (0 == ethertypes[i][INDEX_PKTS]) continue; snprintf(buf, 128, "ethertypes %d %u %u\n", i, ethertypes[i][INDEX_PKTS], ethertypes[i][INDEX_BYTES]); if (write(s, buf, strlen(buf)) < 0) syslog(LOG_ERR, "write: %s", strerror(errno)); } for (i = 0; i < 256; i++) { if (0 == ipprotos[i][INDEX_PKTS]) continue; snprintf(buf, 128, "ipprotos %d %u %u\n", i, ipprotos[i][INDEX_PKTS], ipprotos[i][INDEX_BYTES]); if (write(s, buf, strlen(buf)) < 0) syslog(LOG_ERR, "write: %s", strerror(errno)); } for (i = 0; i < 65536; i++) { if (0 == tcpports[i][INDEX_PKTS][INDEX_LOCAL]) continue; snprintf(buf, 128, "lcl_tcpports %d %u %u\n", i, tcpports[i][INDEX_PKTS][INDEX_LOCAL], tcpports[i][INDEX_BYTES][INDEX_LOCAL]); if (write(s, buf, strlen(buf)) < 0) syslog(LOG_ERR, "write: %s", strerror(errno)); } for (i = 0; i < 65536; i++) { if (0 == tcpports[i][INDEX_PKTS][INDEX_REMOTE]) continue; snprintf(buf, 128, "rem_tcpports %d %u %u\n", i, tcpports[i][INDEX_PKTS][INDEX_REMOTE], tcpports[i][INDEX_BYTES][INDEX_REMOTE]); if (write(s, buf, strlen(buf)) < 0) syslog(LOG_ERR, "write: %s", strerror(errno)); } for (i = 0; i < 65536; i++) { if (0 == udpports[i][INDEX_PKTS][INDEX_LOCAL]) continue; snprintf(buf, 128, "lcl_udpports %d %u %u\n", i, udpports[i][INDEX_PKTS][INDEX_LOCAL], udpports[i][INDEX_BYTES][INDEX_LOCAL]); if (write(s, buf, strlen(buf)) < 0) syslog(LOG_ERR, "write: %s", strerror(errno)); } for (i = 0; i < 65536; i++) { if (0 == udpports[i][INDEX_PKTS][INDEX_REMOTE]) continue; snprintf(buf, 128, "rem_udpports %d %u %u\n", i, udpports[i][INDEX_PKTS][INDEX_REMOTE], udpports[i][INDEX_BYTES][INDEX_REMOTE]); if (write(s, buf, strlen(buf)) < 0) syslog(LOG_ERR, "write: %s", strerror(errno)); } write(s, "EOF\n", 4); close(s); _exit(0); } static int open_server(void) { int s; struct sockaddr_in L; int flags; int dummy; s = socket(PF_INET, SOCK_STREAM, 0); if (s < 0) { syslog(LOG_ERR, "socket: %s", strerror(errno)); return 1; } memset(&L, '\0', sizeof(L)); L.sin_family = AF_INET; L.sin_addr.s_addr = inet_addr("127.0.0.1"); L.sin_port = htons(NETCOUNT_PORT); dummy = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &dummy, sizeof(dummy)); if (bind(s, (struct sockaddr *) &L, sizeof(L)) < 0) syslog(LOG_WARNING, "bind: %s", strerror(errno)); if ((flags = fcntl(s, F_GETFL, dummy)) < 0) { syslog(LOG_ERR, "fcntl F_GETFL: %s", strerror(errno)); close(s); return -1; } if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { syslog(LOG_ERR, "fcntl F_SETFL: %s", strerror(errno)); close(s); return -1; } listen(s, 1); return s; } void reap(int sig) { int status; pid_t p; while ((p = waitpid(-1, &status, WNOHANG)) > 0); signal(SIGCHLD, reap); } int main(int argc, char *argv[]) { struct bpf_program bpf; pcap_t *pc; char errmsg[PCAP_ERRBUF_SIZE]; char *dev; unsigned int netmask; unsigned int localnet; pid_t pid; int i; if (3 > argc) { fprintf(stderr, "usage: %s device local_ip_addr\n", argv[0]); return 1; } dev = strdup(argv[1]); for (i = 2; i 0) exit(0); if (setsid() < 0) syslog(LOG_ERR, "setsid failed: %s", strerror(errno)); signal(SIGCHLD, reap); Listen = open_server(); pc = pcap_open_live(dev, SNAPLEN, 0, 1000, errmsg); if (NULL == pc) { syslog(LOG_ERR, "%s: %s", dev, errmsg); return 1; } if (pcap_lookupnet(dev, &localnet, &netmask, errmsg) < 0) { localnet = 0; netmask = 0; syslog(LOG_WARNING, "%s", errmsg); } setuid(getuid()); pcap_compile(pc, &bpf, 0, 1, netmask); if (pcap_setfilter(pc, &bpf) < 0) { syslog(LOG_ERR, "%s", pcap_geterr(pc)); return 1; } syslog(LOG_CRIT, "netcount starting"); switch (pcap_datalink(pc)) { case DLT_EN10MB: datalink_handle = ether_handle; break; case DLT_NULL: datalink_handle = null_handle; break; default: fprintf(stderr, "unsupported data link type %d\n", pcap_datalink(pc)); return 1; break; } while (1) { if (pcap_dispatch(pc, 0, packet_handle, NULL) < 0) { syslog(LOG_ERR, "pcap_dispatch: %s", pcap_geterr(pc)); break; } check_connect(); } pcap_close(pc); syslog(LOG_CRIT, "netcount exiting"); return 0; } @ 1.6 log @- make find_inout() understand multicast packets - remove newlines from syslog messages - remove handle_fddi() @ text @d1 1 a1 1 /* $Id$ */ d8 1 @ 1.5 log @some random fixes @ text @d1 2 a19 1 #include d60 2 d67 2 d70 3 a72 1 syslog(LOG_WARNING, "IP packet not to/from here\n"); d86 1 a86 1 syslog(LOG_WARNING, "truncated IP packet (%d)\n", length); d102 1 a102 1 syslog(LOG_WARNING, "truncated TCP packet (%d)\n", length); d120 1 a120 1 syslog(LOG_WARNING, "truncated UDP packet (%d)\n", length); a154 31 fddi_handle(const unsigned char *p, int length) { const struct fddi_header *fddip = (const struct fddi_header *) p; const struct llc *llc; if (length < sizeof(*fddip)) return 0; p += sizeof(*fddip); length -= sizeof(*fddip); if (length < sizeof(*llc)) return 0; llc = (struct llc *) p; if (llc->llc_dsap != LLC_SNAP_LSAP) { syslog(LOG_ERR, "fddi packet llc_dsap != LLC_SNAP_LSAP"); return 0; } if (llc->llc_ssap != LLC_SNAP_LSAP) { syslog(LOG_ERR, "fddi packet llc_ssap != LLC_SNAP_LSAP (%x)", (int)llc->llc_ssap); return 0; } if (llc->llc_un.type_snap.control != LLC_UI) { syslog(LOG_ERR, "fddi packet llc_un.type_snap.control != LLC_UI"); return 0; } p += sizeof(*llc); length -= sizeof(*llc); return ip_handle(p, length); } int d189 1 a189 1 syslog(LOG_ERR, "fcntl F_GETFL: %s\n", strerror(errno)); d194 1 a194 1 syslog(LOG_ERR, "fcntl F_SETFL: %s\n", strerror(errno)); d204 1 a204 1 syslog(LOG_ERR, "write: %s\n", strerror(errno)); d212 1 a212 1 syslog(LOG_ERR, "write: %s\n", strerror(errno)); d222 1 a222 1 syslog(LOG_ERR, "write: %s\n", strerror(errno)); d232 1 a232 1 syslog(LOG_ERR, "write: %s\n", strerror(errno)); d242 1 a242 1 syslog(LOG_ERR, "write: %s\n", strerror(errno)); d252 1 a252 1 syslog(LOG_ERR, "write: %s\n", strerror(errno)); d269 1 a269 1 syslog(LOG_ERR, "socket: %s\n", strerror(errno)); d279 1 a279 1 syslog(LOG_WARNING, "bind: %s\n", strerror(errno)); d281 1 a281 1 syslog(LOG_ERR, "fcntl F_GETFL: %s\n", strerror(errno)); d286 1 a286 1 syslog(LOG_ERR, "fcntl F_SETFL: %s\n", strerror(errno)); d326 1 a326 1 syslog(LOG_ERR, "fork failed: %s\n", strerror(errno)); d330 1 a330 1 syslog(LOG_ERR, "setsid failed: %s\n", strerror(errno)); d335 1 a335 1 syslog(LOG_ERR, "%s: %s\n", dev, errmsg); d349 1 a349 1 syslog(LOG_CRIT, "netcount starting\n"); a357 3 case DLT_FDDI: datalink_handle = fddi_handle; break; d368 1 a368 1 syslog(LOG_ERR, "pcap_dispatch: %s\n", pcap_geterr(pc)); d374 1 a374 1 syslog(LOG_CRIT, "netcount exiting\n"); @ 1.4 log @apply local/remote feature from squid @ text @d36 1 d42 4 a45 1 static struct in_addr my_addr; d56 14 d76 1 a76 1 int inout = INOUT_IN; d85 2 a86 6 if (my_addr.s_addr == ip->ip_dst.s_addr) inout = INOUT_IN; else if (my_addr.s_addr == ip->ip_src.s_addr) inout = INOUT_OUT; else { syslog(LOG_WARNING, "IP packet not to/from here\n"); a87 1 } d337 2 a338 1 if (3 != argc) { d343 5 a347 1 my_addr.s_addr = inet_addr(argv[2]); @ 1.3 log @add FDDI support @ text @d34 7 d45 3 a47 2 static unsigned int tcpports[65536][2]; static unsigned int udpports[65536][2]; a54 1 int inout; d56 3 a58 1 unsigned short port; d65 2 a66 2 ipprotos[ip->ip_p][0]++; ipprotos[ip->ip_p][1] += length; d68 1 a68 1 inout = 0; d70 1 a70 1 inout = 1; d86 11 a96 6 if (inout) port = ntohs(tcp->th_sport); else port = ntohs(tcp->th_dport); tcpports[port][0]++; tcpports[port][1] += length; d104 11 a114 6 if (inout) port = ntohs(udp->uh_sport); else port = ntohs(udp->uh_dport); udpports[port][0]++; udpports[port][1] += length; d125 2 a126 2 ethertypes[ethertype][0]++; ethertypes[ethertype][1] += length; d191 1 a191 1 int dummy; d210 1 a210 1 if (0 == ethertypes[i][0]) d213 1 a213 1 i, ethertypes[i][0], ethertypes[i][1]); d218 1 a218 1 if (0 == ipprotos[i][0]) d221 1 a221 1 i, ipprotos[i][0], ipprotos[i][1]); d225 1 d227 1 a227 1 if (0 == tcpports[i][0]) d229 3 a231 2 snprintf(buf, 128, "tcpports %d %u %u\n", i, tcpports[i][0], tcpports[i][1]); d235 1 d237 1 a237 1 if (0 == udpports[i][0]) d239 3 a241 2 snprintf(buf, 128, "udpports %d %u %u\n", i, udpports[i][0], udpports[i][1]); d245 21 @ 1.2 log @don't assume ETHER link layer @ text @d18 2 d116 31 d320 3 @ 1.1 log @Initial revision @ text @d39 4 a42 2 void packet_handle(unsigned char *user, const struct pcap_pkthdr *h, const unsigned char *p) a43 3 unsigned int length = h->len; const struct ether_header *ep = (struct ether_header *) p; unsigned short ethertype = ntohs(ep->ether_type); d45 1 a47 10 int inout; /* L2 */ ethertypes[ethertype][0]++; ethertypes[ethertype][1] += length; if (ETHERTYPE_IP != ethertype) return; p += sizeof(*ep); length -= sizeof(*ep); d51 1 a51 1 return; d62 1 a62 1 return; d72 1 a72 1 return; d85 1 a85 1 return; d95 35 d279 16 @