1 /* 2 * Copyright (c) 1993, 1994, 1995, 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[] _U_ = 23 "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.45.2.5 2004/03/21 08:33:24 guy Exp $ (LBL)"; 24 #endif 25 26 #ifdef HAVE_CONFIG_H 27 #include "config.h" 28 #endif 29 30 #include <sys/param.h> 31 #include <sys/file.h> 32 #include <sys/ioctl.h> 33 #include <sys/socket.h> 34 #include <sys/time.h> 35 36 #include <net/raw.h> 37 #include <net/if.h> 38 39 #include <netinet/in.h> 40 #include <netinet/in_systm.h> 41 #include <netinet/ip.h> 42 #include <netinet/if_ether.h> 43 #include <netinet/ip_var.h> 44 #include <netinet/udp.h> 45 #include <netinet/udp_var.h> 46 #include <netinet/tcp.h> 47 #include <netinet/tcpip.h> 48 49 #include <errno.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 55 #include "pcap-int.h" 56 57 #ifdef HAVE_OS_PROTO_H 58 #include "os-proto.h" 59 #endif 60 61 static int 62 pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 63 { 64 int cc; 65 register struct snoopheader *sh; 66 register int datalen; 67 register int caplen; 68 register u_char *cp; 69 70 again: 71 /* 72 * Has "pcap_breakloop()" been called? 73 */ 74 if (p->break_loop) { 75 /* 76 * Yes - clear the flag that indicates that it 77 * has, and return -2 to indicate that we were 78 * told to break out of the loop. 79 */ 80 p->break_loop = 0; 81 return (-2); 82 } 83 cc = read(p->fd, (char *)p->buffer, p->bufsize); 84 if (cc < 0) { 85 /* Don't choke when we get ptraced */ 86 switch (errno) { 87 88 case EINTR: 89 goto again; 90 91 case EWOULDBLOCK: 92 return (0); /* XXX */ 93 } 94 snprintf(p->errbuf, sizeof(p->errbuf), 95 "read: %s", pcap_strerror(errno)); 96 return (-1); 97 } 98 sh = (struct snoopheader *)p->buffer; 99 datalen = sh->snoop_packetlen; 100 caplen = (datalen < p->snapshot) ? datalen : p->snapshot; 101 cp = (u_char *)(sh + 1) + p->offset; /* XXX */ 102 103 /* 104 * XXX unfortunately snoop loopback isn't exactly like 105 * BSD's. The address family is encoded in the first 2 106 * bytes rather than the first 4 bytes! Luckily the last 107 * two snoop loopback bytes are zeroed. 108 */ 109 if (p->linktype == DLT_NULL && *((short *)(cp + 2)) == 0) { 110 u_int *uip = (u_int *)cp; 111 *uip >>= 16; 112 } 113 114 if (p->fcode.bf_insns == NULL || 115 bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) { 116 struct pcap_pkthdr h; 117 ++p->md.stat.ps_recv; 118 h.ts.tv_sec = sh->snoop_timestamp.tv_sec; 119 h.ts.tv_usec = sh->snoop_timestamp.tv_usec; 120 h.len = datalen; 121 h.caplen = caplen; 122 (*callback)(user, &h, cp); 123 return (1); 124 } 125 return (0); 126 } 127 128 static int 129 pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps) 130 { 131 register struct rawstats *rs; 132 struct rawstats rawstats; 133 134 rs = &rawstats; 135 memset(rs, 0, sizeof(*rs)); 136 if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) { 137 snprintf(p->errbuf, sizeof(p->errbuf), 138 "SIOCRAWSTATS: %s", pcap_strerror(errno)); 139 return (-1); 140 } 141 142 /* 143 * "ifdrops" are those dropped by the network interface 144 * due to resource shortages or hardware errors. 145 * 146 * "sbdrops" are those dropped due to socket buffer limits. 147 * 148 * As filter is done in userland, "sbdrops" counts packets 149 * regardless of whether they would've passed the filter. 150 * 151 * XXX - does this count *all* Snoop or Drain sockets, 152 * rather than just this socket? If not, why does it have 153 * both Snoop and Drain statistics? 154 */ 155 p->md.stat.ps_drop = 156 rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops + 157 rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops; 158 159 /* 160 * "ps_recv" counts only packets that passed the filter. 161 * As filtering is done in userland, this does not include 162 * packets dropped because we ran out of buffer space. 163 */ 164 *ps = p->md.stat; 165 return (0); 166 } 167 168 static void 169 pcap_close_snoop(pcap_t *p) 170 { 171 if (p->buffer != NULL) 172 free(p->buffer); 173 if (p->fd >= 0) 174 close(p->fd); 175 } 176 177 /* XXX can't disable promiscuous */ 178 pcap_t * 179 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 180 char *ebuf) 181 { 182 int fd; 183 struct sockaddr_raw sr; 184 struct snoopfilter sf; 185 u_int v; 186 int ll_hdrlen; 187 int snooplen; 188 pcap_t *p; 189 struct ifreq ifr; 190 191 p = (pcap_t *)malloc(sizeof(*p)); 192 if (p == NULL) { 193 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", 194 pcap_strerror(errno)); 195 return (NULL); 196 } 197 memset(p, 0, sizeof(*p)); 198 fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP); 199 if (fd < 0) { 200 snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop socket: %s", 201 pcap_strerror(errno)); 202 goto bad; 203 } 204 p->fd = fd; 205 memset(&sr, 0, sizeof(sr)); 206 sr.sr_family = AF_RAW; 207 (void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname)); 208 if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) { 209 snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop bind: %s", 210 pcap_strerror(errno)); 211 goto bad; 212 } 213 memset(&sf, 0, sizeof(sf)); 214 if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) { 215 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s", 216 pcap_strerror(errno)); 217 goto bad; 218 } 219 v = 64 * 1024; 220 (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v)); 221 /* 222 * XXX hack - map device name to link layer type 223 */ 224 if (strncmp("et", device, 2) == 0 || /* Challenge 10 Mbit */ 225 strncmp("ec", device, 2) == 0 || /* Indigo/Indy 10 Mbit, 226 O2 10/100 */ 227 strncmp("ef", device, 2) == 0 || /* O200/2000 10/100 Mbit */ 228 strncmp("eg", device, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */ 229 strncmp("gfe", device, 3) == 0 || /* GIO 100 Mbit */ 230 strncmp("fxp", device, 3) == 0 || /* Challenge VME Enet */ 231 strncmp("ep", device, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */ 232 strncmp("vfe", device, 3) == 0 || /* Challenge VME 100Mbit */ 233 strncmp("fa", device, 2) == 0 || 234 strncmp("qaa", device, 3) == 0 || 235 strncmp("cip", device, 3) == 0 || 236 strncmp("el", device, 2) == 0) { 237 p->linktype = DLT_EN10MB; 238 p->offset = RAW_HDRPAD(sizeof(struct ether_header)); 239 ll_hdrlen = sizeof(struct ether_header); 240 } else if (strncmp("ipg", device, 3) == 0 || 241 strncmp("rns", device, 3) == 0 || /* O2/200/2000 FDDI */ 242 strncmp("xpi", device, 3) == 0) { 243 p->linktype = DLT_FDDI; 244 p->offset = 3; /* XXX yeah? */ 245 ll_hdrlen = 13; 246 } else if (strncmp("ppp", device, 3) == 0) { 247 p->linktype = DLT_RAW; 248 ll_hdrlen = 0; /* DLT_RAW meaning "no PPP header, just the IP packet"? */ 249 } else if (strncmp("qfa", device, 3) == 0) { 250 p->linktype = DLT_IP_OVER_FC; 251 ll_hdrlen = 24; 252 } else if (strncmp("pl", device, 2) == 0) { 253 p->linktype = DLT_RAW; 254 ll_hdrlen = 0; /* Cray UNICOS/mp pseudo link */ 255 } else if (strncmp("lo", device, 2) == 0) { 256 p->linktype = DLT_NULL; 257 ll_hdrlen = 4; 258 } else { 259 snprintf(ebuf, PCAP_ERRBUF_SIZE, 260 "snoop: unknown physical layer type"); 261 goto bad; 262 } 263 #ifdef SIOCGIFMTU 264 /* 265 * XXX - IRIX appears to give you an error if you try to set the 266 * capture length to be greater than the MTU, so let's try to get 267 * the MTU first and, if that succeeds, trim the snap length 268 * to be no greater than the MTU. 269 */ 270 (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 271 if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) { 272 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s", 273 pcap_strerror(errno)); 274 goto bad; 275 } 276 /* 277 * OK, we got it. 278 * 279 * XXX - some versions of IRIX 6.5 define "ifr_mtu" and have an 280 * "ifru_metric" member of the "ifr_ifru" union in an "ifreq" 281 * structure, others don't. 282 * 283 * I've no idea what's going on, so, if "ifr_mtu" isn't defined, 284 * we define it as "ifr_metric", as using that field appears to 285 * work on the versions that lack "ifr_mtu" (and, on those that 286 * don't lack it, "ifru_metric" and "ifru_mtu" are both "int" 287 * members of the "ifr_ifru" union, which suggests that they 288 * may be interchangeable in this case). 289 */ 290 #ifndef ifr_mtu 291 #define ifr_mtu ifr_metric 292 #endif 293 if (snaplen > ifr.ifr_mtu + ll_hdrlen) 294 snaplen = ifr.ifr_mtu + ll_hdrlen; 295 #endif 296 297 /* 298 * The argument to SIOCSNOOPLEN is the number of link-layer 299 * payload bytes to capture - it doesn't count link-layer 300 * header bytes. 301 */ 302 snooplen = snaplen - ll_hdrlen; 303 if (snooplen < 0) 304 snooplen = 0; 305 if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) { 306 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s", 307 pcap_strerror(errno)); 308 goto bad; 309 } 310 p->snapshot = snaplen; 311 v = 1; 312 if (ioctl(fd, SIOCSNOOPING, &v) < 0) { 313 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s", 314 pcap_strerror(errno)); 315 goto bad; 316 } 317 318 p->bufsize = 4096; /* XXX */ 319 p->buffer = (u_char *)malloc(p->bufsize); 320 if (p->buffer == NULL) { 321 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", 322 pcap_strerror(errno)); 323 goto bad; 324 } 325 326 /* 327 * "p->fd" is a socket, so "select()" should work on it. 328 */ 329 p->selectable_fd = p->fd; 330 331 p->read_op = pcap_read_snoop; 332 p->setfilter_op = install_bpf_program; /* no kernel filtering */ 333 p->set_datalink_op = NULL; /* can't change data link type */ 334 p->getnonblock_op = pcap_getnonblock_fd; 335 p->setnonblock_op = pcap_setnonblock_fd; 336 p->stats_op = pcap_stats_snoop; 337 p->close_op = pcap_close_snoop; 338 339 return (p); 340 bad: 341 (void)close(fd); 342 free(p); 343 return (NULL); 344 } 345 346 int 347 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 348 { 349 return (0); 350 } 351