1 /* 2 * Reimplementation of winpcap pcap-remote.c 3 * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) 4 * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the Politecnico di Torino, CACE Technologies 17 * nor the names of its contributors may be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifdef HAVE_CONFIG_H 35 #include "config.h" 36 #endif 37 38 #include "pcap-int.h" 39 40 #ifdef NEED_STRERROR_H 41 #include "strerror.h" 42 #endif 43 44 #include <errno.h> 45 #include <stdlib.h> 46 #include <unistd.h> 47 #include <string.h> 48 #include <sys/socket.h> 49 #include <arpa/inet.h> 50 51 #include <time.h> 52 #include <sys/time.h> 53 #include <netinet/in.h> 54 #include <sys/types.h> 55 56 #include "pcap-rpcap-unix.h" 57 58 #define RPCAP_IFACE "rpcap://" 59 60 /* default */ 61 #define RPCAP_DEFAULT_NETPORT 2002 62 63 /* version */ 64 #define RPCAP_VERSION_EXPERIMENTAL 0 65 66 /* packets */ 67 #define RPCAP_MSG_ERROR 1 /*!< Message that keeps an error notification */ 68 #define RPCAP_MSG_OPEN_REQ 3 /*!< Request to open a remote device */ 69 #define RPCAP_MSG_STARTCAP_REQ 4 /*!< Request to start a capture on a remote device */ 70 #define RPCAP_MSG_UPDATEFILTER_REQ 5 /*!< Send a compiled filter into the remote device */ 71 #define RPCAP_MSG_PACKET 7 /*!< This is a 'data' message, which carries a network packet */ 72 #define RPCAP_MSG_AUTH_REQ 8 /*!< Message that keeps the authentication parameters */ 73 #define RPCAP_MSG_STATS_REQ 9 /*!< It requires to have network statistics */ 74 75 #define RPCAP_UPDATEFILTER_BPF 1 /*!< This code tells us that the filter is encoded with the BPF/NPF syntax */ 76 77 static unsigned short 78 get16(const unsigned char *buf) 79 { 80 unsigned short val; 81 82 val = buf[0]; 83 val = val << 8 | buf[1]; 84 return val; 85 } 86 87 static void 88 put16(unsigned char *buf, unsigned int val) 89 { 90 buf[0] = val >> 8; 91 buf[1] = val >> 0; 92 } 93 94 static unsigned int 95 get32(const unsigned char *buf) 96 { 97 unsigned int val; 98 99 val = buf[0]; 100 val = val << 8 | buf[1]; 101 val = val << 8 | buf[2]; 102 val = val << 8 | buf[3]; 103 return val; 104 } 105 106 static void 107 put32(unsigned char *buf, unsigned int val) 108 { 109 buf[0] = val >> 24; 110 buf[1] = val >> 16; 111 buf[2] = val >> 8; 112 buf[3] = val >> 0; 113 } 114 115 static int 116 rpcap_recv_pkt(pcap_t *p, int fd, unsigned char *recv_buf, unsigned int buflen) 117 { 118 static unsigned char discard[1024]; 119 120 size_t mlen; 121 int ret; 122 unsigned char *buf; 123 unsigned int len; 124 unsigned int pkt_len; 125 126 unsigned char hdr[8]; 127 int pkt_type; 128 129 /* read header loop */ 130 buf = hdr; 131 len = 8; 132 133 ret = 0; 134 do { 135 buf += ret; 136 len -= ret; 137 138 do { 139 ret = read(fd, buf, len); 140 if (p->break_loop) { 141 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "break-loop"); 142 p->break_loop = 0; 143 return -2; 144 } 145 } while (ret == -1 && errno == EINTR); 146 } while (ret > 0 && len-ret); 147 148 if (ret <= 0) { 149 if (!ret) 150 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection closed"); 151 else 152 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection error (%s)", strerror(errno)); 153 return -1; 154 } 155 156 if (hdr[0] != RPCAP_VERSION_EXPERIMENTAL) { 157 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: incorrect reply version (%.2x)", hdr[0]); 158 return -1; 159 } 160 161 pkt_type = (unsigned char) hdr[1]; 162 pkt_len = get32(&hdr[4]); 163 164 if (pkt_type == RPCAP_MSG_ERROR) { 165 recv_buf = (unsigned char *)p->errbuf; 166 buflen = PCAP_ERRBUF_SIZE-1; 167 } 168 169 buf = recv_buf; 170 171 /* read payload loop */ 172 if (pkt_len) { 173 ret = 0; 174 len = pkt_len; 175 do { 176 buf += ret; 177 buflen -= ret; 178 len -= ret; 179 180 if (!buflen) { 181 buf = discard; 182 buflen = sizeof(discard); 183 } 184 185 mlen = (len < 0x7fff) ? len : 0x7fff; 186 187 if (mlen > buflen) 188 mlen = buflen; 189 190 do { 191 ret = read(fd, buf, mlen); 192 if (p->break_loop) { 193 p->break_loop = 0; 194 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "break-loop"); 195 return -2; 196 } 197 } while (ret == -1 && errno == EINTR); 198 } while (ret > 0 && len-ret); 199 200 if (ret <= 0) { 201 if (!ret) 202 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection closed"); 203 else 204 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection error (%s)", strerror(errno)); 205 return -1; 206 } 207 buf += ret; 208 } 209 210 /* always NUL terminate errbuf, and signal error */ 211 if (pkt_type == RPCAP_MSG_ERROR) { 212 *buf = '\0'; 213 return -1; 214 } 215 return pkt_len; 216 } 217 218 static int 219 rpcap_send_pkt(pcap_t *p, const unsigned char *send_buf, unsigned int len) 220 { 221 size_t mlen; 222 int ret; 223 224 /* send loop */ 225 ret = 0; 226 do { 227 send_buf += ret; 228 len -= ret; 229 230 mlen = (len < 0x7fff) ? len : 0x7fff; 231 232 do { 233 ret = write(p->fd, send_buf, mlen); 234 if (p->break_loop) { 235 p->break_loop = 0; 236 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "break-loop"); 237 return -2; 238 } 239 } while (ret == -1 && errno == EINTR); 240 } while (ret > 0 && len-ret); 241 242 if (ret <= 0) { 243 if (!ret) 244 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection closed"); 245 else 246 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: connection error (%s)", strerror(errno)); 247 return -1; 248 } 249 return 0; 250 } 251 252 static int 253 rpcap_send_request(pcap_t *p, char type, unsigned char *buf, unsigned int payload_len) 254 { 255 buf[0] = RPCAP_VERSION_EXPERIMENTAL; 256 buf[1] = type; 257 buf[2] = buf[3] = 0; 258 put32(&buf[4], payload_len); 259 260 return rpcap_send_pkt(p, buf, 8+payload_len); 261 } 262 263 static int 264 rpcap_send_request_auth(pcap_t *p, const char *username, const char *password) 265 { 266 267 if (username || password) { 268 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: auth not supported (yet!)"); 269 return -1; 270 271 } else { 272 static const unsigned char login_null_pkt[16] = { 273 RPCAP_VERSION_EXPERIMENTAL, 274 RPCAP_MSG_AUTH_REQ, 275 0, 0, 276 0, 0, 0, 8, 277 278 0, 0, 0, 0, 0, 0, 0, 0 279 }; 280 281 if (rpcap_send_pkt(p, login_null_pkt, sizeof(login_null_pkt))) 282 return -1; 283 } 284 285 return rpcap_recv_pkt(p, p->fd, NULL, 0); 286 } 287 288 static int 289 rpcap_send_request_open(pcap_t *p, const char *interface) 290 { 291 const size_t interface_len = strlen(interface); 292 293 unsigned char buf_open[8+255] = { 294 RPCAP_VERSION_EXPERIMENTAL, 295 RPCAP_MSG_OPEN_REQ, 296 0, 0, 297 0, 0, 0, interface_len 298 }; 299 300 unsigned char reply_buf[8]; 301 int reply_len; 302 303 if (interface_len > 255) { 304 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "rpcap: maximum interface length: 255"); 305 return -1; 306 } 307 308 memcpy(buf_open + 8, interface, interface_len); 309 if (rpcap_send_pkt(p, buf_open, 8 + interface_len)) 310 return -1; 311 312 reply_len = rpcap_recv_pkt(p, p->fd, reply_buf, sizeof(reply_buf)); 313 if (reply_len != sizeof(reply_buf)) { 314 if (reply_len >= 0) 315 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (openreply: %u)", reply_len); 316 return -1; 317 } 318 319 p->linktype = get32(&reply_buf[0]); 320 p->tzoff = get32(&reply_buf[4]); 321 322 return 0; 323 } 324 325 static int 326 rpcap_send_request_start(pcap_t *p, struct in_addr *server_ip) 327 { 328 unsigned char buf_start[8+12+8+8] = { 329 RPCAP_VERSION_EXPERIMENTAL, 330 RPCAP_MSG_STARTCAP_REQ, 331 0, 0, 332 0, 0, 0, 12+8+8, 333 /* rpcap_startcapreq (12B) */ 334 0xff, 0xff, 0xff, 0xff, /* snaplen */ 335 0xff, 0xff, 0xff, 0xff, /* timeout */ 336 0x00, 0x00, /* flags */ 337 0x00, 0x00, /* portdata */ 338 /* rpcap_filter (8B+8B) */ 339 0x00, RPCAP_UPDATEFILTER_BPF, /* filtertype */ 340 0x00, 0x00, 341 0x00, 0x00, 0x00, 0x01, 342 343 0x00, 0x06, /* ret */ 344 0x00, 345 0x00, 346 0x00, 0x00, 0xff, 0xff /* #65535 */ 347 }; 348 349 struct sockaddr_in sin; 350 unsigned char reply_buf[8]; 351 int reply_len; 352 int fd; 353 354 unsigned short portdata; 355 356 put32(&buf_start[8], p->snapshot); /* snaplen */ 357 put32(&buf_start[12], p->opt.timeout/2); /* read_timeout */ 358 359 if (rpcap_send_pkt(p, buf_start, sizeof(buf_start))) 360 return -1; 361 362 reply_len = rpcap_recv_pkt(p, p->fd, reply_buf, sizeof(reply_buf)); 363 if (reply_len != sizeof(reply_buf)) { 364 if (reply_len >= 0) 365 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (startreply: %u)", reply_len); 366 return -1; 367 } 368 369 get32(&reply_buf[0]); 370 portdata = get16(&reply_buf[4]); 371 372 fd = socket(AF_INET, SOCK_STREAM, 0); 373 if (fd < 0) { 374 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 375 "Can't create data socket %d:%s", 376 errno, pcap_strerror(errno)); 377 return -1; 378 } 379 sin.sin_family = AF_INET; 380 sin.sin_addr = *server_ip; 381 sin.sin_port = htons(portdata); 382 383 if (connect(fd, (struct sockaddr *) &sin, sizeof(sin))) { 384 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 385 "Can't connect to data socket (%d:%s)", 386 errno, pcap_strerror(errno)); 387 return -1; 388 } 389 p->selectable_fd = fd; 390 391 return 0; 392 } 393 394 static int 395 rpcap_inject_common(pcap_t *handle, const void *buf, size_t size) 396 { 397 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported with remote capture"); 398 return -1; 399 } 400 401 static int 402 rpcap_stats_common(pcap_t *handle, struct pcap_stat *stats) 403 { 404 static const unsigned char buf_stats[8] = { 405 RPCAP_VERSION_EXPERIMENTAL, 406 RPCAP_MSG_STATS_REQ, 407 0, 0, 408 0, 0, 0, 0 409 }; 410 411 unsigned char reply_buf[16]; 412 int reply_len; 413 414 /* local */ 415 #if 0 416 stats->ps_recv = handle->md.packets_read; 417 stats->ps_drop = 0; 418 stats->ps_ifdrop = 0; 419 #endif 420 421 /* remote */ 422 if (rpcap_send_pkt(handle, buf_stats, sizeof(buf_stats))) 423 return -1; 424 425 reply_len = rpcap_recv_pkt(handle, handle->fd, reply_buf, sizeof(reply_buf)); 426 if (reply_len != sizeof(reply_buf)) { 427 if (reply_len >= 0) 428 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (statsreply: %u)", reply_len); 429 return -1; 430 } 431 432 stats->ps_recv = get32(&reply_buf[0]); 433 stats->ps_ifdrop = get32(&reply_buf[4]); 434 stats->ps_drop = get32(&reply_buf[8]); 435 return 0; 436 } 437 438 static int 439 rpcap_setfilter_common(pcap_t *handle, struct bpf_program *prog) 440 { 441 unsigned char *buf_setfilter; 442 443 /* update local filter */ 444 if (install_bpf_program(handle, prog) == -1) 445 return -1; 446 447 /* update remote filter */ 448 if (prog->bf_len < 0xfffff) { 449 unsigned int data_size = 8 + 8 * prog->bf_len; 450 unsigned char *buf_filter; 451 unsigned char *buf_insn; 452 size_t i; 453 454 buf_setfilter = malloc(8 + data_size); 455 if (!buf_setfilter) { 456 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "No memory for setfilter packet"); 457 return -1; 458 } 459 460 buf_filter = &buf_setfilter[8]; 461 buf_insn = &buf_filter[8]; 462 463 put16(&buf_filter[0], RPCAP_UPDATEFILTER_BPF); 464 put16(&buf_filter[2], 0); 465 put32(&buf_filter[4], prog->bf_len); 466 467 for (i = 0; i < prog->bf_len; i++) { 468 unsigned char *data = &buf_insn[i * 8]; 469 470 put16(&data[0], prog->bf_insns[i].code); 471 data[2] = prog->bf_insns[i].jt; 472 data[3] = prog->bf_insns[i].jf; 473 put32(&data[4], prog->bf_insns[i].k); 474 } 475 476 if (rpcap_send_request(handle, RPCAP_MSG_UPDATEFILTER_REQ, buf_setfilter, data_size)) { 477 free(buf_setfilter); 478 return -1; 479 } 480 free(buf_setfilter); 481 482 if (rpcap_recv_pkt(handle, handle->fd, NULL, 0) < 0) 483 return -1; 484 } 485 return 0; 486 } 487 488 static int 489 rpcap_read_unix(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) 490 { 491 struct pcap_pkthdr pkth; 492 const unsigned char *pkt; 493 const unsigned char *buf; 494 unsigned int pkt_len; 495 int count = 0; 496 497 pkt_len = rpcap_recv_pkt(handle, handle->selectable_fd, handle->buffer, handle->bufsize); 498 if (pkt_len < 20) { 499 if (pkt_len == 0) { 500 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pkt_len check failed (%u < 20)", pkt_len); 501 return -1; 502 } 503 return pkt_len; 504 } 505 buf = handle->buffer; 506 507 /* local */ 508 #if 0 509 gettimeofday(&pkth.ts, NULL); 510 pkth.caplen = pkth.len = pkt_len - 20 511 #endif 512 /* remote */ 513 pkth.ts.tv_sec = get32(&buf[0]); 514 pkth.ts.tv_usec = get32(&buf[4]); 515 pkth.caplen = get32(&buf[8]); 516 pkth.len = get32(&buf[12]); 517 /* pktnr */ 518 pkt = &buf[20]; 519 520 /* sanity caplen */ 521 if (pkt_len - 20 < pkth.caplen) { 522 /* pkt.caplen = pkt_len - 20; */ 523 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pkth.caplen check failed (%u < %u)", pkt_len - 20, pkth.caplen); 524 return -1; 525 } 526 527 if (handle->fcode.bf_insns == NULL || 528 bpf_filter(handle->fcode.bf_insns, pkt, pkth.len, pkth.caplen)) 529 { 530 // handle->md.packets_read++; 531 callback(user, &pkth, pkt); 532 count++; 533 } 534 return count; 535 } 536 537 static void 538 rpcap_cleanup(pcap_t *handle) 539 { 540 if (handle->selectable_fd != handle->fd) { 541 int fd = handle->selectable_fd; 542 543 if (fd != -1) { 544 handle->selectable_fd = -1; 545 close(fd); 546 } 547 } 548 pcap_cleanup_live_common(handle); 549 } 550 551 static int 552 rpcap_activate(pcap_t *handle) 553 { 554 const char *dev = handle->opt.device; 555 const char *tmp; 556 557 char *host; 558 char *username = NULL; 559 char *password = NULL; 560 const char *interface = NULL; 561 int port; 562 563 struct sockaddr_in sin; 564 565 /* rpcap[s]://login:password@host:port/interface */ 566 if (strncmp(dev, RPCAP_IFACE, strlen(RPCAP_IFACE)) == 0) { 567 port = RPCAP_DEFAULT_NETPORT; 568 dev += strlen(RPCAP_IFACE); 569 570 } /* else if (strncmp(dev, "rpcaps://", strlen("rpcaps://")) == 0) { 571 port = RPCAP_DEFAULT_NETPORT_SSL; 572 dev += strlen("rpcaps://"); 573 574 } */ else { 575 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid protocol"); 576 return PCAP_ERROR; 577 } 578 579 if ((tmp = strchr(dev, '@'))) { 580 char *ptmp; 581 582 if ((ptmp = strchr(dev, ':'))) { 583 username = strndup(dev, ptmp-dev); 584 password = strndup(ptmp+1, tmp-(ptmp+1)); 585 586 } else { 587 username = strndup(dev, tmp-dev); 588 589 /* XXX, ask for password? */ 590 } 591 592 dev = tmp + 1; 593 } 594 595 if (*dev == '[') { 596 tmp = strchr(dev, ']'); 597 if (!tmp) { 598 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid host (missing ']')"); 599 return PCAP_ERROR; 600 } 601 602 host = strndup(dev+1, tmp-(dev+1)); 603 604 dev = tmp + 1; 605 } else { 606 tmp = strchr(dev, ':'); 607 if (!tmp) 608 tmp = strchr(dev, '/'); 609 610 if (tmp) { 611 host = strndup(dev, tmp-dev); 612 dev = tmp; 613 } else 614 host = strdup(dev); 615 } 616 617 if (*dev == ':') { 618 char *end; 619 620 if (dev[1] == '\0') { 621 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: missing port"); 622 return PCAP_ERROR; 623 } 624 625 port = strtol(dev + 1, &end, 10); 626 if (port < 1 || port > 65535) { 627 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid port"); 628 return PCAP_ERROR; 629 } 630 631 dev = end; 632 } 633 634 if (*dev == '/') 635 interface = dev+1; 636 637 if (!host) { 638 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: couldn't parse host"); 639 return PCAP_ERROR; 640 } 641 642 if (!interface) { 643 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: couldn't parse interface"); 644 return PCAP_ERROR; 645 } 646 647 /* XXX, gethostbyname, ipv6, etc... */ 648 sin.sin_family = AF_INET; 649 sin.sin_addr.s_addr = inet_addr(host); 650 sin.sin_port = htons(port); 651 if (sin.sin_addr.s_addr == INADDR_NONE) { 652 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: not ipv4 address"); 653 goto free_fail; 654 } 655 656 /* Initialize some components of the pcap structure. */ 657 handle->offset = 20; 658 handle->bufsize = handle->snapshot + handle->offset; 659 handle->linktype = -1; /* invalid for now */ 660 handle->read_op = rpcap_read_unix; 661 handle->setfilter_op = rpcap_setfilter_common; 662 handle->inject_op = rpcap_inject_common; 663 handle->setdirection_op = NULL; 664 handle->set_datalink_op = NULL; /* not possible */ 665 handle->getnonblock_op = pcap_getnonblock_fd; 666 handle->setnonblock_op = pcap_setnonblock_fd; 667 handle->stats_op = rpcap_stats_common; 668 handle->cleanup_op = rpcap_cleanup; 669 670 /* Create socket */ 671 handle->fd = socket(AF_INET, SOCK_STREAM, 0); 672 handle->selectable_fd = -1; 673 if (handle->fd < 0) { 674 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 675 "Can't create socket %d:%s", 676 errno, pcap_strerror(errno)); 677 goto close_fail; 678 } 679 680 if (connect(handle->fd, (struct sockaddr *) &sin, sizeof(sin))) { 681 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 682 "Can't connect to %s:%d (%d:%s)", 683 host, port, errno, pcap_strerror(errno)); 684 goto free_fail; 685 } 686 687 /* login */ 688 if (rpcap_send_request_auth(handle, username, password) < 0) 689 goto close_fail; 690 if (rpcap_send_request_open(handle, interface) < 0) 691 goto close_fail; 692 if (rpcap_send_request_start(handle, &(sin.sin_addr)) < 0) 693 goto close_fail; 694 695 handle->buffer = malloc(handle->bufsize); 696 if (!handle->buffer) { 697 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 698 "Can't allocate dump buffer: %s", 699 pcap_strerror(errno)); 700 goto close_fail; 701 } 702 703 if (handle->opt.rfmon) { 704 /* 705 * Monitor mode doesn't apply to rpcap. 706 */ 707 rpcap_cleanup(handle); 708 return PCAP_ERROR_RFMON_NOTSUP; 709 } 710 711 if (handle->opt.buffer_size != 0) { 712 /* 713 * Set the socket buffer size to the specified value. 714 */ 715 if (setsockopt(handle->selectable_fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) { 716 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno)); 717 goto close_fail; 718 } 719 } 720 free(username); 721 free(password); 722 free(host); 723 724 return 0; 725 726 close_fail: 727 rpcap_cleanup(handle); 728 free_fail: 729 free(username); 730 free(password); 731 free(host); 732 return PCAP_ERROR; 733 } 734 735 pcap_t * 736 rpcap_create(const char *device, char *err_str, int *is_ours) 737 { 738 const char *cp = device; 739 pcap_t *p; 740 741 if (strncmp(cp, RPCAP_IFACE, strlen(RPCAP_IFACE)) == 0) 742 cp += strlen(RPCAP_IFACE); 743 else { 744 *is_ours = 0; 745 return NULL; 746 } 747 748 if (*cp == '\0') { 749 *is_ours = 0; 750 return NULL; 751 } 752 753 *is_ours = 1; 754 755 p = pcap_create_common(__UNCONST(device), 16384); 756 if (p == NULL) 757 return NULL; 758 759 p->activate_op = rpcap_activate; 760 return p; 761 } 762 763