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

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.  * Modifications made to accommodate the new SunOS4.0 NIT facility by
  22.  * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989.
  23.  * This module now handles the STREAMS based NIT.
  24.  */
  25. #ifndef lint
  26. static const char rcsid[] =
  27.     "@(#) $Header: /usr/local/cvs/nessus-libraries/libpcap-nessus/pcap-snit.c,v 1.3 2003/02/06 20:28:09 renaud Exp $ (LBL)";
  28. #endif
  29. #include <sys/types.h>
  30. #include <sys/time.h>
  31. #include <sys/timeb.h>
  32. #include <sys/dir.h>
  33. #include <sys/fcntlcom.h>
  34. #include <sys/file.h>
  35. #include <sys/ioctl.h>
  36. #include <sys/socket.h>
  37. #include <sys/stropts.h>
  38. #include <net/if.h>
  39. #include <net/nit.h>
  40. #include <net/nit_if.h>
  41. #include <net/nit_pf.h>
  42. #include <net/nit_buf.h>
  43. #include <netinet/in.h>
  44. #include <netinet/in_systm.h>
  45. #include <netinet/ip.h>
  46. #include <netinet/if_ether.h>
  47. #include <netinet/ip_var.h>
  48. #include <netinet/udp.h>
  49. #include <netinet/udp_var.h>
  50. #include <netinet/tcp.h>
  51. #include <netinet/tcpip.h>
  52. #include <ctype.h>
  53. #include <errno.h>
  54. #ifdef HAVE_MALLOC_H
  55. #include <malloc.h>
  56. #endif
  57. #include <stdio.h>
  58. #include <string.h>
  59. #include <unistd.h>
  60. #include "pcap-int.h"
  61. #include "gnuc.h"
  62. #ifdef HAVE_OS_PROTO_H
  63. #include "os-proto.h"
  64. #endif
  65. /*
  66.  * The chunk size for NIT.  This is the amount of buffering
  67.  * done for read calls.
  68.  */
  69. #define CHUNKSIZE (2*1024)
  70. /*
  71.  * The total buffer space used by NIT.
  72.  */
  73. #define BUFSPACE (4*CHUNKSIZE)
  74. /* Forwards */
  75. static int nit_setflags(int, int, int, char *);
  76. int
  77. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  78. {
  79. *ps = p->md.stat;
  80. return (0);
  81. }
  82. int
  83. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  84. {
  85. register int cc, n;
  86. register struct bpf_insn *fcode = p->fcode.bf_insns;
  87. register u_char *bp, *cp, *ep;
  88. register struct nit_bufhdr *hdrp;
  89. register struct nit_iftime *ntp;
  90. register struct nit_iflen *nlp;
  91. register struct nit_ifdrops *ndp;
  92. register int caplen;
  93. cc = p->cc;
  94. if (cc == 0) {
  95. cc = read(p->fd, (char *)p->buffer, p->bufsize);
  96. if (cc < 0) {
  97. if (errno == EWOULDBLOCK)
  98. return (0);
  99. sprintf(p->errbuf, "pcap_read: %s",
  100. pcap_strerror(errno));
  101. return (-1);
  102. }
  103. bp = p->buffer;
  104. } else
  105. bp = p->bp;
  106. /*
  107.  * loop through each snapshot in the chunk
  108.  */
  109. n = 0;
  110. ep = bp + cc;
  111. while (bp < ep) {
  112. ++p->md.stat.ps_recv;
  113. cp = bp;
  114. /* get past NIT buffer  */
  115. hdrp = (struct nit_bufhdr *)cp;
  116. cp += sizeof(*hdrp);
  117. /* get past NIT timer   */
  118. ntp = (struct nit_iftime *)cp;
  119. cp += sizeof(*ntp);
  120. ndp = (struct nit_ifdrops *)cp;
  121. p->md.stat.ps_drop = ndp->nh_drops;
  122. cp += sizeof *ndp;
  123. /* get past packet len  */
  124. nlp = (struct nit_iflen *)cp;
  125. cp += sizeof(*nlp);
  126. /* next snapshot        */
  127. bp += hdrp->nhb_totlen;
  128. caplen = nlp->nh_pktlen;
  129. if (caplen > p->snapshot)
  130. caplen = p->snapshot;
  131. if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) {
  132. struct pcap_pkthdr h;
  133. h.ts = ntp->nh_timestamp;
  134. h.len = nlp->nh_pktlen;
  135. h.caplen = caplen;
  136. (*callback)(user, &h, cp);
  137. if (++n >= cnt && cnt >= 0) {
  138. p->cc = ep - bp;
  139. p->bp = bp;
  140. return (n);
  141. }
  142. }
  143. }
  144. p->cc = 0;
  145. return (n);
  146. }
  147. static int
  148. nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
  149. {
  150. bpf_u_int32 flags;
  151. struct strioctl si;
  152. struct timeval timeout;
  153. si.ic_timout = INFTIM;
  154. if (to_ms != 0) {
  155. timeout.tv_sec = to_ms / 1000;
  156. timeout.tv_usec = (to_ms * 1000) % 1000000;
  157. si.ic_cmd = NIOCSTIME;
  158. si.ic_len = sizeof(timeout);
  159. si.ic_dp = (char *)&timeout;
  160. if (ioctl(fd, I_STR, (char *)&si) < 0) {
  161. sprintf(ebuf, "NIOCSTIME: %s", pcap_strerror(errno));
  162. return (-1);
  163. }
  164. }
  165. flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
  166. if (promisc)
  167. flags |= NI_PROMISC;
  168. si.ic_cmd = NIOCSFLAGS;
  169. si.ic_len = sizeof(flags);
  170. si.ic_dp = (char *)&flags;
  171. if (ioctl(fd, I_STR, (char *)&si) < 0) {
  172. sprintf(ebuf, "NIOCSFLAGS: %s", pcap_strerror(errno));
  173. return (-1);
  174. }
  175. return (0);
  176. }
  177. pcap_t *
  178. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  179. {
  180. struct strioctl si; /* struct for ioctl() */
  181. struct ifreq ifr; /* interface request struct */
  182. int chunksize = CHUNKSIZE;
  183. int fd;
  184. static char dev[] = "/dev/nit";
  185. register pcap_t *p;
  186. p = (pcap_t *)malloc(sizeof(*p));
  187. if (p == NULL) {
  188. strcpy(ebuf, pcap_strerror(errno));
  189. return (NULL);
  190. }
  191. if (snaplen < 96)
  192. /*
  193.  * NIT requires a snapshot length of at least 96.
  194.  */
  195. snaplen = 96;
  196. bzero(p, sizeof(*p));
  197. p->fd = fd = open(dev, O_RDONLY);
  198. if (fd < 0) {
  199. sprintf(ebuf, "%s: %s", dev, pcap_strerror(errno));
  200. goto bad;
  201. }
  202. /* arrange to get discrete messages from the STREAM and use NIT_BUF */
  203. if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
  204. sprintf(ebuf, "I_SRDOPT: %s", pcap_strerror(errno));
  205. goto bad;
  206. }
  207. if (ioctl(fd, I_PUSH, "nbuf") < 0) {
  208. sprintf(ebuf, "push nbuf: %s", pcap_strerror(errno));
  209. goto bad;
  210. }
  211. /* set the chunksize */
  212. si.ic_cmd = NIOCSCHUNK;
  213. si.ic_timout = INFTIM;
  214. si.ic_len = sizeof(chunksize);
  215. si.ic_dp = (char *)&chunksize;
  216. if (ioctl(fd, I_STR, (char *)&si) < 0) {
  217. sprintf(ebuf, "NIOCSCHUNK: %s", pcap_strerror(errno));
  218. goto bad;
  219. }
  220. /* request the interface */
  221. strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  222. ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
  223. si.ic_cmd = NIOCBIND;
  224. si.ic_len = sizeof(ifr);
  225. si.ic_dp = (char *)&ifr;
  226. if (ioctl(fd, I_STR, (char *)&si) < 0) {
  227. sprintf(ebuf, "NIOCBIND: %s: %s",
  228. ifr.ifr_name, pcap_strerror(errno));
  229. goto bad;
  230. }
  231. /* set the snapshot length */
  232. si.ic_cmd = NIOCSSNAP;
  233. si.ic_len = sizeof(snaplen);
  234. si.ic_dp = (char *)&snaplen;
  235. if (ioctl(fd, I_STR, (char *)&si) < 0) {
  236. sprintf(ebuf, "NIOCSSNAP: %s", pcap_strerror(errno));
  237. goto bad;
  238. }
  239. p->snapshot = snaplen;
  240. if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0)
  241. goto bad;
  242. (void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
  243. /*
  244.  * NIT supports only ethernets.
  245.  */
  246. p->linktype = DLT_EN10MB;
  247. p->bufsize = BUFSPACE;
  248. p->buffer = (u_char *)malloc(p->bufsize);
  249. if (p->buffer == NULL) {
  250. strcpy(ebuf, pcap_strerror(errno));
  251. goto bad;
  252. }
  253. return (p);
  254.  bad:
  255. if (fd >= 0)
  256. close(fd);
  257. free(p);
  258. return (NULL);
  259. }
  260. int
  261. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  262. {
  263. p->fcode = *fp;
  264. return (0);
  265. }