2 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
3 * ziffy.c - a promiscuous Z39.50 APDU sniffer for Ethernet
5 * Copyright (c) 1998-2001 R. Carbone <rocco@ntop.org>
6 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * Operating System include files
37 #include <sys/utsname.h>
43 #include "pcap.h" /* Packet Capture Library */
51 z3950apdu * pduhook (const struct pcap_pkthdr * h, const u_char * p);
54 #if defined(HAVE_XASN1)
55 void please_finsiel_help_me (z3950apdu * hook);
56 #endif /* HAVE_XASN1 */
59 void please_yaz_help_me (z3950apdu * hook);
62 #if defined(HAVE_SNACC)
63 void please_snacc_help_me (z3950apdu * hook);
64 #endif /* HAVE_SNACC */
70 time_t now; /* current time */
71 time_t start_time; /* time the program was started */
72 time_t firstapdu_time; /* time the first APDU was received */
73 time_t laststapdu_time; /* time the last APDU was received */
75 unsigned long int z3950_apduno = 0; /* # of z3950 apdus so far received */
76 u_char * z3950 = NULL; /* pointer to the last apdu received */
77 int z3950_size = 0; /* and its size */
80 * I currently tested the program at home in a null networked environment
81 * and on ethernet 10M lan. the following variable keeps the data-link
82 * encapsulation type. more info in net/bpf.h
86 int aflag = 0; /* attempt to convert numeric network addresses to FQDN */
95 * Length of saved portion of packet
97 #define DEFAULT_SNAPLEN 65536 /* This should be enough... */
98 static int snaplen = DEFAULT_SNAPLEN;
100 #define DEFAULT_MAXAPDUS -1 /* that means indefinite */
101 static int maxapdus = DEFAULT_MAXAPDUS;
104 * A handler for pcap, it needs to be global because there is no other way to
105 * pass it to the signal handler, the same can be said about the file descriptor
114 static char __copyright__ [] = "Copyright (c) 1998-2001";
115 static char __author__ [] = "R. Carbone <rocco@ntop.org>";
116 static char __version__ [] = "Version 0.0.3";
117 static char __released__ [] = "June 2001";
121 struct option options [] =
124 { "help", no_argument, NULL, 'h' },
125 { "version", no_argument, NULL, 'v' },
127 /* Session Management stuff */
128 { "restart-session", required_argument, NULL, 'S' },
129 { "discard-session", required_argument, NULL, 'D' },
135 char ebuf [PCAP_ERRBUF_SIZE] = {0};
136 struct pcap_stat pcapstats = {0};
141 void on_signal (int signo)
144 * time for statistics
146 if (pcap_stats (ph, & pcapstats) != 0)
148 printf ("Cannot get the statistics due to %s\n", ebuf),
155 printf ("%u packets received by decoder\n", pcapstats . ps_recv);
156 printf ("%u packets dropped by kernel\n", pcapstats . ps_drop);
174 void welcome (char * progname)
176 time_t now = ((time_t) time ((time_t *) 0));
177 char * nowstring = ctime (& now);
178 struct utsname machine;
180 nowstring [24] = '\0';
183 printf ("This is %s %s of %s\n", progname, __version__, __released__);
184 printf ("%s %s\n", __copyright__, __author__);
185 printf ("Started at %s on %s\n\n", nowstring, machine . nodename);
193 * Wrong. Please try again accordingly to ....
195 void usage (char * progname)
199 printf ("Usage: %s [--help] [--version]\n\n", progname);
200 printf ("Options:\n");
201 printf (" h, --help display this help and exit\n");
202 printf (" v, --version output version information and exit\n");
204 printf (" , -- print filter code\n");
205 printf (" , -- print ethernet header\n");
206 printf (" , -- try to resolve ip addresses\n");
207 printf (" , -- remove domains from printed host names\n");
208 printf (" , -- don't translate _foreign_ IP address\n");
209 printf (" , -- print packet arrival time\n");
211 printf (" s, --snaplen \n");
212 printf (" N, --non-promiscuous capture APDUs addressed to the host machine\n");
213 printf (" C, --maxcount capture maxcount APDUs and then terminate\n");
215 printf (" D, --dropped-packets display number of packets dropped during capture\n");
221 * This is really the `main' function of the sniffer.
223 * Parse the incoming APDU, and when possible show all pertinent data.
225 * 'h' is the pointer to the packet header (independent from interfaces)
226 * 'p' is the pointer to the packet data
227 * 'caplen' is the number of bytes actually captured
228 * 'length' is the length of the packet off the wire
230 void parse_pdu (u_char * user_data,
231 const struct pcap_pkthdr * h,
237 if (! (hook = pduhook (h, p)))
241 * update the descriptor of the apdu
243 hook -> t = & h -> ts;
244 hook -> calling = srchost ();
245 hook -> srcport = srcport ();
246 hook -> called = dsthost ();
247 hook -> dstport = dstport ();
249 #if defined(HAVE_XASN1)
251 please_finsiel_help_me (hook);
253 #endif /* HAVE_XASN1 */
255 #if defined(HAVE_YAZ)
257 please_yaz_help_me (hook);
259 #endif /* HAVE_YAZ */
261 #if defined(HAVE_SNACC)
263 please_snacc_help_me (hook);
265 #endif /* HAVE_SNACC */
270 * Oh no! yet another main here
272 int main (int argc, char * argv [])
275 char * optstr = "hvac:ef:i:lnprs:twxz";
279 char * interface = NULL;
280 char * filename = NULL;
282 char * filter = NULL;
283 struct bpf_program program = {0};
284 bpf_u_int32 network = {0};
285 bpf_u_int32 netmask = {0};
289 * notice the program name
291 progname = strrchr (argv [0], '/');
292 if (! progname || ! * progname)
304 opterr = 0; /* this prevents getopt() to send error messages to stderr */
308 * Parse command-line options
310 while ((option = getopt (argc, argv, optstr)) != EOF)
319 printf ("%s: unrecognized option %c\n", progname, optopt);
324 printf ("%s: missing parameter %c\n", progname, optopt);
337 maxapdus = atoi (optarg);
339 printf ("malformed max apdus counter %s", optarg), maxapdus = DEFAULT_MAXAPDUS;
347 filename = strdup (optarg);
351 interface = strdup (optarg);
367 snaplen = atoi (optarg);
369 printf ("malformed snaplen %s", optarg), snaplen = DEFAULT_SNAPLEN;
396 * build a string from all remaining arguments
401 while (optind < argc)
403 roomsize += (strlen (argv [optind]) + 1 + 1);
406 strcat (filter, " ");
407 filter = realloc (filter, roomsize);
408 strcat (filter, argv [optind ++]);
412 filter = malloc (roomsize);
413 strcpy (filter, argv [optind ++]);
420 * find a suitable interface, if i don't have one
422 if (! filename && ! interface && ! (interface = pcap_lookupdev (ebuf)))
424 printf ("No suitable interfaces found, please specify one with -i\n");
429 if ((getuid () && geteuid ()) || setuid (0))
431 printf ("Sorry, you must be root in order to run this program.\n");
436 * time to initialize the libpcap
438 ph = filename ? pcap_open_offline (filename, ebuf) :
439 pcap_open_live (interface, snaplen, 1, 1000, ebuf);
442 printf ("Cannot initialize the libpcap package due to %s\n", ebuf),
446 * get the interface network number and its mask
447 * (unless we are reading data from a file)
449 if (! filename && pcap_lookupnet (interface, & network, & netmask, ebuf) < 0)
450 printf ("Cannot lookup for the network due to %s\n", ebuf),
454 * determine the type of the underlying network and the data-link encapsulation method
455 * (unless we are reading data from a file)
457 dlt = pcap_datalink (ph);
459 if (! filename && dlt != DLT_NULL && dlt != DLT_IEEE802 && dlt != DLT_EN10MB)
460 printf ("Unsupported data-link encapsulation %d\n", dlt),
464 * compile an optional filter into a BPF program
466 if (filter && pcap_compile (ph, & program, filter, 1, netmask) == -1)
467 printf ("Cannot compile the filter %s\n", filter),
471 * apply the filter to the handler
473 if (filter && pcap_setfilter (ph, & program) == -1)
474 printf ("Cannot set the filter %s\n", filter),
478 * announce to the world
480 printf ("%s %s: listening on %s\n", progname, __version__, interface);
484 * Setup signal handlers
486 signal (SIGTERM, on_signal);
487 signal (SIGINT, on_signal);
491 * Go for fun! and handle any packet received
493 if (pcap_loop (ph, -1, parse_pdu, NULL) == -1)
494 printf ("%s: error while capturing packets due to %s\n", progname, pcap_geterr (ph)),