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 #if 0 321 p->tzoff = get32(&reply_buf[4]); 322 #endif 323 324 return 0; 325 } 326 327 static int 328 rpcap_send_request_start(pcap_t *p, struct in_addr *server_ip) 329 { 330 unsigned char buf_start[8+12+8+8] = { 331 RPCAP_VERSION_EXPERIMENTAL, 332 RPCAP_MSG_STARTCAP_REQ, 333 0, 0, 334 0, 0, 0, 12+8+8, 335 /* rpcap_startcapreq (12B) */ 336 0xff, 0xff, 0xff, 0xff, /* snaplen */ 337 0xff, 0xff, 0xff, 0xff, /* timeout */ 338 0x00, 0x00, /* flags */ 339 0x00, 0x00, /* portdata */ 340 /* rpcap_filter (8B+8B) */ 341 0x00, RPCAP_UPDATEFILTER_BPF, /* filtertype */ 342 0x00, 0x00, 343 0x00, 0x00, 0x00, 0x01, 344 345 0x00, 0x06, /* ret */ 346 0x00, 347 0x00, 348 0x00, 0x00, 0xff, 0xff /* #65535 */ 349 }; 350 351 struct sockaddr_in sin; 352 unsigned char reply_buf[8]; 353 int reply_len; 354 int fd; 355 356 unsigned short portdata; 357 358 put32(&buf_start[8], p->snapshot); /* snaplen */ 359 put32(&buf_start[12], p->opt.timeout/2); /* read_timeout */ 360 361 if (rpcap_send_pkt(p, buf_start, sizeof(buf_start))) 362 return -1; 363 364 reply_len = rpcap_recv_pkt(p, p->fd, reply_buf, sizeof(reply_buf)); 365 if (reply_len != sizeof(reply_buf)) { 366 if (reply_len >= 0) 367 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (startreply: %u)", reply_len); 368 return -1; 369 } 370 371 get32(&reply_buf[0]); 372 portdata = get16(&reply_buf[4]); 373 374 fd = socket(AF_INET, SOCK_STREAM, 0); 375 if (fd < 0) { 376 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 377 "Can't create data socket %d:%s", 378 errno, pcap_strerror(errno)); 379 return -1; 380 } 381 sin.sin_family = AF_INET; 382 sin.sin_addr = *server_ip; 383 sin.sin_port = htons(portdata); 384 385 if (connect(fd, (struct sockaddr *) &sin, sizeof(sin))) { 386 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 387 "Can't connect to data socket (%d:%s)", 388 errno, pcap_strerror(errno)); 389 return -1; 390 } 391 p->selectable_fd = fd; 392 393 return 0; 394 } 395 396 static int 397 rpcap_inject_common(pcap_t *handle, const void *buf, size_t size) 398 { 399 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported with remote capture"); 400 return -1; 401 } 402 403 static int 404 rpcap_stats_common(pcap_t *handle, struct pcap_stat *stats) 405 { 406 static const unsigned char buf_stats[8] = { 407 RPCAP_VERSION_EXPERIMENTAL, 408 RPCAP_MSG_STATS_REQ, 409 0, 0, 410 0, 0, 0, 0 411 }; 412 413 unsigned char reply_buf[16]; 414 int reply_len; 415 416 /* local */ 417 #if 0 418 stats->ps_recv = handle->md.packets_read; 419 stats->ps_drop = 0; 420 stats->ps_ifdrop = 0; 421 #endif 422 423 /* remote */ 424 if (rpcap_send_pkt(handle, buf_stats, sizeof(buf_stats))) 425 return -1; 426 427 reply_len = rpcap_recv_pkt(handle, handle->fd, reply_buf, sizeof(reply_buf)); 428 if (reply_len != sizeof(reply_buf)) { 429 if (reply_len >= 0) 430 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Bad protocol (statsreply: %u)", reply_len); 431 return -1; 432 } 433 434 stats->ps_recv = get32(&reply_buf[0]); 435 stats->ps_ifdrop = get32(&reply_buf[4]); 436 stats->ps_drop = get32(&reply_buf[8]); 437 return 0; 438 } 439 440 static int 441 rpcap_setfilter_common(pcap_t *handle, struct bpf_program *prog) 442 { 443 unsigned char *buf_setfilter; 444 445 /* update local filter */ 446 if (pcapint_install_bpf_program(handle, prog) == -1) 447 return -1; 448 449 /* update remote filter */ 450 if (prog->bf_len < 0xfffff) { 451 unsigned int data_size = 8 + 8 * prog->bf_len; 452 unsigned char *buf_filter; 453 unsigned char *buf_insn; 454 size_t i; 455 456 buf_setfilter = malloc(8 + data_size); 457 if (!buf_setfilter) { 458 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "No memory for setfilter packet"); 459 return -1; 460 } 461 462 buf_filter = &buf_setfilter[8]; 463 buf_insn = &buf_filter[8]; 464 465 put16(&buf_filter[0], RPCAP_UPDATEFILTER_BPF); 466 put16(&buf_filter[2], 0); 467 put32(&buf_filter[4], prog->bf_len); 468 469 for (i = 0; i < prog->bf_len; i++) { 470 unsigned char *data = &buf_insn[i * 8]; 471 472 put16(&data[0], prog->bf_insns[i].code); 473 data[2] = prog->bf_insns[i].jt; 474 data[3] = prog->bf_insns[i].jf; 475 put32(&data[4], prog->bf_insns[i].k); 476 } 477 478 if (rpcap_send_request(handle, RPCAP_MSG_UPDATEFILTER_REQ, buf_setfilter, data_size)) { 479 free(buf_setfilter); 480 return -1; 481 } 482 free(buf_setfilter); 483 484 if (rpcap_recv_pkt(handle, handle->fd, NULL, 0) < 0) 485 return -1; 486 } 487 return 0; 488 } 489 490 static int 491 rpcap_read_unix(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) 492 { 493 struct pcap_pkthdr pkth; 494 const unsigned char *pkt; 495 const unsigned char *buf; 496 unsigned int pkt_len; 497 int count = 0; 498 499 pkt_len = rpcap_recv_pkt(handle, handle->selectable_fd, handle->buffer, handle->bufsize); 500 if (pkt_len < 20) { 501 if (pkt_len == 0) { 502 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pkt_len check failed (%u < 20)", pkt_len); 503 return -1; 504 } 505 return pkt_len; 506 } 507 buf = handle->buffer; 508 509 /* local */ 510 #if 0 511 gettimeofday(&pkth.ts, NULL); 512 pkth.caplen = pkth.len = pkt_len - 20 513 #endif 514 /* remote */ 515 pkth.ts.tv_sec = get32(&buf[0]); 516 pkth.ts.tv_usec = get32(&buf[4]); 517 pkth.caplen = get32(&buf[8]); 518 pkth.len = get32(&buf[12]); 519 /* pktnr */ 520 pkt = &buf[20]; 521 522 /* sanity caplen */ 523 if (pkt_len - 20 < pkth.caplen) { 524 /* pkt.caplen = pkt_len - 20; */ 525 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pkth.caplen check failed (%u < %u)", pkt_len - 20, pkth.caplen); 526 return -1; 527 } 528 529 if (handle->fcode.bf_insns == NULL || 530 bpf_filter(handle->fcode.bf_insns, pkt, pkth.len, pkth.caplen)) 531 { 532 // handle->md.packets_read++; 533 callback(user, &pkth, pkt); 534 count++; 535 } 536 return count; 537 } 538 539 static void 540 rpcap_cleanup(pcap_t *handle) 541 { 542 if (handle->selectable_fd != handle->fd) { 543 int fd = handle->selectable_fd; 544 545 if (fd != -1) { 546 handle->selectable_fd = -1; 547 close(fd); 548 } 549 } 550 pcapint_cleanup_live_common(handle); 551 } 552 553 static int 554 rpcap_activate(pcap_t *handle) 555 { 556 const char *dev = handle->opt.device; 557 const char *tmp; 558 559 char *host; 560 char *username = NULL; 561 char *password = NULL; 562 const char *interface = NULL; 563 int port; 564 565 struct sockaddr_in sin; 566 567 /* rpcap[s]://login:password@host:port/interface */ 568 if (strncmp(dev, RPCAP_IFACE, strlen(RPCAP_IFACE)) == 0) { 569 port = RPCAP_DEFAULT_NETPORT; 570 dev += strlen(RPCAP_IFACE); 571 572 } /* else if (strncmp(dev, "rpcaps://", strlen("rpcaps://")) == 0) { 573 port = RPCAP_DEFAULT_NETPORT_SSL; 574 dev += strlen("rpcaps://"); 575 576 } */ else { 577 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid protocol"); 578 return PCAP_ERROR; 579 } 580 581 if ((tmp = strchr(dev, '@'))) { 582 char *ptmp; 583 584 if ((ptmp = strchr(dev, ':'))) { 585 username = strndup(dev, ptmp-dev); 586 password = strndup(ptmp+1, tmp-(ptmp+1)); 587 588 } else { 589 username = strndup(dev, tmp-dev); 590 591 /* XXX, ask for password? */ 592 } 593 594 dev = tmp + 1; 595 } 596 597 if (*dev == '[') { 598 tmp = strchr(dev, ']'); 599 if (!tmp) { 600 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid host (missing ']')"); 601 return PCAP_ERROR; 602 } 603 604 host = strndup(dev+1, tmp-(dev+1)); 605 606 dev = tmp + 1; 607 } else { 608 tmp = strchr(dev, ':'); 609 if (!tmp) 610 tmp = strchr(dev, '/'); 611 612 if (tmp) { 613 host = strndup(dev, tmp-dev); 614 dev = tmp; 615 } else 616 host = strdup(dev); 617 } 618 619 if (*dev == ':') { 620 char *end; 621 622 if (dev[1] == '\0') { 623 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: missing port"); 624 return PCAP_ERROR; 625 } 626 627 port = strtol(dev + 1, &end, 10); 628 if (port < 1 || port > 65535) { 629 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: invalid port"); 630 return PCAP_ERROR; 631 } 632 633 dev = end; 634 } 635 636 if (*dev == '/') 637 interface = dev+1; 638 639 if (!host) { 640 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: couldn't parse host"); 641 return PCAP_ERROR; 642 } 643 644 if (!interface) { 645 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: couldn't parse interface"); 646 return PCAP_ERROR; 647 } 648 649 /* XXX, gethostbyname, ipv6, etc... */ 650 sin.sin_family = AF_INET; 651 sin.sin_addr.s_addr = inet_addr(host); 652 sin.sin_port = htons(port); 653 if (sin.sin_addr.s_addr == INADDR_NONE) { 654 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "rpcap: not ipv4 address"); 655 goto free_fail; 656 } 657 658 /* Initialize some components of the pcap structure. */ 659 handle->offset = 20; 660 handle->bufsize = handle->snapshot + handle->offset; 661 handle->linktype = -1; /* invalid for now */ 662 handle->read_op = rpcap_read_unix; 663 handle->setfilter_op = rpcap_setfilter_common; 664 handle->inject_op = rpcap_inject_common; 665 handle->setdirection_op = NULL; 666 handle->set_datalink_op = NULL; /* not possible */ 667 handle->getnonblock_op = pcapint_getnonblock_fd; 668 handle->setnonblock_op = pcapint_setnonblock_fd; 669 handle->stats_op = rpcap_stats_common; 670 handle->cleanup_op = rpcap_cleanup; 671 672 /* Create socket */ 673 handle->fd = socket(AF_INET, SOCK_STREAM, 0); 674 handle->selectable_fd = -1; 675 if (handle->fd < 0) { 676 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 677 "Can't create socket %d:%s", 678 errno, pcap_strerror(errno)); 679 goto close_fail; 680 } 681 682 if (connect(handle->fd, (struct sockaddr *) &sin, sizeof(sin))) { 683 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 684 "Can't connect to %s:%d (%d:%s)", 685 host, port, errno, pcap_strerror(errno)); 686 goto free_fail; 687 } 688 689 /* login */ 690 if (rpcap_send_request_auth(handle, username, password) < 0) 691 goto close_fail; 692 if (rpcap_send_request_open(handle, interface) < 0) 693 goto close_fail; 694 if (rpcap_send_request_start(handle, &(sin.sin_addr)) < 0) 695 goto close_fail; 696 697 handle->buffer = malloc(handle->bufsize); 698 if (!handle->buffer) { 699 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 700 "Can't allocate dump buffer: %s", 701 pcap_strerror(errno)); 702 goto close_fail; 703 } 704 705 if (handle->opt.rfmon) { 706 /* 707 * Monitor mode doesn't apply to rpcap. 708 */ 709 rpcap_cleanup(handle); 710 return PCAP_ERROR_RFMON_NOTSUP; 711 } 712 713 if (handle->opt.buffer_size != 0) { 714 /* 715 * Set the socket buffer size to the specified value. 716 */ 717 if (setsockopt(handle->selectable_fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) { 718 snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno)); 719 goto close_fail; 720 } 721 } 722 free(username); 723 free(password); 724 free(host); 725 726 return 0; 727 728 close_fail: 729 rpcap_cleanup(handle); 730 free_fail: 731 free(username); 732 free(password); 733 free(host); 734 return PCAP_ERROR; 735 } 736 737 pcap_t * 738 rpcap_create(const char *device, char *err_str, int *is_ours) 739 { 740 const char *cp = device; 741 pcap_t *p; 742 743 if (strncmp(cp, RPCAP_IFACE, strlen(RPCAP_IFACE)) == 0) 744 cp += strlen(RPCAP_IFACE); 745 else { 746 *is_ours = 0; 747 return NULL; 748 } 749 750 if (*cp == '\0') { 751 *is_ours = 0; 752 return NULL; 753 } 754 755 *is_ours = 1; 756 757 p = pcapint_create_common(__UNCONST(device), 16384, 0); 758 if (p == NULL) 759 return NULL; 760 761 p->activate_op = rpcap_activate; 762 return p; 763 } 764 765