PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/nfswatch-4.99.11/pktfilter.c

#
C | 502 lines | 329 code | 50 blank | 123 comment | 47 complexity | 62d7b4476eb7ad0d49656fca33612a49 MD5 | raw file
  1. /*
  2. * $Id: pktfilter.c,v 1.12 2009/04/21 05:42:08 c4chris Exp $
  3. */
  4. #include "os.h"
  5. /*
  6. * pktfilter.c - filters to count the packets.
  7. *
  8. * David A. Curry Jeffrey C. Mogul
  9. * Purdue University Digital Equipment Corporation
  10. * Engineering Computer Network Western Research Laboratory
  11. * 1285 Electrical Engineering Building 250 University Avenue
  12. * West Lafayette, IN 47907-1285 Palo Alto, CA 94301
  13. * davy@ecn.purdue.edu mogul@decwrl.dec.com
  14. *
  15. */
  16. #include <sys/param.h>
  17. #include <sys/socket.h>
  18. #include <net/if.h>
  19. #if !defined(ultrix) && !defined(__osf__)
  20. #include <net/if_arp.h>
  21. #endif
  22. #include <netinet/in.h>
  23. #include <netinet/if_ether.h>
  24. #include <netinet/in_systm.h>
  25. #include <netinet/ip.h>
  26. #include <netinet/udp.h>
  27. #include <netinet/tcp.h>
  28. #ifndef LINUX
  29. #include <netinet/ip_var.h>
  30. #include <netinet/udp_var.h>
  31. #endif
  32. #include <netinet/ip_icmp.h>
  33. #include <errno.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include "nfswatch.h"
  37. #include "externs.h"
  38. #include "screen.h"
  39. #ifdef SUNOS4
  40. #define NND 1
  41. #include <sun/ndio.h>
  42. #endif
  43. #ifdef ultrix
  44. #include "ultrix.map.h"
  45. #include "ipports.h"
  46. #endif
  47. #ifdef __osf__
  48. /* or perhaps "#if defined(__osf__) && defined(__alpha)"? */
  49. #include "osf.map.h"
  50. #include "ipports.h"
  51. #endif
  52. #ifdef sgi
  53. #include <rpc/types.h>
  54. #include "sgi.map.h"
  55. #include "ipports.h"
  56. #endif
  57. #ifdef LINUX
  58. #define uh_sport source
  59. #define uh_dport dest
  60. #define uh_ulen len
  61. #define uh_sum check
  62. #define th_sport source
  63. #define th_dport dest
  64. #define th_off doff
  65. #endif
  66. /*
  67. * Ethernet broadcast address.
  68. */
  69. static struct ether_addr ether_broadcast = {
  70. { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
  71. };
  72. #ifndef SUNOS5
  73. static void pkt_dispatch(char *, int, u_short, struct timeval *);
  74. #endif
  75. static void ip_filter(struct ip *, ipaddrt, ipaddrt, struct timeval *);
  76. static void tcp_filter(struct tcphdr *, u_int, ipaddrt, ipaddrt,
  77. struct timeval *);
  78. static void udp_filter(struct udphdr *, ipaddrt, ipaddrt,
  79. struct timeval *);
  80. static void icmp_filter(void);
  81. /*
  82. * pkt_filter_ether - Parse Ethernet header,
  83. * pass rest of packet to pkt_dispatch()
  84. */
  85. void
  86. pkt_filter_ether(char *cp, u_int length, struct timeval *tstamp)
  87. {
  88. char packet[PACKETSIZE];
  89. register int bdcst;
  90. struct ether_header eheader;
  91. /*
  92. * Extract the ethernet header.
  93. */
  94. memcpy(&eheader, cp, sizeof(struct ether_header));
  95. memcpy(packet, cp + sizeof(struct ether_header),
  96. length - sizeof(struct ether_header));
  97. /*
  98. * See if it's a broadcast packet.
  99. */
  100. #if defined(ultrix) || defined(sgi) || defined(__osf__)
  101. bdcst = !bcmp((char *) eheader.ether_dhost, (char *) &ether_broadcast,
  102. sizeof(struct ether_addr));
  103. #else
  104. bdcst = !bcmp((char *) &eheader.ether_dhost, (char *) &ether_broadcast,
  105. sizeof(struct ether_addr));
  106. #endif
  107. /*
  108. * Figure out what kind of packet it is, and pass
  109. * it off to the appropriate filter.
  110. */
  111. pkt_dispatch(packet, bdcst, eheader.ether_type, tstamp);
  112. }
  113. #ifndef LLC_SNAP_LSAP
  114. #define LLC_UI 0x3
  115. #define LLC_SNAP_LSAP 0xaa
  116. #endif
  117. /*
  118. * pkt_filter_fddi - Parse FDDI and LLC headers,
  119. * pass rest of packet to pkt_dispatch()
  120. */
  121. void
  122. pkt_filter_fddi(char *cp, u_int length, struct timeval *tstamp)
  123. {
  124. char packet[PACKETSIZE];
  125. register int bdcst;
  126. struct fddi_header {
  127. u_char fddi_fc;
  128. u_char fddi_dhost[6];
  129. u_char fddi_shost[6];
  130. } fheader;
  131. struct llc_header {
  132. u_char llc_dsap;
  133. u_char llc_ssap;
  134. u_char llc_control;
  135. u_char llc_org_code[3];
  136. u_short llc_ether_type;
  137. } lheader;
  138. u_short etype;
  139. #define FDDI_LLC_LEN (sizeof(struct fddi_header) + sizeof(struct llc_header))
  140. if (length <= FDDI_LLC_LEN)
  141. return; /* runt */
  142. /*
  143. * Extract the FDDI and LLC headers.
  144. */
  145. (void) bcopy(cp, (char *) &fheader, sizeof(struct fddi_header));
  146. (void) bcopy(cp + sizeof(struct fddi_header), (char *) &lheader,
  147. sizeof(struct llc_header));
  148. (void) bcopy(cp + FDDI_LLC_LEN, (char *) packet,
  149. (int) (length - FDDI_LLC_LEN));
  150. /* Should check FDDI frame control ... */
  151. /*
  152. * See if it's a broadcast packet.
  153. */
  154. bdcst = !bcmp((char *) fheader.fddi_dhost, (char *) &ether_broadcast,
  155. sizeof(struct ether_addr));
  156. /*
  157. * Check LLC encapsulation type, extract Ethernet type if SNAP
  158. */
  159. if ((lheader.llc_dsap == LLC_SNAP_LSAP)
  160. && (lheader.llc_ssap == LLC_SNAP_LSAP)
  161. && (lheader.llc_control == LLC_UI)
  162. && (lheader.llc_org_code[0] == 0)
  163. && (lheader.llc_org_code[1] == 0)
  164. && (lheader.llc_org_code[2] == 0)) {
  165. etype = lheader.llc_ether_type;
  166. }
  167. else
  168. etype = 0;
  169. /*
  170. * Figure out what kind of packet it is, and pass
  171. * it off to the appropriate filter.
  172. */
  173. pkt_dispatch(packet, bdcst, etype, tstamp);
  174. }
  175. #ifdef USE_LINUX
  176. /*
  177. * A DLT_LINUX_SLL fake link-layer header.
  178. */
  179. #define SLL_HDR_LEN 16 /* total header length */
  180. #define SLL_ADDRLEN 8 /* length of address field */
  181. #define LINUX_SLL_HOST 0
  182. #define LINUX_SLL_BROADCAST 1
  183. #define LINUX_SLL_MULTICAST 2
  184. #define LINUX_SLL_OTHERHOST 3
  185. #define LINUX_SLL_OUTGOING 4
  186. struct sll_header {
  187. u_int16_t sll_pkttype; /* packet type */
  188. u_int16_t sll_hatype; /* link-layer address type */
  189. u_int16_t sll_halen; /* link-layer address length */
  190. u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
  191. u_int16_t sll_protocol; /* protocol */
  192. };
  193. /*
  194. * pkt_filter_sll - Parse LINUX_SLL header,
  195. * pass rest of packet to pkt_dispatch()
  196. */
  197. void
  198. pkt_filter_sll(char *cp, u_int length, struct timeval *tstamp)
  199. {
  200. char packet[PACKETSIZE];
  201. register int bdcst;
  202. struct sll_header sheader;
  203. /*
  204. * Extract the SLL header.
  205. */
  206. memcpy(&sheader, cp, sizeof(struct sll_header));
  207. memcpy(packet, cp + sizeof(struct sll_header),
  208. length - sizeof(struct sll_header));
  209. /*
  210. * See if it's a broadcast packet.
  211. */
  212. bdcst = ntohs(sheader.sll_pkttype) == LINUX_SLL_BROADCAST;
  213. /*
  214. * Figure out what kind of packet it is, and pass
  215. * it off to the appropriate filter.
  216. */
  217. pkt_dispatch(packet, bdcst, sheader.sll_protocol, tstamp);
  218. }
  219. #endif /* USE_LINUX */
  220. /*
  221. * pkt_dispatch - count a packet, and pass it off to the appropriate filter.
  222. * Caller tells us the Ethernet type code and if the packet
  223. * was a broadcast.
  224. */
  225. #ifdef SUNOS5
  226. void
  227. #else
  228. static void
  229. #endif
  230. /* packet: address of IP or ARP header */
  231. /* bdcst: was packet a LAN broadcast? */
  232. /* etype: still in network byte-order */
  233. pkt_dispatch(char *packet, int bdcst,
  234. u_short etype, struct timeval *tstamp)
  235. {
  236. struct ip *ip;
  237. struct ether_arp *arp;
  238. int sender, target;
  239. register int want;
  240. /*
  241. * Count this packet in the network totals.
  242. */
  243. int_pkt_total++;
  244. pkt_total++;
  245. /*
  246. * See if it's a broadcast packet, and count it if it is.
  247. */
  248. if (bdcst) {
  249. pkt_counters[PKT_BROADCAST].pc_interval++;
  250. pkt_counters[PKT_BROADCAST].pc_total++;
  251. }
  252. /*
  253. * Figure out what kind of packet it is, and pass
  254. * it off to the appropriate filter.
  255. */
  256. switch (ntohs(etype)) {
  257. case ETHERTYPE_IP: /* IP packet */
  258. ip = (struct ip *) packet;
  259. want = want_packet(ip->ip_src.s_addr, ip->ip_dst.s_addr);
  260. /*
  261. * If we want this packet, count it in the host
  262. * totals and pass it off.
  263. */
  264. if (bdcst || want) {
  265. int_dst_pkt_total++;
  266. dst_pkt_total++;
  267. ip_filter(ip, ip->ip_src.s_addr,
  268. ip->ip_dst.s_addr, tstamp);
  269. }
  270. break;
  271. case ETHERTYPE_ARP: /* Address Resolution Protocol */
  272. arp = (struct ether_arp *) packet;
  273. sender = (arp->arp_spa[0] << 24) +
  274. (arp->arp_spa[1] << 16) +
  275. (arp->arp_spa[2] << 8) +
  276. arp->arp_spa[3];
  277. target = (arp->arp_tpa[0] << 24) +
  278. (arp->arp_tpa[1] << 16) +
  279. (arp->arp_tpa[2] << 8) +
  280. arp->arp_tpa[3];
  281. want = want_packet(sender, target);
  282. /*
  283. * If we want this packet, count it in the host
  284. * totals and then count it in the packet
  285. * type counters.
  286. */
  287. if (bdcst || want) {
  288. int_dst_pkt_total++;
  289. dst_pkt_total++;
  290. pkt_counters[PKT_ARP].pc_interval++;
  291. pkt_counters[PKT_ARP].pc_total++;
  292. }
  293. break;
  294. case ETHERTYPE_REVARP: /* Reverse Addr Resol Protocol */
  295. arp = (struct ether_arp *) packet;
  296. sender = (arp->arp_spa[0] << 24) +
  297. (arp->arp_spa[1] << 16) +
  298. (arp->arp_spa[2] << 8) +
  299. arp->arp_spa[3];
  300. target = (arp->arp_tpa[0] << 24) +
  301. (arp->arp_tpa[1] << 16) +
  302. (arp->arp_tpa[2] << 8) +
  303. arp->arp_tpa[3];
  304. want = want_packet(sender, target);
  305. /*
  306. * If we want this packet, count it in the host
  307. * totals and then count it in the packet
  308. * type counters.
  309. */
  310. if (bdcst || want) {
  311. int_dst_pkt_total++;
  312. dst_pkt_total++;
  313. pkt_counters[PKT_RARP].pc_interval++;
  314. pkt_counters[PKT_RARP].pc_total++;
  315. }
  316. break;
  317. #ifdef notdef
  318. case ETHERTYPE_PUP: /* Xerox PUP */
  319. #endif
  320. default: /* who knows... */
  321. int_dst_pkt_total++;
  322. dst_pkt_total++;
  323. pkt_counters[PKT_OTHER].pc_interval++;
  324. pkt_counters[PKT_OTHER].pc_total++;
  325. break;
  326. }
  327. }
  328. /*
  329. * ip_filter - strip off the IP header and pass off to the appropriate
  330. * filter.
  331. */
  332. static void
  333. ip_filter(struct ip *ip, ipaddrt src, ipaddrt dst,
  334. struct timeval *tstamp)
  335. {
  336. register int *data;
  337. register int datalength;
  338. data = (int *) ip;
  339. data += ip->ip_hl;
  340. datalength = ntohs(ip->ip_len) - (4 * ip->ip_hl);
  341. /*
  342. * Figure out what kind of IP packet this is, and
  343. * pass it off to the appropriate filter.
  344. */
  345. switch (ip->ip_p) {
  346. case IPPROTO_TCP: /* transmission control protocol*/
  347. tcp_filter((struct tcphdr *) data, datalength,
  348. src, dst, tstamp);
  349. break;
  350. case IPPROTO_UDP: /* user datagram protocol */
  351. udp_filter((struct udphdr *) data,
  352. src, dst, tstamp);
  353. break;
  354. case IPPROTO_ICMP: /* control message protocol */
  355. icmp_filter();
  356. break;
  357. #ifdef notdef
  358. case IPPROTO_IGMP: /* group message protocol */
  359. case IPPROTO_GGP: /* gateway-gateway protocol */
  360. case IPPROTO_EGP: /* exterior gateway protocol */
  361. case IPPROTO_PUP: /* Xerox pup protocol */
  362. case IPPROTO_IDP: /* XNS IDP */
  363. #endif
  364. default: /* who knows... */
  365. break;
  366. }
  367. }
  368. /* We should get this from the services database... */
  369. #define NFS_PORT 2049
  370. /*
  371. * tcp_filter - count TCP packets, pass RPC packets to the RPC filter.
  372. */
  373. static void
  374. tcp_filter(struct tcphdr *tcp, u_int length, ipaddrt src, ipaddrt dst,
  375. struct timeval *tstamp)
  376. {
  377. unsigned short source = ntohs(tcp->th_sport);
  378. unsigned short dest = ntohs(tcp->th_dport);
  379. unsigned int hdr_len = tcp->th_off * 4;
  380. /*
  381. * Count as a TCP packet.
  382. */
  383. pkt_counters[PKT_TCP].pc_interval++;
  384. pkt_counters[PKT_TCP].pc_total++;
  385. hdr_len += 4; /* For some reason... */
  386. if (length < hdr_len)
  387. return;
  388. if (source == NFS_PORT
  389. || dest == NFS_PORT) {
  390. rpc_filter((char *) tcp + hdr_len, length - hdr_len,
  391. src, dst, tstamp);
  392. return;
  393. }
  394. if (rpcPortCnt > 0) {
  395. unsigned int i;
  396. for (i = 0; i < rpcPortCnt; i++) {
  397. if (dest == rpcPort[i]) {
  398. rpc_filter((char *) tcp + hdr_len, length - hdr_len,
  399. src, dst, tstamp);
  400. return;
  401. }
  402. }
  403. }
  404. }
  405. /*
  406. * udp_filter - count UDP packets, pass RPC packets to the RPC filter.
  407. */
  408. static void
  409. udp_filter(struct udphdr *udp, ipaddrt src, ipaddrt dst,
  410. struct timeval *tstamp)
  411. {
  412. unsigned short source = ntohs(udp->uh_sport);
  413. unsigned short dest = ntohs(udp->uh_dport);
  414. /*
  415. * Count as a UDP packet.
  416. */
  417. pkt_counters[PKT_UDP].pc_interval++;
  418. pkt_counters[PKT_UDP].pc_total++;
  419. if (source == IPPORT_ROUTESERVER
  420. || dest == IPPORT_ROUTESERVER) {
  421. pkt_counters[PKT_ROUTING].pc_interval++;
  422. pkt_counters[PKT_ROUTING].pc_total++;
  423. return;
  424. }
  425. if (source == NFS_PORT
  426. || dest == NFS_PORT) {
  427. rpc_filter((char *) udp + sizeof(struct udphdr),
  428. ntohs(udp->uh_ulen) - sizeof(struct udphdr),
  429. src, dst, tstamp);
  430. return;
  431. }
  432. if (rpcPortCnt > 0) {
  433. unsigned int i;
  434. for (i = 0; i < rpcPortCnt; i++) {
  435. if (dest == rpcPort[i]) {
  436. rpc_filter((char *) udp + sizeof(struct udphdr),
  437. ntohs(udp->uh_ulen) - sizeof(struct udphdr),
  438. src, dst, tstamp);
  439. return;
  440. }
  441. }
  442. }
  443. }
  444. /*
  445. * icmp_filter - count ICMP packets.
  446. */
  447. static void
  448. icmp_filter(void)
  449. {
  450. pkt_counters[PKT_ICMP].pc_interval++;
  451. pkt_counters[PKT_ICMP].pc_total++;
  452. }