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

Telnet服务器

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1996, 1997
  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-linux.c,v 1.5 2003/03/07 00:57:40 renaud Exp $ (LBL)";
  24. #endif
  25. #include <sys/param.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/socket.h>
  28. #include <sys/time.h>
  29. #include <net/if.h>
  30. #ifdef HAVE_NET_IF_ARP_H
  31. #include <net/if_arp.h>
  32. #else
  33. #include <linux/if_arp.h>
  34. #endif
  35. #include <linux/if_ether.h>
  36. #include <netinet/in.h>
  37. #include <errno.h>
  38. #include <malloc.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <unistd.h>
  43. static struct ifreq saved_ifr;
  44. #include "pcap-int.h"
  45. #include "gnuc.h"
  46. #ifdef HAVE_OS_PROTO_H
  47. #include "os-proto.h"
  48. #endif
  49. #define TIMEVAL_SUBTRACT(a,b)  ((a.tv_sec - b.tv_sec) * 1000000 + a.tv_usec - b.tv_usec)
  50. static int timeout;
  51. void linux_restore_ifr(void);
  52. int
  53. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  54. {
  55. *ps = p->md.stat;
  56. return (0);
  57. }
  58. int
  59. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  60. {
  61. register int cc;
  62. register int bufsize;
  63. register int caplen;
  64. register u_char *bp;
  65. struct sockaddr from;
  66. int fromlen;
  67. fd_set fd_r;
  68. struct timeval select_time, start, now, tmp;
  69. int res;
  70. fromlen = sizeof(from);
  71. select_time.tv_sec = timeout / 1000;
  72. select_time.tv_usec = (timeout % 1000) * 1000;
  73. gettimeofday(&start, NULL);
  74. do {
  75.   FD_ZERO(&fd_r);
  76.   FD_SET(p->fd, &fd_r );
  77.   bp = p->buffer + p->offset;
  78.   bufsize = p->bufsize - p->offset;
  79.   if (p->md.pad > 0) {
  80.     memset(bp, 0, p->md.pad);
  81.     bp += p->md.pad;
  82.     bufsize -= p->md.pad;
  83.   }
  84.   tmp = select_time; /* Because linux mucks with the timeout in select() */
  85.   res = select(p->fd+1, &fd_r, NULL, NULL, &tmp);
  86.   if (res < 0) {
  87.     sprintf(p->errbuf, "select: %s", pcap_strerror(errno));
  88.     return (-1);
  89.   } else if (res > 0) {
  90.     fromlen = sizeof(from);
  91.     while ((cc = recvfrom(p->fd, bp, bufsize, 0, &from, &fromlen)) < 0) {
  92.       /* Don't choke when we get ptraced */
  93.       if (errno != EINTR && errno != EAGAIN) {
  94. sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
  95. return (-1);
  96.       }
  97.     }
  98.     
  99.     if (!strcmp(p->md.device, from.sa_data)) {
  100.       /* If we need have leading zero bytes, adjust count */
  101.       cc += p->md.pad;
  102.       bp = p->buffer + p->offset;
  103.       
  104.       /* If we need to step over leading junk, adjust count and pointer */
  105.       cc -= p->md.skip;
  106.       bp += p->md.skip;
  107.       
  108.       /* Captured length can't exceed our read buffer size */
  109. caplen = cc;
  110. if (caplen > bufsize)
  111.   caplen = bufsize;
  112. /* Captured length can't exceed the snapshot length */
  113. if (caplen > p->snapshot)
  114.   caplen = p->snapshot;
  115. if (p->fcode.bf_insns == NULL ||
  116.     bpf_filter(p->fcode.bf_insns, bp, cc, caplen)) {
  117.   struct pcap_pkthdr h;
  118.   
  119.   ++p->md.stat.ps_recv;
  120.   /* Get timestamp */
  121.   if (ioctl(p->fd, SIOCGSTAMP, &h.ts) < 0) {
  122.     sprintf(p->errbuf, "SIOCGSTAMP: %s",
  123.                             pcap_strerror(errno));
  124.     return (-1);
  125.   }
  126.   h.len = cc;
  127.   h.caplen = caplen;
  128.   (*callback)(user, &h, bp);
  129.   return (1);
  130. }
  131.       }
  132.     }
  133.   gettimeofday(&now, NULL);
  134. } while((timeout == 0 && res) || (TIMEVAL_SUBTRACT(now,start) < timeout * 1000));
  135. return 0;
  136. }
  137. pcap_t *
  138. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  139. {
  140. register int fd, broadcast;
  141. register pcap_t *p;
  142. struct ifreq ifr;
  143. struct sockaddr sa;
  144. timeout = to_ms;
  145. p = (pcap_t *)malloc(sizeof(*p));
  146. if (p == NULL) {
  147. sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  148. return (NULL);
  149. }
  150. memset(p, 0, sizeof(*p));
  151. fd = -1;
  152. fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
  153. if (fd < 0) {
  154. sprintf(ebuf, "socket: %s", pcap_strerror(errno));
  155. goto bad;
  156. }
  157. p->fd = fd;
  158. /* Bind to the interface name */
  159. memset(&sa, 0, sizeof(sa));
  160. sa.sa_family = AF_INET;
  161. (void)strncpy(sa.sa_data, device, sizeof(sa.sa_data));
  162. if (bind(p->fd, &sa, sizeof(sa))) {
  163. sprintf(ebuf, "bind: %s: %s", device, pcap_strerror(errno));
  164. goto bad;
  165. }
  166. memset(&ifr, 0, sizeof(ifr));
  167. strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  168. if (ioctl(p->fd, SIOCGIFHWADDR, &ifr) < 0 ) {
  169. sprintf(ebuf, "SIOCGIFHWADDR: %s", pcap_strerror(errno));
  170. goto bad;
  171. }
  172. broadcast = 0;
  173. switch (ifr.ifr_hwaddr.sa_family) {
  174. case ARPHRD_ETHER:
  175. case ARPHRD_METRICOM:
  176. p->linktype = DLT_EN10MB;
  177. p->offset = 2;
  178. ++broadcast;
  179. break;
  180. case ARPHRD_EETHER:
  181. p->linktype = DLT_EN3MB;
  182. ++broadcast;
  183. break;
  184. case ARPHRD_AX25:
  185. p->linktype = DLT_AX25;
  186. ++broadcast;
  187. break;
  188. #if defined(ARPHRD_IEEE802_TR) && defined(DLT_IEEE802)
  189. case ARPHRD_IEEE802_TR:
  190.                p->linktype = DLT_IEEE802;
  191.                ++broadcast;
  192.                break;
  193. #endif
  194. case ARPHRD_PRONET:
  195. p->linktype = DLT_PRONET;
  196. break;
  197. case ARPHRD_CHAOS:
  198. p->linktype = DLT_CHAOS;
  199. break;
  200. case ARPHRD_IEEE802:
  201. p->linktype = DLT_IEEE802;
  202. ++broadcast;
  203. break;
  204. case ARPHRD_ARCNET:
  205. p->linktype = DLT_ARCNET;
  206. ++broadcast;
  207. break;
  208. case ARPHRD_SLIP:
  209. case ARPHRD_CSLIP:
  210. case ARPHRD_SLIP6:
  211. case ARPHRD_CSLIP6:
  212. case ARPHRD_PPP:
  213. p->linktype = DLT_RAW;
  214. break;
  215. case ARPHRD_LOOPBACK:
  216. p->linktype = DLT_NULL;
  217. p->md.pad = 2;
  218. p->md.skip = 12;
  219. break;
  220. #ifdef ARPHRD_FDDI
  221. /* Not all versions of the kernel has this define */
  222. case ARPHRD_FDDI:
  223. p->linktype = DLT_FDDI;
  224. ++broadcast;
  225. break;
  226. #endif
  227. #ifdef notdef
  228. case ARPHRD_LOCALTLK:
  229. case ARPHRD_NETROM:
  230. case ARPHRD_APPLETLK:
  231. case ARPHRD_DLCI:
  232. case ARPHRD_RSRVD:
  233. case ARPHRD_ADAPT:
  234. case ARPHRD_TUNNEL:
  235. case ARPHRD_TUNNEL6:
  236. case ARPHRD_FRAD:
  237. case ARPHRD_SKIP:
  238. /* XXX currently do not know what to do with these... */
  239. abort();
  240. #endif
  241. default:
  242. sprintf(ebuf, "unknown physical layer type 0x%x",
  243.     ifr.ifr_hwaddr.sa_family);
  244. goto bad;
  245. }
  246. /* Base the buffer size on the interface MTU */
  247. memset(&ifr, 0, sizeof(ifr));
  248. strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  249. if (ioctl(p->fd, SIOCGIFMTU, &ifr) < 0 ) {
  250. sprintf(ebuf, "SIOCGIFMTU: %s", pcap_strerror(errno));
  251. goto bad;
  252. }
  253. /* Leave room for link header (which is never large under linux...) */
  254. p->bufsize = ifr.ifr_mtu + 64;
  255. p->buffer = (u_char *)malloc(p->bufsize + p->offset);
  256. if (p->buffer == NULL) {
  257. sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  258. goto bad;
  259. }
  260. /* XXX */
  261. if (promisc && broadcast) {
  262. memset(&ifr, 0, sizeof(ifr));
  263. strcpy(ifr.ifr_name, device);
  264. if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) {
  265. sprintf(ebuf, "SIOCGIFFLAGS: %s", pcap_strerror(errno));
  266. goto bad;
  267. }
  268. saved_ifr = ifr;
  269. ifr.ifr_flags |= IFF_PROMISC;
  270. if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) {
  271. sprintf(ebuf, "SIOCSIFFLAGS: %s", pcap_strerror(errno));
  272. goto bad;
  273. }
  274. ifr.ifr_flags &= ~IFF_PROMISC;
  275. atexit(linux_restore_ifr);
  276. }
  277. p->md.device = strdup(device);
  278. if (p->md.device == NULL) {
  279. sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  280. goto bad;
  281. }
  282. p->snapshot = snaplen;
  283. return (p);
  284. bad:
  285. if (fd >= 0)
  286. (void)close(fd);
  287. if (p->buffer != NULL)
  288. free(p->buffer);
  289. if (p->md.device != NULL)
  290. free(p->md.device);
  291. free(p);
  292. return (NULL);
  293. }
  294. int
  295. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  296. {
  297. p->fcode = *fp;
  298. return (0);
  299. }
  300. void
  301. linux_restore_ifr(void)
  302. {
  303. register int fd;
  304. fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  305. if (fd < 0)
  306. fprintf(stderr, "linux socket: %s", pcap_strerror(errno));
  307. else if (ioctl(fd, SIOCSIFFLAGS, &saved_ifr) < 0)
  308. fprintf(stderr, "linux SIOCSIFFLAGS: %s", pcap_strerror(errno));
  309. }