pcap-nit.c
上传用户:tjescc
上传日期:2021-02-23
资源大小:419k
文件大小:6k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
  3.  * The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static const char rcsid[] =
  23.     "@(#) $Header: /usr/local/cvs/nessus-libraries/libpcap-nessus/pcap-nit.c,v 1.3 2003/02/06 20:28:08 renaud Exp $ (LBL)";
  24. #endif
  25. #include <sys/types.h>
  26. #include <sys/time.h>
  27. #include <sys/timeb.h>
  28. #include <sys/file.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/socket.h>
  31. #include <net/if.h>
  32. #include <net/nit.h>
  33. #include <netinet/in.h>
  34. #include <netinet/in_systm.h>
  35. #include <netinet/ip.h>
  36. #include <netinet/if_ether.h>
  37. #include <netinet/ip_var.h>
  38. #include <netinet/udp.h>
  39. #include <netinet/udp_var.h>
  40. #include <netinet/tcp.h>
  41. #include <netinet/tcpip.h>
  42. #include <ctype.h>
  43. #include <errno.h>
  44. #include <stdio.h>
  45. #include "pcap-int.h"
  46. #include "gnuc.h"
  47. #ifdef HAVE_OS_PROTO_H
  48. #include "os-proto.h"
  49. #endif
  50. /*
  51.  * The chunk size for NIT.  This is the amount of buffering
  52.  * done for read calls.
  53.  */
  54. #define CHUNKSIZE (2*1024)
  55. /*
  56.  * The total buffer space used by NIT.
  57.  */
  58. #define BUFSPACE (4*CHUNKSIZE)
  59. /* Forwards */
  60. static int nit_setflags(int, int, int, char *);
  61. int
  62. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  63. {
  64. *ps = p->md.stat;
  65. return (0);
  66. }
  67. int
  68. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  69. {
  70. register int cc, n;
  71. register struct bpf_insn *fcode = p->fcode.bf_insns;
  72. register u_char *bp, *cp, *ep;
  73. register struct nit_hdr *nh;
  74. register int caplen;
  75. cc = p->cc;
  76. if (cc == 0) {
  77. cc = read(p->fd, (char *)p->buffer, p->bufsize);
  78. if (cc < 0) {
  79. if (errno == EWOULDBLOCK)
  80. return (0);
  81. sprintf(p->errbuf, "pcap_read: %s",
  82. pcap_strerror(errno));
  83. return (-1);
  84. }
  85. bp = p->buffer;
  86. } else
  87. bp = p->bp;
  88. /*
  89.  * Loop through each packet.  The increment expression
  90.  * rounds up to the next int boundary past the end of
  91.  * the previous packet.
  92.  */
  93. n = 0;
  94. ep = bp + cc;
  95. while (bp < ep) {
  96. nh = (struct nit_hdr *)bp;
  97. cp = bp + sizeof(*nh);
  98. switch (nh->nh_state) {
  99. case NIT_CATCH:
  100. break;
  101. case NIT_NOMBUF:
  102. case NIT_NOCLUSTER:
  103. case NIT_NOSPACE:
  104. p->md.stat.ps_drop = nh->nh_dropped;
  105. continue;
  106. case NIT_SEQNO:
  107. continue;
  108. default:
  109. sprintf(p->errbuf, "bad nit state %d", nh->nh_state);
  110. return (-1);
  111. }
  112. ++p->md.stat.ps_recv;
  113. bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
  114.     sizeof(int) - 1) & ~(sizeof(int) - 1));
  115. caplen = nh->nh_wirelen;
  116. if (caplen > p->snapshot)
  117. caplen = p->snapshot;
  118. if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) {
  119. struct pcap_pkthdr h;
  120. h.ts = nh->nh_timestamp;
  121. h.len = nh->nh_wirelen;
  122. h.caplen = caplen;
  123. (*callback)(user, &h, cp);
  124. if (++n >= cnt && cnt >= 0) {
  125. p->cc = ep - bp;
  126. p->bp = bp;
  127. return (n);
  128. }
  129. }
  130. }
  131. p->cc = 0;
  132. return (n);
  133. }
  134. static int
  135. nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
  136. {
  137. struct nit_ioc nioc;
  138. bzero((char *)&nioc, sizeof(nioc));
  139. nioc.nioc_bufspace = BUFSPACE;
  140. nioc.nioc_chunksize = CHUNKSIZE;
  141. nioc.nioc_typetomatch = NT_ALLTYPES;
  142. nioc.nioc_snaplen = p->snapshot;
  143. nioc.nioc_bufalign = sizeof(int);
  144. nioc.nioc_bufoffset = 0;
  145. if (to_ms != 0) {
  146. nioc.nioc_flags |= NF_TIMEOUT;
  147. nioc.nioc_timeout.tv_sec = to_ms / 1000;
  148. nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000;
  149. }
  150. if (promisc)
  151. nioc.nioc_flags |= NF_PROMISC;
  152. if (ioctl(fd, SIOCSNIT, &nioc) < 0) {
  153. sprintf(ebuf, "SIOCSNIT: %s", pcap_strerror(errno));
  154. return (-1);
  155. }
  156. return (0);
  157. }
  158. pcap_t *
  159. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  160. {
  161. int fd;
  162. struct sockaddr_nit snit;
  163. register pcap_t *p;
  164. p = (pcap_t *)malloc(sizeof(*p));
  165. if (p == NULL) {
  166. strcpy(ebuf, pcap_strerror(errno));
  167. return (NULL);
  168. }
  169. if (snaplen < 96)
  170. /*
  171.  * NIT requires a snapshot length of at least 96.
  172.  */
  173. snaplen = 96;
  174. bzero(p, sizeof(*p));
  175. p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
  176. if (fd < 0) {
  177. sprintf(ebuf, "socket: %s", pcap_strerror(errno));
  178. goto bad;
  179. }
  180. snit.snit_family = AF_NIT;
  181. (void)strncpy(snit.snit_ifname, device, NITIFSIZ);
  182. if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
  183. sprintf(ebuf, "bind: %s: %s", snit.snit_ifname,
  184. pcap_strerror(errno));
  185. goto bad;
  186. }
  187. p->snapshot = snaplen;
  188. nit_setflags(p->fd, promisc, to_ms, ebuf);
  189. /*
  190.  * NIT supports only ethernets.
  191.  */
  192. p->linktype = DLT_EN10MB;
  193. p->bufsize = BUFSPACE;
  194. p->buffer = (u_char *)malloc(p->bufsize);
  195. if (p->buffer == NULL) {
  196. strcpy(ebuf, pcap_strerror(errno));
  197. goto bad;
  198. }
  199. return (p);
  200.  bad:
  201. if (fd >= 0)
  202. close(fd);
  203. free(p);
  204. return (NULL);
  205. }
  206. int
  207. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  208. {
  209. p->fcode = *fp;
  210. return (0);
  211. }