2 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
3 * hooks.c - a TCP/IP protocol filter for ziffy
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 # if !defined(_BSD_SOURCE)
31 * Operating System include files
35 #include <sys/types.h>
36 #include <sys/socket.h>
39 #include <arpa/inet.h>
46 #include <netinet/in.h>
49 #if HAVE_NETINET_IF_ETHER_H
50 #include <netinet/if_ether.h>
53 #if HAVE_NETINET_IN_SYSTM_H
54 #include <netinet/in_systm.h>
57 #include <netinet/ip.h>
58 #include <netinet/tcp.h>
60 #include "pcap.h" /* Packet Capture Library */
64 void fmemdmp (FILE * fd, char * ptr, int size, char * text);
72 * to allow a pretty-print of lower-layers address I save
73 * relevant pointers to all the protocol data units in global variables,
74 * rather than pass them across function calls.
75 * So, for example, if someone is interested in the paired source and
76 * destination IP addressed, they can be easily accessed by global 'ip' pointer.
81 * hooks to the known protocols in the ethernet packets
83 static struct ether_header * e = NULL;
84 static struct ip * ip = NULL;
85 static struct tcphdr * tcp = NULL;
86 extern u_char * z3950;
89 * sizes of the known protocols in the ethernet packets
91 static int eth_size = 0;
92 static int eth_hlen = 0;
93 static int ip_size = 0;
94 static int ip_hlen = 0;
95 static int tcp_size = 0;
96 static int tcp_hlen = 0;
97 extern int z3950_size;
100 char * srchost (void)
102 static char buf [256]; /* should be enough for humans !!! */
104 struct hostent * host = NULL;
107 host = gethostbyaddr ((char *) & ip -> ip_src, sizeof (ip -> ip_src), AF_INET);
109 sprintf (buf, "%s", host ? host -> h_name : inet_ntoa (ip -> ip_src));
116 return ((int) ntohs (tcp -> th_sport));
120 char * dsthost (void)
122 static char buf [256]; /* should be enough for humans !!! */
124 struct hostent * host = NULL;
127 host = gethostbyaddr ((char *) & ip -> ip_dst, sizeof (ip -> ip_dst), AF_INET);
129 sprintf (buf, "%s", host ? host -> h_name : inet_ntoa (ip -> ip_dst));
136 return ((int) ntohs (tcp -> th_dport));
141 * stolen from the addrtoname.c in tcpdump
143 static char hex [] = "0123456789abcdef";
145 static char * etheraddr_string (u_char * e)
147 static char buf [sizeof ("00:00:00:00:00:00")];
153 strcpy (buf, "00:00:00:00:00:00");
156 * hacked to manage DLT_NULL
162 if ((j = * e >> 4) != 0)
164 * p ++ = hex [* e ++ & 0xf];
165 for (i = 5; -- i >= 0; )
168 if ((j = * e >> 4) != 0)
170 * p ++ = hex [* e ++ & 0xf];
178 * Parse the incoming Ethernet Packet and set hooks to all pertinent data.
180 * 'h' is the pointer to the packet header (independent from interfaces)
181 * 'p' is the pointer to the packet data
183 * Warning: I really want libpcap to give me aligned packets
185 z3950apdu * pduhook (const struct pcap_pkthdr * h, const u_char * p)
187 static unsigned long ethno = 0; /* # of ethernet packets received by the decoder */
188 static unsigned long ipno = 0; /* # of IP packets received by the decoder */
189 static unsigned long tcpno = 0; /* # of TCP packets received by the decoder */
193 z3950apdu * apdu = NULL;
198 e = (struct ether_header *) p;
203 * The header is only 4 bytes long in case of no link-layer encapsulation (DLT_NULL).
204 * It contains a network order 32 bit integer that specifies the family, e.g. AF_INET
207 eth_hlen = dlt == DLT_NULL ? 4 : sizeof (struct ether_header);
212 printf ("ETHER: ----- Ether Header -----\n"),
214 printf ("ETHER: Packet %ld arrived at %s\n", ethno, timestamp (& h -> ts, ABS_FMT)),
215 printf ("ETHER: Total size = %d : header = %d : data = %d\n",
216 eth_size, eth_hlen, eth_size - eth_hlen),
217 printf ("ETHER: Source = %s\n",
218 etheraddr_string (dlt == DLT_NULL ? NULL : (u_char *) & e -> ether_shost)),
219 printf ("ETHER: Destination = %s\n",
220 etheraddr_string (dlt == DLT_NULL ? NULL : (u_char *) & e -> ether_dhost)),
222 fmemdmp (stdout, (char *) e, eth_size, "Ethernet Packet");
225 * Process only IP packets (or loopback packets when testing at home sweet home)
227 if (dlt == DLT_NULL || ntohs (e -> ether_type) == ETHERTYPE_IP)
232 ip = (struct ip *) (p + eth_hlen);
237 * ip->ip_hl*4 = size of the IP (Header Only)
238 * ntohs (ip->ip_len) = size of the IP (Full Packet)
239 * ip_size = eth_size - eth_hlen (better IMO)
241 ip_size = eth_size - eth_hlen;
242 ip_hlen = ip -> ip_hl * 4;
247 printf ("IP: ----- IP Header -----\n"),
249 printf ("IP: Packet %ld arrived at %s\n", ipno, timestamp (& h -> ts, ABS_FMT)),
250 printf ("IP: Total size = %d : header = %d : data = %d\n",
251 ip_size, ip_hlen, ip_size - ip_hlen),
252 printf ("IP: Source = %s\n", inet_ntoa (ip -> ip_src)),
253 printf ("IP: Destination = %s\n", inet_ntoa (ip -> ip_dst)),
257 fmemdmp (stdout, (char *) ip, ip_size, "IP Packet");
261 * i am looking for Z39.50 APDUs over TCP/IP. so...
263 if (ip -> ip_p == IPPROTO_TCP)
268 q = (u_char *) ip + ip_hlen;
269 tcp = (struct tcphdr *) q;
274 * tcp->th_off*4 = size of the TCP (Header Only)
276 tcp_size = ip_size - ip_hlen;
277 tcp_hlen = tcp -> th_off * 4;
282 printf ("TCP: ----- TCP Header -----\n"),
284 printf ("TCP: Packet %ld arrived at %s\n", tcpno, timestamp (& h -> ts, ABS_FMT)),
285 printf ("TCP: Total size = %d : header = %d : data = %d\n",
286 tcp_size, tcp_hlen, tcp_size - tcp_hlen),
287 printf ("TCP: Source = %d\n", ntohs (tcp -> th_sport)),
288 printf ("TCP: Destination = %d\n", ntohs (tcp -> th_dport)),
290 fmemdmp (stdout, (char *) tcp, tcp_size, "TCP Packet");
293 * Application Protocol
294 * (time to play with Z39.50 APDUs here)
296 z3950 = (u_char *) e + eth_hlen + ip_hlen + tcp_hlen;
299 * Higher Protocol Packet Size
301 z3950_size = tcp_size - tcp_hlen;
303 apdu = parseable (z3950, z3950_size);
306 printf ("TCP: ----- TCP Header -----\n"),
308 printf ("TCP: Packet %ld arrived at %s\n", tcpno, timestamp (& h -> ts, ABS_FMT)),
309 printf ("TCP: Total size = %d : header = %d : data = %d\n",
310 tcp_size, tcp_hlen, tcp_size - tcp_hlen),
311 printf ("TCP: Source = %d\n", ntohs (tcp -> th_sport)),
312 printf ("TCP: Destination = %d\n", ntohs (tcp -> th_dport)),
314 fmemdmp (stdout, (char *) tcp, tcp_size, "TCP Packet");