+++ /dev/null
-/*
- * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- * ziffy.c - a promiscuous Z39.50 APDU sniffer for Ethernet
- *
- * Copyright (c) 1998-2001 R. Carbone <rocco@ntop.org>
- * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-
-/*
- * Operating System include files
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-
-#include <time.h>
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <sys/utsname.h>
-
-#include <yaz/options.h>
-
-#include "pcap.h" /* Packet Capture Library */
-
-#include "apdu.h"
-
-
-/*
- * external
- */
-z3950apdu * pduhook (const struct pcap_pkthdr * h, const u_char * p);
-
-
-#if defined(HAVE_XASN1)
-void please_finsiel_help_me (z3950apdu * hook);
-#endif /* HAVE_XASN1 */
-
-#if defined(HAVE_YAZ)
-void please_yaz_help_me (z3950apdu * hook);
-#endif /* HAVE_YAZ */
-
-#if defined(HAVE_SNACC)
-void please_snacc_help_me (z3950apdu * hook);
-#endif /* HAVE_SNACC */
-
-
-/*
- * global variables
- */
-time_t now; /* current time */
-time_t start_time; /* time the program was started */
-time_t firstapdu_time; /* time the first APDU was received */
-time_t laststapdu_time; /* time the last APDU was received */
-
-unsigned long int z3950_apduno = 0; /* # of z3950 apdus so far received */
-u_char * z3950 = NULL; /* pointer to the last apdu received */
-int z3950_size = 0; /* and its size */
-
-/*
- * I currently tested the program at home in a null networked environment
- * and on ethernet 10M lan. the following variable keeps the data-link
- * encapsulation type. more info in net/bpf.h
- */
-int dlt = -1;
-
-int aflag = 0; /* attempt to convert numeric network addresses to FQDN */
-
-int ethflag = 0;
-int ipflag = 0;
-int tcpflag = 0;
-int z3950flag = 0;
-
-
-/*
- * Length of saved portion of packet
- */
-#define DEFAULT_SNAPLEN 65536 /* This should be enough... */
-static int snaplen = DEFAULT_SNAPLEN;
-
-#define DEFAULT_MAXAPDUS -1 /* that means indefinite */
-static int maxapdus = DEFAULT_MAXAPDUS;
-
-/*
- * A handler for pcap, it needs to be global because there is no other way to
- * pass it to the signal handler, the same can be said about the file descriptor
- * for SOCK_PACKET.
- */
-pcap_t * ph = NULL;
-
-
-/*
- * package info
- */
-static char __copyright__ [] = "Copyright (c) 1998-2001";
-static char __author__ [] = "R. Carbone <rocco@ntop.org>";
-static char __version__ [] = "Version 0.0.3";
-static char __released__ [] = "June 2001";
-
-
-char ebuf [PCAP_ERRBUF_SIZE] = {0};
-struct pcap_stat pcapstats = {0};
-
-/*
- * signal handler
- */
-void on_signal (int signo)
-{
- /*
- * time for statistics
- */
- if (pcap_stats (ph, & pcapstats) != 0)
- {
- printf ("Cannot get the statistics due to %s\n", ebuf),
- exit (-1);
- }
- else
- {
- printf ("\n\n");
-
- printf ("%u packets received by decoder\n", pcapstats . ps_recv);
- printf ("%u packets dropped by kernel\n", pcapstats . ps_drop);
- }
-
- fflush (stdout);
-
- /*
- * bye bye !
- */
- pcap_close (ph);
-
- exit (0);
-}
-
-
-
-/*
- * You are welcome!
- */
-void welcome (char * progname)
-{
- time_t now = ((time_t) time ((time_t *) 0));
- char * nowstring = ctime (& now);
- struct utsname machine;
-
- nowstring [24] = '\0';
- uname (& machine);
-
- printf ("This is %s %s of %s\n", progname, __version__, __released__);
- printf ("%s %s\n", __copyright__, __author__);
- printf ("Started at %s on %s\n\n", nowstring, machine . nodename);
- printf ("\n");
- fflush (stdout);
- fflush (stderr);
-}
-
-
-/*
- * Wrong. Please try again accordingly to ....
- */
-void usage (char * progname)
-{
- welcome (progname);
-
- printf ("Usage: %s [--help] [--version]\n\n", progname);
- printf ("Options:\n");
- printf (" h, --help display this help and exit\n");
- printf (" v, --version output version information and exit\n");
-
- printf (" , -- print filter code\n");
- printf (" , -- print ethernet header\n");
- printf (" , -- try to resolve ip addresses\n");
- printf (" , -- remove domains from printed host names\n");
- printf (" , -- don't translate _foreign_ IP address\n");
- printf (" , -- print packet arrival time\n");
-
- printf (" s, --snaplen \n");
- printf (" N, --non-promiscuous capture APDUs addressed to the host machine\n");
- printf (" C, --maxcount capture maxcount APDUs and then terminate\n");
-
- printf (" D, --dropped-packets display number of packets dropped during capture\n");
- fflush (stdout);
-}
-
-
-/*
- * This is really the `main' function of the sniffer.
- *
- * Parse the incoming APDU, and when possible show all pertinent data.
- *
- * 'h' is the pointer to the packet header (independent from interfaces)
- * 'p' is the pointer to the packet data
- * 'caplen' is the number of bytes actually captured
- * 'length' is the length of the packet off the wire
- */
-void parse_pdu (u_char * user_data,
- const struct pcap_pkthdr * h,
- const u_char * p)
-{
- z3950apdu * hook;
- int done = 0;
-
- if (! (hook = pduhook (h, p)))
- return;
-
- /*
- * update the descriptor of the apdu
- */
- hook -> t = & h -> ts;
- hook -> calling = srchost ();
- hook -> srcport = srcport ();
- hook -> called = dsthost ();
- hook -> dstport = dstport ();
-
-#if defined(HAVE_XASN1)
- if (! done)
- please_finsiel_help_me (hook);
- done = 1;
-#endif /* HAVE_XASN1 */
-
-#if defined(HAVE_YAZ)
- if (! done)
- please_yaz_help_me (hook);
- done = 1;
-#endif /* HAVE_YAZ */
-
-#if defined(HAVE_SNACC)
- if (! done)
- please_snacc_help_me (hook);
- done = 1;
-#endif /* HAVE_SNACC */
-}
-
-
-/*
- * Oh no! yet another main here
- */
-int main (int argc, char * argv [])
-{
- int option;
- const char * optstr = "hvac:ef:i:lnprs:twxz";
- char *optarg;
-
- char * progname;
-
- char * interface = NULL;
- char * filename = NULL;
-
- char * filter = NULL;
- struct bpf_program program = {0};
- bpf_u_int32 network = {0};
- bpf_u_int32 netmask = {0};
-
-
- /*
- * notice the program name
- */
- progname = strrchr (argv [0], '/');
- if (! progname || ! * progname)
- progname = * argv;
- else
- progname ++;
-
- /*
- * Parse command-line options
- */
- while ((option = options(optstr, argv, argc, &optarg)) != -2)
- {
- switch (option)
- {
- default:
- usage (progname);
- return (-1);
-
- case '?':
- printf ("%s: unrecognized option %c\n", progname, optopt);
- usage (progname);
- return (-1);
-
- case ':':
- printf ("%s: missing parameter %c\n", progname, optopt);
- usage (progname);
- return (-1);
-
- case 'h':
- usage (progname);
- return (0);
-
- case 'a':
- aflag = 1;
- break;
-
- case 'c':
- maxapdus = atoi (optarg);
- if (maxapdus <= 0)
- printf ("malformed max apdus counter %s", optarg), maxapdus = DEFAULT_MAXAPDUS;
- break;
-
- case 'e':
- ethflag = 1;
- break;
-
- case 'f':
- filename = strdup (optarg);
- break;
-
- case 'i':
- interface = strdup (optarg);
- break;
-
- case 'l':
- break;
-
- case 'n':
- break;
-
- case 'p':
- break;
-
- case 'r':
- break;
-
- case 's':
- snaplen = atoi (optarg);
- if (snaplen <= 0)
- printf ("malformed snaplen %s", optarg), snaplen = DEFAULT_SNAPLEN;
- break;
-
- case 't':
- tcpflag = 1;
- break;
-
- case 'w':
- break;
-
- case 'x':
- ipflag = 1;
- break;
-
- case 'z':
- z3950flag = 1;
- break;
- }
- }
-
- /*
- * You are welcome
- */
- welcome (progname);
-
-
- /*
- * build a string from all remaining arguments
- */
- filter = NULL;
- {
- int roomsize = 0;
- while (optind < argc)
- {
- roomsize += (strlen (argv [optind]) + 1 + 1);
- if (filter)
- {
- strcat (filter, " ");
- filter = (char *) realloc (filter, roomsize);
- strcat (filter, argv [optind ++]);
- }
- else
- {
- filter = (char *) malloc (roomsize);
- strcpy (filter, argv [optind ++]);
- }
- }
- }
-
-
- /*
- * find a suitable interface, if i don't have one
- */
- if (! filename && ! interface && ! (interface = pcap_lookupdev (ebuf)))
- {
- printf ("No suitable interfaces found, please specify one with -i\n");
- exit (-1);
- }
-
-
- if ((getuid () && geteuid ()) || setuid (0))
- {
- printf ("Sorry, you must be root in order to run this program.\n");
- exit (-1);
- }
-
- /*
- * time to initialize the libpcap
- */
- ph = filename ? pcap_open_offline (filename, ebuf) :
- pcap_open_live (interface, snaplen, 1, 1000, ebuf);
-
- if (! ph)
- printf ("Cannot initialize the libpcap package due to %s\n", ebuf),
- exit (-1);
-
- /*
- * get the interface network number and its mask
- * (unless we are reading data from a file)
- */
- if (! filename && pcap_lookupnet (interface, & network, & netmask, ebuf) < 0)
- printf ("Cannot lookup for the network due to %s\n", ebuf),
- exit (-1);
-
- /*
- * determine the type of the underlying network and the data-link encapsulation method
- * (unless we are reading data from a file)
- */
- dlt = pcap_datalink (ph);
-
- if (! filename && dlt != DLT_NULL && dlt != DLT_IEEE802 && dlt != DLT_EN10MB)
- printf ("Unsupported data-link encapsulation %d\n", dlt),
- exit (-1);
-
- /*
- * compile an optional filter into a BPF program
- */
- if (filter && pcap_compile (ph, & program, filter, 1, netmask) == -1)
- printf ("Cannot compile the filter %s\n", filter),
- exit (-1);
-
- /*
- * apply the filter to the handler
- */
- if (filter && pcap_setfilter (ph, & program) == -1)
- printf ("Cannot set the filter %s\n", filter),
- exit (-1);
-
- /*
- * announce to the world
- */
- printf ("%s %s: listening on %s\n", progname, __version__, interface);
- fflush (stdout);
-
- /*
- * Setup signal handlers
- */
- signal (SIGTERM, on_signal);
- signal (SIGINT, on_signal);
-
-
- /*
- * Go for fun! and handle any packet received
- */
- if (pcap_loop (ph, -1, parse_pdu, NULL) == -1)
- printf ("%s: error while capturing packets due to %s\n", progname, pcap_geterr (ph)),
- exit (-1);
-
- pcap_close (ph);
-
-
- return (0);
-}