00001 /* 00002 * Copyright (c) 2002 - 2003 00003 * NetGroup, Politecnico di Torino (Italy) 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * 3. Neither the name of the Politecnico di Torino nor the names of its 00016 * contributors may be used to endorse or promote products derived from 00017 * this software without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00020 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00022 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00023 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00025 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00026 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00027 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00029 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 */ 00032 00033 00034 #include <string.h> // for strlen(), ... 00035 #include <stdlib.h> // for malloc(), free(), ... 00036 #include <stdarg.h> // for functions with variable number of arguments 00037 #include <errno.h> // for the errno variable 00038 #include <pcap.h> 00039 #include <pcap-int.h> 00040 #include <pcap-remote.h> 00041 #include <sockutils.h> 00042 00043 00065 #define PCAP_STATS_STANDARD 0 00066 #define PCAP_STATS_EX 1 00070 00071 struct activehosts *activeHosts; 00072 00073 00074 /**************************************************** 00075 * * 00076 * Locally defined functions * 00077 * * 00078 ****************************************************/ 00079 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf); 00080 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode); 00081 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog); 00082 int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog); 00083 00084 00085 00086 00087 /**************************************************** 00088 * * 00089 * Function bodies * 00090 * * 00091 ****************************************************/ 00092 00126 int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf) 00127 { 00128 // Warning: we support only AF_INET and AF_INET6 00129 if ( ntohs(sockaddrin->ss_family) == AF_INET) 00130 { 00131 struct sockaddr_in *sockaddr; 00132 00133 sockaddr= (struct sockaddr_in *) sockaddrin; 00134 sockaddr->sin_family= ntohs(sockaddr->sin_family); 00135 sockaddr->sin_port= ntohs(sockaddr->sin_port); 00136 00137 (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in) ); 00138 if ( (*sockaddrout) == NULL) 00139 { 00140 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00141 return -1; 00142 } 00143 memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in) ); 00144 return 0; 00145 } 00146 if ( ntohs(sockaddrin->ss_family) == AF_INET6) 00147 { 00148 struct sockaddr_in6 *sockaddr; 00149 00150 sockaddr= (struct sockaddr_in6 *) sockaddrin; 00151 sockaddr->sin6_family= ntohs(sockaddr->sin6_family); 00152 sockaddr->sin6_port= ntohs(sockaddr->sin6_port); 00153 sockaddr->sin6_flowinfo= ntohl(sockaddr->sin6_flowinfo); 00154 sockaddr->sin6_scope_id= ntohl(sockaddr->sin6_scope_id); 00155 00156 (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in6) ); 00157 if ( (*sockaddrout) == NULL) 00158 { 00159 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00160 return -1; 00161 } 00162 memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in6) ); 00163 return 0; 00164 } 00165 00166 // It is neither AF_INET nor AF_INET6 00167 *sockaddrout= NULL; 00168 return 0; 00169 } 00170 00171 00172 00196 int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data) 00197 { 00198 struct rpcap_header *header; // general header according to the RPCAP format 00199 struct rpcap_pkthdr *net_pkt_header; // header of the packet 00200 char netbuf[RPCAP_NETBUF_SIZE]; // size of the network buffer in which the packet is copied, just for UDP 00201 unsigned int nread; // number of bytes (of payload) currently read from the network (referred to the current pkt) 00202 int retval; // generic return value 00203 00204 // Structures needed for the select() call 00205 fd_set rfds; // set of socket descriptors we have to check 00206 struct timeval tv; // maximum time the select() can block waiting for data 00207 00208 00209 // Define the read timeout, to be used in the select() 00210 // 'timeout', in pcap_t, is in milliseconds; we have to convert it into sec and microsec 00211 #ifdef linux 00212 tv.tv_sec = p->md.timeout/1000; 00213 tv.tv_usec = (p->md.timeout - tv.tv_sec * 1000 )* 1000; 00214 #else 00215 tv.tv_sec = p->timeout/1000; 00216 tv.tv_usec = (p->timeout - tv.tv_sec * 1000 )* 1000; 00217 #endif 00218 00219 // Watch out sockdata to see if it has input 00220 FD_ZERO(&rfds); 00221 00222 // 'fp->rmt_sockdata' has always to be set before calling the select(), 00223 // since it is cleared by the select() 00224 FD_SET(p->rmt_sockdata, &rfds); 00225 00226 retval = select(p->rmt_sockdata + 1, &rfds, NULL, NULL, &tv); 00227 if (retval == -1) 00228 { 00229 sock_geterror("select(): ", p->errbuf, PCAP_ERRBUF_SIZE); 00230 return -1; 00231 } 00232 00233 // There is no data waiting, so return '0' 00234 if (retval == 0) 00235 return 0; 00236 00237 // data is here; so, let's copy it into the user buffer 00238 // I'm going to read a new packet; so I reset the number of bytes (payload only) read 00239 nread= 0; 00240 00241 // We have to define 'header' as a pointer to a larger buffer, 00242 // because in case of UDP we have to read all the message within a single call 00243 header= (struct rpcap_header *) netbuf; 00244 net_pkt_header= (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header) ); 00245 00246 if (p->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) 00247 { 00248 // Read the entire message from the network 00249 if (sock_recv(p->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, SOCK_RECEIVEALL_NO, p->errbuf, PCAP_ERRBUF_SIZE) == -1) 00250 return -1; 00251 } 00252 else 00253 { 00254 if (sock_recv(p->rmt_sockdata, netbuf, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1) 00255 return -1; 00256 } 00257 00258 // Checks if the message is correct 00259 retval= rpcap_checkmsg(p->errbuf, p->rmt_sockdata, header, RPCAP_MSG_PACKET, 0); 00260 00261 if (retval != RPCAP_MSG_PACKET) // the message is not the one expected 00262 { 00263 switch (retval) 00264 { 00265 case -3: // Unrecoverable network error 00266 return -1; // Do nothing; just exit from here; the error code is already into the errbuf 00267 00268 case -2: // The other endpoint sent a message that is not allowed here 00269 case -1: // The other endpoint has a version number that is not compatible with our 00270 return 0; // Return 'no packets received' 00271 00272 default: 00273 { 00274 SOCK_ASSERT("Internal error", 1); 00275 return 0; // Return 'no packets received 00276 }; 00277 } 00278 } 00279 00280 // In case of TCP, read the remaining of the packet from the socket 00281 if ( !(p->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)) 00282 { 00283 // Read the RPCAP packet header from the network 00284 if ( (nread= sock_recv(p->rmt_sockdata, (char *) net_pkt_header, 00285 sizeof(struct rpcap_pkthdr), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1) 00286 return -1; 00287 } 00288 00289 if ( (ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) p->bufsize) ) 00290 { 00291 // Initialize returned structures 00292 *pkt_header= (struct pcap_pkthdr *) p->buffer; 00293 *pkt_data= p->buffer + sizeof(struct pcap_pkthdr); 00294 00295 (*pkt_header)->caplen= ntohl(net_pkt_header->caplen); 00296 (*pkt_header)->len= ntohl(net_pkt_header->len); 00297 (*pkt_header)->ts.tv_sec= ntohl(net_pkt_header->timestamp_sec); 00298 (*pkt_header)->ts.tv_usec= ntohl(net_pkt_header->timestamp_usec); 00299 00300 // I don't update the counter of the packets dropped by the network since we're using TCP; 00301 // therefore no packets are dropped. Just update the number of packets received correctly 00302 p->md.TotCapt++; 00303 00304 // Copies the packet into the data buffer 00305 if (p->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) 00306 { 00307 unsigned int npkt; 00308 00309 // In case of UDP the packet has already been read; we have to copy it into 'buffer' 00310 // Another option should bne to declare 'netbuf' as 'static'; however this prevents 00311 // using several pcap instances within the same process (because the static buffer is shared among 00312 // all processes) 00313 memcpy(*pkt_data, netbuf + sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr), (*pkt_header)->caplen); 00314 00315 // We're using UDP, so we need to update the counter of the packets dropped by the network 00316 npkt= ntohl(net_pkt_header->npkt); 00317 00318 if (p->md.TotCapt != npkt) 00319 { 00320 p->md.TotNetDrops+= (npkt - p->md.TotCapt); 00321 p->md.TotCapt= npkt; 00322 } 00323 00324 } 00325 else 00326 { 00327 // In case of TCP, read the remaining of the packet from the socket 00328 if ( (nread+= sock_recv(p->rmt_sockdata, *pkt_data, (*pkt_header)->caplen, SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1) 00329 return -1; 00330 00331 // Checks if all the data has been read; if not, discard the data in excess 00332 // This check has to be done only on TCP connections 00333 if (nread != ntohl(header->plen)) 00334 sock_discard(p->rmt_sockdata, ntohl(header->plen) - nread, NULL, 0); 00335 } 00336 00337 00338 // Packet read successfully 00339 return 1; 00340 } 00341 else 00342 { 00343 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Received a packet that is larger than the internal buffer size."); 00344 return -1; 00345 } 00346 00347 } 00348 00349 00364 int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 00365 { 00366 struct pcap_pkthdr *pkt_header; 00367 u_char *pkt_data; 00368 int n = 0; 00369 00370 while ( (++n <= cnt) || (cnt < 0) ) 00371 { 00372 if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) ) 00373 (*callback)(user, pkt_header, pkt_data); 00374 else 00375 return n; 00376 } 00377 return n; 00378 } 00379 00380 00394 void pcap_close_remote(pcap_t *fp) 00395 { 00396 struct rpcap_header header; // header of the RPCAP packet 00397 struct activehosts *temp; // temp var needed to scan the host list chain, to detect if we're in active mode 00398 int active= 0; // active mode or not? 00399 00400 // detect if we're in active mode 00401 temp= activeHosts; 00402 while (temp) 00403 { 00404 if (temp->sockctrl == fp->rmt_sockctrl) 00405 { 00406 active= 1; 00407 break; 00408 } 00409 temp= temp->next; 00410 } 00411 00412 if (!active) 00413 { 00414 rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0); 00415 00416 // I don't check for errors, since I'm going to close everything 00417 sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), NULL, 0); 00418 } 00419 else 00420 { 00421 rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REQ, 0, 0); 00422 00423 // I don't check for errors, since I'm going to close everything 00424 sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), NULL, 0); 00425 00426 // wait for the answer 00427 // Don't check what we got, since the present libpcap does not uses this pcap_t anymore 00428 sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, NULL, 0); 00429 00430 if ( ntohl(header.plen) != 0) 00431 sock_discard(fp->rmt_sockctrl, ntohl(header.plen), NULL, 0); 00432 } 00433 00434 if (fp->rmt_sockdata) 00435 { 00436 sock_close(fp->rmt_sockdata, NULL, 0); 00437 fp->rmt_sockdata= 0; 00438 } 00439 00440 if ( (!active) && (fp->rmt_sockctrl) ) 00441 sock_close(fp->rmt_sockctrl, NULL, 0); 00442 00443 fp->rmt_sockctrl= 0; 00444 00445 if (fp->currentfilter) 00446 { 00447 free(fp->currentfilter); 00448 fp->currentfilter= NULL; 00449 } 00450 00451 // To avoid inconsistencies in the number of sock_init() 00452 sock_cleanup(); 00453 } 00454 00455 00456 00466 int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps) 00467 { 00468 struct pcap_stat *retval; 00469 00470 retval= rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD); 00471 00472 if (retval) 00473 return 0; 00474 else 00475 return -1; 00476 } 00477 00478 00479 00489 struct pcap_stat *pcap_stats_ex_remote(pcap_t *p) 00490 { 00491 // '0' (third param) means 'standard pcap_stats()' 00492 return (rpcap_stats_remote(p, &(p->md.stat), PCAP_STATS_EX)); 00493 } 00494 00495 00496 00527 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode) 00528 { 00529 struct rpcap_header header; // header of the RPCAP packet 00530 struct rpcap_stats netstats; // statistics sent on the network 00531 unsigned int nread= 0; // number of bytes of the payload read from the socket 00532 int retval; // temp variable which stores functions return value 00533 00534 // If the capture has still to start, we cannot ask statistics to the other peer 00535 // So, we return a fake number 00536 if (!p->rmt_capstarted) 00537 { 00538 if (mode == PCAP_STATS_STANDARD) 00539 { 00540 ps->ps_drop= 0; 00541 ps->ps_ifdrop= 0; 00542 ps->ps_recv= 0; 00543 } 00544 else 00545 { 00546 ps->ps_capt= 0; 00547 ps->ps_drop= 0; 00548 ps->ps_ifdrop= 0; 00549 ps->ps_netdrop= 0; 00550 ps->ps_recv= 0; 00551 ps->ps_sent= 0; 00552 } 00553 00554 return ps; 00555 } 00556 00557 rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0); 00558 00559 // Send the PCAP_STATS command 00560 if (sock_send(p->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE) ) 00561 goto error; 00562 00563 // Receive the RPCAP stats reply message 00564 if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1) 00565 goto error; 00566 00567 // Checks if the message is correct 00568 retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0); 00569 00570 if (retval != RPCAP_MSG_STATS_REPLY) // the message is not the one expected 00571 { 00572 switch (retval) 00573 { 00574 case -3: // Unrecoverable network error 00575 case -2: // The other endpoint send a message that is not allowed here 00576 case -1: // The other endpoint has a version number that is not compatible with our 00577 goto error; 00578 00579 case RPCAP_MSG_ERROR: // The other endpoint reported an error 00580 // Update nread, since the rpcap_checkmsg() already purged the buffer 00581 nread = ntohl(header.plen); 00582 00583 // Do nothing; just exit; the error code is already into the errbuf 00584 goto error; 00585 00586 default: 00587 { 00588 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 00589 goto error; 00590 }; 00591 } 00592 } 00593 00594 if ( (nread= sock_recv(p->rmt_sockctrl, (char *) &netstats, sizeof(struct rpcap_stats), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1) 00595 goto error; 00596 00597 if (mode == PCAP_STATS_STANDARD) 00598 { 00599 ps->ps_drop= ntohl(netstats.krnldrop); 00600 ps->ps_ifdrop= ntohl(netstats.ifdrop); 00601 ps->ps_recv= ntohl(netstats.ifrecv); 00602 } 00603 else 00604 { 00605 ps->ps_capt= p->md.TotCapt; 00606 ps->ps_drop= ntohl(netstats.krnldrop); 00607 ps->ps_ifdrop= ntohl(netstats.ifdrop); 00608 ps->ps_netdrop= p->md.TotNetDrops; 00609 ps->ps_recv= ntohl(netstats.ifrecv); 00610 ps->ps_sent= ntohl(netstats.svrcapt); 00611 } 00612 00613 // Checks if all the data has been read; if not, discard the data in excess 00614 if (nread != ntohl(header.plen)) 00615 { 00616 if (sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, NULL, 0) == 1) 00617 goto error; 00618 } 00619 00620 return ps; 00621 00622 error: 00623 if (nread != ntohl(header.plen)) 00624 sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, NULL, 0); 00625 00626 return NULL; 00627 } 00628 00629 00630 00631 00670 pcap_t *pcap_opensource_remote(const char *source, struct pcap_rmtauth *auth, char *errbuf) 00671 { 00672 char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE]; 00673 00674 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 00675 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00676 struct pcap *fp= NULL; // pcap_t main variable 00677 unsigned int nread= 0; // number of bytes of the payload read from the socket 00678 int retval; // store the return value of the functions 00679 int active= 0; // '1' if we're in active mode 00680 00681 // socket-related variables 00682 struct addrinfo hints; // temp, needed to open a socket connection 00683 struct addrinfo *addrinfo; // temp, needed to open a socket connection 00684 SOCKET sockctrl= 0; // socket descriptor of the control connection 00685 00686 // RPCAP-related variables 00687 struct rpcap_header header; // header of the RPCAP packet 00688 struct rpcap_openreply openreply; // open reply message 00689 00690 00691 // determine the type of the source (NULL, file, local, remote) 00692 // You must have a valid source string even if we're in active mode, because otherwise 00693 // the call to the following funciton will fail. 00694 if (pcap_parsesrcstr(source, &retval, host, ctrlport, iface, errbuf) == -1) 00695 return NULL; 00696 00697 if ( retval != PCAP_SRC_IFREMOTE) 00698 { 00699 snprintf(errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces"); 00700 return NULL; 00701 } 00702 00703 addrinfo= NULL; 00704 00705 // Warning: this call can be the first one called by the user. 00706 // For this reason, we have to initialize the WinSock support. 00707 if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1) 00708 return NULL; 00709 00710 retval= rpcap_remoteact_getsock(host, errbuf); 00711 00712 if (retval == -1) 00713 return NULL; 00714 00715 // The capturing machine is in active mode 00716 if (retval) 00717 { 00718 sockctrl= retval; 00719 active= 1; 00720 } 00721 else 00722 { 00723 memset(&hints, 0, sizeof(struct addrinfo) ); 00724 hints.ai_family = PF_UNSPEC; 00725 hints.ai_socktype = SOCK_STREAM; 00726 00727 if ( (ctrlport == NULL) || (ctrlport[0] == 0) ) 00728 { 00729 // the user chose not to specify the port 00730 if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) 00731 return NULL; 00732 } 00733 else 00734 { 00735 // the user chose not to specify the port 00736 if (sock_initaddress(host, ctrlport, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) 00737 return NULL; 00738 } 00739 00740 if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1) 00741 goto error; 00742 00743 freeaddrinfo(addrinfo); 00744 addrinfo= NULL; 00745 00746 if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1) 00747 goto error; 00748 } 00749 00750 00751 // Now it's time to start playing with the RPCAP protocol 00752 // RPCAP open command: create the request message 00753 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 00754 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) ) 00755 goto error; 00756 00757 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, strlen(iface) ); 00758 00759 if ( sock_bufferize(iface, strlen(iface), sendbuf, &sendbufidx, 00760 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) ) 00761 goto error; 00762 00763 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) ) 00764 goto error; 00765 00766 // Receive the RPCAP open reply message 00767 if (sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1) 00768 goto error; 00769 00770 // Checks if the message is correct 00771 retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0); 00772 00773 if (retval != RPCAP_MSG_OPEN_REPLY) // the message is not the one expected 00774 { 00775 switch (retval) 00776 { 00777 case -3: // Unrecoverable network error 00778 case -2: // The other endpoint send a message that is not allowed here 00779 case -1: // The other endpoint has a version number that is not compatible with our 00780 goto error; 00781 00782 case RPCAP_MSG_ERROR: // The other endpoint reported an error 00783 // Update nread, since the rpcap_checkmsg() already purged the buffer 00784 nread = ntohl(header.plen); 00785 // Do nothing; just exit; the error code is already into the errbuf 00786 goto error; 00787 00788 default: 00789 { 00790 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 00791 goto error; 00792 }; 00793 } 00794 } 00795 00796 00797 if ( (nread+= sock_recv(sockctrl, (char *) &openreply, sizeof(struct rpcap_openreply), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1) 00798 goto error; 00799 00800 // Allocates a pcap_t struct for this end of the connection 00801 fp = (pcap_t *) malloc( sizeof(pcap_t) ); 00802 if (fp == NULL) 00803 { 00804 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00805 goto error; 00806 } 00807 00808 memset(fp, 0, sizeof(pcap_t)); 00809 00810 // Set proper fields into the pcap_t struct 00811 fp->linktype= ntohl(openreply.linktype); 00812 fp->tzoff= ntohl(openreply.tzoff); 00813 fp->rmt_sockctrl= sockctrl; 00814 fp->rmt_clientside= 1; 00815 00816 00817 // This code is duplicated from the end of this function 00818 fp->read_op= pcap_read_remote; 00819 fp->setfilter_op= pcap_setfilter_remote; 00820 fp->getnonblock_op= NULL; // This is not implemented in remote capture 00821 fp->setnonblock_op= NULL; // This is not implemented in remote capture 00822 fp->stats_op= pcap_stats_remote; 00823 fp->close_op= pcap_close_remote; 00824 00825 // Checks if all the data has been read; if not, discard the data in excess 00826 if (nread != ntohl(header.plen)) 00827 { 00828 if (sock_discard(sockctrl, ntohl(header.plen) - nread, NULL, 0) == 1) 00829 goto error; 00830 } 00831 return fp; 00832 00833 error: 00834 // When the connection has been established, we have to close it. So, at the 00835 // beginning of this function, if an error occur we return immediately with 00836 // a return NULL; when the connection is established, we have to come here 00837 // ('goto error;') in order to close everything properly. 00838 00839 // Checks if all the data has been read; if not, discard the data in excess 00840 if (nread != ntohl(header.plen)) 00841 sock_discard(sockctrl, ntohl(header.plen) - nread, NULL, 0); 00842 00843 if (addrinfo) 00844 freeaddrinfo(addrinfo); 00845 00846 if (!active) 00847 sock_close(sockctrl, NULL, 0); 00848 00849 if (fp) 00850 { 00851 pcap_close(fp); 00852 fp= NULL; 00853 } 00854 00855 return NULL; 00856 } 00857 00858 00859 00860 00861 00862 00863 00886 int pcap_startcapture_remote(pcap_t *fp) 00887 { 00888 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 00889 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00890 char portdata[PCAP_BUF_SIZE]; // temp variable needed to keep the network port for the the data connection 00891 unsigned int nread= 0; // number of bytes of the payload read from the socket 00892 int retval; // store the return value of the functions 00893 int active= 0; // '1' if we're in active mode 00894 struct activehosts *temp; // temp var needed to scan the host list chain, to detect if we're in active mode 00895 char host[INET6_ADDRSTRLEN + 1]; // numeric name of the other host 00896 00897 // socket-related variables 00898 struct addrinfo hints; // temp, needed to open a socket connection 00899 struct addrinfo *addrinfo; // temp, needed to open a socket connection 00900 SOCKET sockdata= 0; // socket descriptor of the data connection 00901 struct sockaddr_storage saddr; // temp, needed to retrieve the network data port chosen on the local machine 00902 socklen_t saddrlen; // temp, needed to retrieve the network data port chosen on the local machine 00903 int ai_family; // temp, keeps the address family used by the control connection 00904 00905 // RPCAP-related variables 00906 struct rpcap_header header; // header of the RPCAP packet 00907 struct rpcap_startcapreq *startcapreq; // start capture request message 00908 struct rpcap_startcapreply startcapreply; // start capture reply message 00909 00910 // Variables related to the buffer setting 00911 int res, itemp; 00912 int sockbufsize= 0; 00913 00914 00915 // Let's check if sampling has been required. 00916 // If so, let's set it first 00917 if (pcap_setsampling_remote(fp) != 0) 00918 return -1; 00919 00920 00921 // detect if we're in active mode 00922 temp= activeHosts; 00923 while (temp) 00924 { 00925 if (temp->sockctrl == fp->rmt_sockctrl) 00926 { 00927 active= 1; 00928 break; 00929 } 00930 temp= temp->next; 00931 } 00932 00933 addrinfo= NULL; 00934 00935 // Gets the complete sockaddr structure used in the ctrl connection 00936 // This is needed to get the address family of the control socket 00937 // Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct, 00938 // since the ctrl socket can already be open in case of active mode; 00939 // so I would have to call getpeername() anyway 00940 saddrlen = sizeof(struct sockaddr_storage); 00941 if (getpeername(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1) 00942 { 00943 sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00944 goto error; 00945 } 00946 ai_family= ((struct sockaddr_storage *) &saddr)->ss_family; 00947 00948 // Get the numeric address of the remote host we are connected to 00949 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, host, 00950 sizeof(host), NULL, 0, NI_NUMERICHOST) ) 00951 { 00952 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00953 goto error; 00954 } 00955 00956 /* 00957 Data connection is opened by the server toward the client if: 00958 - we're using TCP, and the user wants us to be in active mode 00959 - we're using UDP 00960 */ 00961 if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ) 00962 { 00963 // We have to create a new socket to receive packets 00964 // We have to do that immediately, since we have to tell the other 00965 // end which network port we picked up 00966 memset(&hints, 0, sizeof(struct addrinfo) ); 00967 // TEMP addrinfo is NULL in case of active 00968 hints.ai_family = ai_family; // Use the same address family of the control socket 00969 hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM; 00970 hints.ai_flags = AI_PASSIVE; // Data connection is opened by the server toward the client 00971 00972 // Let's the server pick up a free network port for us 00973 if (sock_initaddress(NULL, "0", &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 00974 goto error; 00975 00976 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 00977 1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1) 00978 goto error; 00979 00980 // addrinfo is no longer used 00981 freeaddrinfo(addrinfo); 00982 addrinfo= NULL; 00983 00984 // get the complete sockaddr structure used in the data connection 00985 saddrlen = sizeof(struct sockaddr_storage); 00986 if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1) 00987 { 00988 sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00989 goto error; 00990 } 00991 00992 // Get the local port the system picked up 00993 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 00994 0, portdata, sizeof(portdata), NI_NUMERICSERV) ) 00995 { 00996 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00997 goto error; 00998 } 00999 } 01000 01001 // Now it's time to start playing with the RPCAP protocol 01002 // RPCAP start ca[ture command: create the request message 01003 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 01004 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01005 goto error; 01006 01007 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0, 01008 sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn) ); 01009 01010 // Fill the structure needed to open an adapter remotely 01011 startcapreq= (struct rpcap_startcapreq *) &sendbuf[sendbufidx]; 01012 01013 if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL, 01014 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01015 goto error; 01016 01017 memset(startcapreq, 0, sizeof(struct rpcap_startcapreq) ); 01018 01019 // By default, apply half the timeout on one side, half of the other 01020 #ifdef linux 01021 fp->md.timeout= fp->md.timeout/2; 01022 startcapreq->read_timeout= htonl(fp->md.timeout); 01023 #else 01024 fp->timeout= fp->timeout/2; 01025 startcapreq->read_timeout= htonl(fp->timeout); 01026 #endif 01027 01028 // portdata on the openreq is meaningful only if we're in active mode 01029 if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ) 01030 { 01031 sscanf(portdata, "%d", (int *) &(startcapreq->portdata)); // cast to avoid a compiler warning 01032 startcapreq->portdata= htons(startcapreq->portdata); 01033 } 01034 01035 startcapreq->snaplen= htonl(fp->snapshot); 01036 startcapreq->flags= 0; 01037 01038 if (fp->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS) 01039 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_PROMISC; 01040 if (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) 01041 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_DGRAM; 01042 if (active) 01043 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN; 01044 01045 startcapreq->flags= htons(startcapreq->flags); 01046 01047 // Pack the capture filter 01048 if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode) ) 01049 goto error; 01050 01051 if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01052 goto error; 01053 01054 01055 // Receive the RPCAP start capture reply message 01056 if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01057 goto error; 01058 01059 // Checks if the message is correct 01060 retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0); 01061 01062 if (retval != RPCAP_MSG_STARTCAP_REPLY) // the message is not the one expected 01063 { 01064 switch (retval) 01065 { 01066 case -3: // Unrecoverable network error 01067 case -2: // The other endpoint send a message that is not allowed here 01068 case -1: // The other endpoint has a version number that is not compatible with our 01069 goto error; 01070 01071 case RPCAP_MSG_ERROR: // The other endpoint reported an error 01072 // Update nread, since the rpcap_checkmsg() already purged the buffer 01073 nread = ntohl(header.plen); 01074 // Do nothing; just exit; the error code is already into the errbuf 01075 goto error; 01076 01077 default: 01078 { 01079 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 01080 goto error; 01081 }; 01082 } 01083 } 01084 01085 01086 if ( (nread+= sock_recv(fp->rmt_sockctrl, (char *) &startcapreply, 01087 sizeof(struct rpcap_startcapreply), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1) 01088 goto error; 01089 01090 // In case of UDP data stream, the connection is always opened by the daemon 01091 // So, this case is already covered by the code above. 01092 // Now, we have still to handle TCP connections, because: 01093 // - if we're in active mode, we have to wait for a remote connection 01094 // - if we're in passive more, we have to start a connection 01095 // 01096 // We have to do he job in two steps because in case we're opening a tcp connection, we have 01097 // to tell the port we're using to the remote side; in case we're accepting a TCP 01098 // connection, we have to wait this info from the remote side. 01099 01100 if (!(fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)) 01101 { 01102 if (!active) 01103 { 01104 memset(&hints, 0, sizeof(struct addrinfo) ); 01105 hints.ai_family = ai_family; // Use the same address family of the control socket 01106 hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM; 01107 01108 sprintf(portdata, "%d", ntohs(startcapreply.portdata) ); 01109 01110 // Let's the server pick up a free network port for us 01111 if (sock_initaddress(host, portdata, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01112 goto error; 01113 01114 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1) 01115 goto error; 01116 01117 // addrinfo is no longer used 01118 freeaddrinfo(addrinfo); 01119 addrinfo= NULL; 01120 } 01121 else 01122 { 01123 SOCKET socktemp; // We need another socket, since we're going to accept() a connection 01124 01125 // Connection creation 01126 saddrlen = sizeof(struct sockaddr_storage); 01127 01128 socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen); 01129 01130 if (socktemp == -1) 01131 { 01132 sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01133 goto error; 01134 } 01135 01136 // Now that I accepted the connection, the server socket is no longer needed 01137 sock_close(sockdata, fp->errbuf, PCAP_ERRBUF_SIZE); 01138 sockdata= socktemp; 01139 } 01140 } 01141 01142 // Let's save the socket of the data connection 01143 fp->rmt_sockdata= sockdata; 01144 01145 // Allocates WinPcap/libpcap user buffer, which is a socket buffer in case of a remote capture 01146 // It has the same size of the one used on the other side of the connection 01147 fp->bufsize= ntohl(startcapreply.bufsize); 01148 01149 // Let's get the actual size of the socket buffer 01150 itemp= sizeof(sockbufsize); 01151 01152 res= getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &itemp); 01153 if (res == -1) 01154 { 01155 sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE); 01156 SOCK_ASSERT(fp->errbuf, 1); 01157 } 01158 01159 /* 01160 Warning: on some kernels (e.g. linux), the size of the user buffer does not take 01161 into account the pcap_header and such, and it is set equal to the snaplen. 01162 In my view, this is wrong (the meaning of the bufsize becames a bit strange). 01163 So, here bufsize is the whole size of the user buffer. 01164 In case the bufsize returned is too small, let's adjust it accordingly. 01165 */ 01166 if (fp->bufsize <= fp->snapshot) 01167 fp->bufsize+= sizeof (struct pcap_pkthdr); 01168 01169 // if the current socket buffer is smaller than the desired one 01170 if (sockbufsize < fp->bufsize) 01171 { 01172 // Loop until the buffer size is OK or the original socket buffer size is larger than this one 01173 while (1) 01174 { 01175 res= setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &(fp->bufsize), sizeof(fp->bufsize) ); 01176 01177 if (res == 0) 01178 break; 01179 01180 // If something goes wrong, half the buffer size (checking that it does not become smaller than 01181 // the current one) 01182 fp->bufsize/= 2; 01183 01184 if (sockbufsize >= fp->bufsize) 01185 { 01186 fp->bufsize= sockbufsize; 01187 break; 01188 } 01189 } 01190 } 01191 01192 // Let's allocate the packet; this is required in order to put the packet somewhere when 01193 // extracting data from the socket 01194 // Since buffering has already been done in the socket buffer, here we need just a buffer, 01195 // whose size is equal to the pcap header plus the snapshot length 01196 fp->bufsize= fp->snapshot + sizeof (struct pcap_pkthdr); 01197 01198 fp->buffer = (u_char *) malloc(fp->bufsize); 01199 if (fp->buffer == NULL) 01200 { 01201 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 01202 goto error; 01203 } 01204 01205 01206 // Checks if all the data has been read; if not, discard the data in excess 01207 if (nread != ntohl(header.plen)) 01208 { 01209 if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, NULL, 0) == 1) 01210 goto error; 01211 } 01212 01213 // In case the user does not want to capture RPCAP packets, let's update the filter 01214 // We have to update it here (instead of sending it into the 'StartCapture' message 01215 // because when we generate the 'start capture' we do not know (yet) all the ports 01216 // we're currently using. 01217 if (fp->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP) 01218 { 01219 struct bpf_program fcode; 01220 01221 if (pcap_createfilter_norpcappkt(fp, &fcode) == -1) 01222 goto error; 01223 01224 // We cannot use 'pcap_setfilter_remote' because formally the capture has not been started yet 01225 // (the 'fp->rmt_capstarted' variable will be updated some lines below) 01226 if (pcap_updatefilter_remote(fp, &fcode) == -1) 01227 goto error; 01228 01229 pcap_freecode(&fcode); 01230 } 01231 01232 fp->rmt_capstarted= 1; 01233 return 0; 01234 01235 error: 01236 // When the connection has been established, we have to close it. So, at the 01237 // beginning of this function, if an error occur we return immediately with 01238 // a return NULL; when the connection is established, we have to come here 01239 // ('goto error;') in order to close everything properly. 01240 01241 // Checks if all the data has been read; if not, discard the data in excess 01242 if (nread != ntohl(header.plen)) 01243 sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, NULL, 0); 01244 01245 if ((sockdata) && (sockdata != -1)) // we can be here because sockdata said 'error' 01246 sock_close(sockdata, NULL, 0); 01247 01248 if (!active) 01249 sock_close(fp->rmt_sockctrl, NULL, 0); 01250 01251 // We do not have to call pcap_close() here, because this function is always called 01252 // by the user in case something bad happens 01253 // if (fp) 01254 // { 01255 // pcap_close(fp); 01256 // fp= NULL; 01257 // } 01258 01259 return -1; 01260 } 01261 01262 01263 01264 01265 01289 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog) 01290 { 01291 struct rpcap_filter *filter; 01292 struct rpcap_filterbpf_insn *insn; 01293 struct bpf_insn *bf_insn; 01294 struct bpf_program fake_prog; // To be used just in case the user forgot to set a filter 01295 unsigned int i; 01296 01297 01298 if (prog->bf_len == 0) // No filters have been specified; so, let's apply a "fake" filter 01299 { 01300 if (pcap_compile(fp, &fake_prog, NULL /*buffer*/, 1, 0) == -1) 01301 return -1; 01302 01303 prog= &fake_prog; 01304 } 01305 01306 filter= (struct rpcap_filter *) sendbuf; 01307 01308 if ( sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx, 01309 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01310 return -1; 01311 01312 filter->filtertype= htons(RPCAP_UPDATEFILTER_BPF); 01313 filter->nitems= htonl( (int32) prog->bf_len); 01314 01315 if ( sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn), 01316 NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01317 return -1; 01318 01319 insn= (struct rpcap_filterbpf_insn *) (filter + 1); 01320 bf_insn= prog->bf_insns; 01321 01322 for (i= 0; i < prog->bf_len; i++) 01323 { 01324 insn->code= htons(bf_insn->code); 01325 insn->jf= bf_insn->jf; 01326 insn->jt= bf_insn->jt; 01327 insn->k= htonl(bf_insn->k); 01328 01329 insn++; 01330 bf_insn++; 01331 } 01332 01333 return 0; 01334 } 01335 01336 01337 01338 01339 01359 int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog) 01360 { 01361 int retval; // general variable used to keep the return value of other functions 01362 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 01363 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01364 struct rpcap_header header; // To keep the reply message 01365 01366 01367 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 01368 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01369 return -1; 01370 01371 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0, 01372 sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn)); 01373 01374 if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog) ) 01375 return -1; 01376 01377 if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01378 return -1; 01379 01380 // Waits for the answer 01381 if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01382 return -1; 01383 01384 // Checks if the message is correct 01385 retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0); 01386 01387 if (retval != RPCAP_MSG_UPDATEFILTER_REPLY) // the message is not the one expected 01388 { 01389 switch (retval) 01390 { 01391 case -3: // Unrecoverable network error 01392 case -2: // The other endpoint sent a message that is not allowed here 01393 case -1: // The other endpoint has a version number that is not compatible with our 01394 // Do nothing; just exit from here; the error code is already into the errbuf 01395 return -1; 01396 01397 default: 01398 { 01399 SOCK_ASSERT("Internal error", 0); 01400 return -1; 01401 }; 01402 } 01403 } 01404 01405 if (ntohl(header.plen) != 0) // the message has an unexpected size 01406 { 01407 if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01408 return -1; 01409 } 01410 01411 return 0; 01412 } 01413 01414 01415 01416 01428 int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog) 01429 { 01430 if (!fp->rmt_capstarted) 01431 { 01432 // copy filter into the pcap_t structure 01433 if (install_bpf_program(fp, prog) == -1) 01434 return -1; 01435 return 0; 01436 } 01437 01438 // we have to update a filter during run-time 01439 if (pcap_updatefilter_remote(fp, prog) ) 01440 return -1; 01441 01442 return 0; 01443 } 01444 01445 01446 01447 01448 01460 int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog) 01461 { 01462 int RetVal= 0; 01463 01464 // We do not want to capture our RPCAP traffic. So, let's update the filter 01465 if (fp->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP) 01466 { 01467 struct sockaddr_storage saddr; // temp, needed to retrieve the network data port chosen on the local machine 01468 socklen_t saddrlen; // temp, needed to retrieve the network data port chosen on the local machine 01469 char myaddress[128]; 01470 char myctrlport[128]; 01471 char mydataport[128]; 01472 char peeraddress[128]; 01473 char peerctrlport[128]; 01474 char *newfilter; 01475 const int newstringsize= 1024; 01476 int currentfiltersize; 01477 01478 // Get the name/port of the other peer 01479 saddrlen = sizeof(struct sockaddr_storage); 01480 if (getpeername(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1) 01481 { 01482 sock_geterror("getpeername(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01483 return -1; 01484 } 01485 01486 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, peeraddress, 01487 sizeof(peeraddress), peerctrlport, sizeof(peerctrlport), NI_NUMERICHOST | NI_NUMERICSERV) ) 01488 { 01489 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01490 return -1; 01491 } 01492 01493 // We cannot check the data port, because this is available only in case of TCP sockets 01494 01495 // Get the name/port of the current host 01496 if (getsockname(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1) 01497 { 01498 sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01499 return -1; 01500 } 01501 01502 // Get the local port the system picked up 01503 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, myaddress, 01504 sizeof(myaddress), myctrlport, sizeof(myctrlport), NI_NUMERICHOST | NI_NUMERICSERV) ) 01505 { 01506 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01507 return -1; 01508 } 01509 01510 // Let's now check the data port 01511 if (getsockname(fp->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1) 01512 { 01513 sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01514 return -1; 01515 } 01516 01517 // Get the local port the system picked up 01518 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen,NULL, 0, mydataport, sizeof(mydataport), NI_NUMERICSERV) ) 01519 { 01520 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01521 return -1; 01522 } 01523 01524 currentfiltersize= strlen(fp->currentfilter); 01525 01526 newfilter= (char *) malloc (currentfiltersize + newstringsize + 1); 01527 01528 if (currentfiltersize) 01529 { 01530 snprintf(newfilter, currentfiltersize + newstringsize, 01531 "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)", 01532 fp->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport); 01533 } 01534 else 01535 { 01536 snprintf(newfilter, currentfiltersize + newstringsize, 01537 "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)", 01538 myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport); 01539 } 01540 01541 newfilter[currentfiltersize + newstringsize]= 0; 01542 01543 // This is only an hack to make the pcap_compile() working properly 01544 fp->rmt_clientside= 0; 01545 01546 if (pcap_compile(fp, prog, newfilter, 1, 0) == -1) 01547 RetVal= -1; 01548 01549 // This is only an hack to make the pcap_compile() working properly 01550 fp->rmt_clientside= 1; 01551 01552 free(newfilter); 01553 } 01554 01555 return RetVal; 01556 } 01557 01572 int pcap_setsampling_remote(pcap_t *p) 01573 { 01574 int retval; // general variable used to keep the return value of other functions 01575 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 01576 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01577 struct rpcap_header header; // To keep the reply message 01578 struct rpcap_sampling *sampling_pars; // Structure that is needed to send sampling parameters to the remote host 01579 01580 // If no samping is requested, return 'ok' 01581 if (p->rmt_samp.method == PCAP_SAMP_NOSAMP) 01582 return 0; 01583 01584 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 01585 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) ) 01586 return -1; 01587 01588 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling) ); 01589 01590 // Fill the structure needed to open an adapter remotely 01591 sampling_pars= (struct rpcap_sampling *) &sendbuf[sendbufidx]; 01592 01593 if ( sock_bufferize(NULL, sizeof(struct rpcap_sampling), NULL, 01594 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) ) 01595 return -1; 01596 01597 memset(sampling_pars, 0, sizeof(struct rpcap_sampling) ); 01598 01599 sampling_pars->method= p->rmt_samp.method; 01600 sampling_pars->value= htonl(p->rmt_samp.value); 01601 01602 if ( sock_send(p->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE) ) 01603 return -1; 01604 01605 // Waits for the answer 01606 if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1) 01607 return -1; 01608 01609 // Checks if the message is correct 01610 retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0); 01611 01612 if (retval != RPCAP_MSG_SETSAMPLING_REPLY) // the message is not the one expected 01613 { 01614 switch (retval) 01615 { 01616 case -3: // Unrecoverable network error 01617 case -2: // The other endpoint sent a message that is not allowed here 01618 case -1: // The other endpoint has a version number that is not compatible with our 01619 case RPCAP_MSG_ERROR: 01620 // Do nothing; just exit from here; the error code is already into the errbuf 01621 return -1; 01622 01623 default: 01624 { 01625 SOCK_ASSERT("Internal error", 0); 01626 return -1; 01627 }; 01628 } 01629 } 01630 01631 if (ntohl(header.plen) != 0) // the message has an unexpected size 01632 { 01633 if (sock_discard(p->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1) 01634 return -1; 01635 } 01636 01637 return 0; 01638 01639 } 01640 01641 01642 01643 01644 01645 /********************************************************* 01646 * * 01647 * Miscellaneous functions * 01648 * * 01649 *********************************************************/ 01650 01651 01676 int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf) 01677 { 01678 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered 01679 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01680 uint16 length; 01681 01682 length= (uint16) strlen(error); 01683 01684 if (length > PCAP_ERRBUF_SIZE) 01685 length= PCAP_ERRBUF_SIZE; 01686 01687 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length); 01688 01689 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 01690 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) ) 01691 return -1; 01692 01693 if ( sock_bufferize(error, length, sendbuf, &sendbufidx, 01694 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) ) 01695 return -1; 01696 01697 if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) ) 01698 return -1; 01699 01700 return 0; 01701 } 01702 01703 01704 01723 int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf) 01724 { 01725 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data that has to be sent is buffered 01726 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01727 uint16 length; // length of the payload of this message 01728 struct rpcap_auth *rpauth; 01729 uint16 auth_type; 01730 struct rpcap_header header; 01731 int retval; // temp variable which stores functions return value 01732 01733 if (auth) 01734 { 01735 auth_type= auth->type; 01736 01737 switch (auth->type) 01738 { 01739 case RPCAP_RMTAUTH_NULL: 01740 length= sizeof (struct rpcap_auth); 01741 break; 01742 01743 case RPCAP_RMTAUTH_PWD: 01744 length= sizeof (struct rpcap_auth); 01745 if (auth->username) length+= strlen(auth->username); 01746 if (auth->password) length+= strlen(auth->password); 01747 break; 01748 01749 default: 01750 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized."); 01751 return -1; 01752 } 01753 } 01754 else 01755 { 01756 auth_type= RPCAP_RMTAUTH_NULL; 01757 length= sizeof (struct rpcap_auth); 01758 } 01759 01760 01761 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 01762 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) ) 01763 return -1; 01764 01765 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length); 01766 01767 rpauth= (struct rpcap_auth *) &sendbuf[sendbufidx]; 01768 01769 if ( sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL, 01770 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) ) 01771 return -1; 01772 01773 memset(rpauth, 0, sizeof (struct rpcap_auth) ); 01774 01775 rpauth->type= htons(auth_type); 01776 01777 if (auth_type == RPCAP_RMTAUTH_PWD) 01778 { 01779 01780 if (auth->username) 01781 rpauth->slen1= strlen(auth->username); 01782 else 01783 rpauth->slen1= 0; 01784 01785 if ( sock_bufferize(auth->username, rpauth->slen1, sendbuf, 01786 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) ) 01787 return -1; 01788 01789 if (auth->password) 01790 rpauth->slen2= strlen(auth->password); 01791 else 01792 rpauth->slen2= 0; 01793 01794 if ( sock_bufferize(auth->password, rpauth->slen2, sendbuf, 01795 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) ) 01796 return -1; 01797 01798 rpauth->slen1= htons (rpauth->slen1); 01799 rpauth->slen2= htons (rpauth->slen2); 01800 } 01801 01802 if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) ) 01803 return -1; 01804 01805 if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1) 01806 return -1; 01807 01808 retval= rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0); 01809 01810 if (retval != RPCAP_MSG_AUTH_REPLY) // the message is not the one expected 01811 { 01812 switch (retval) 01813 { 01814 case -3: // Unrecoverable network error 01815 case -2: // The other endpoint sent a message that is not allowed here 01816 case -1: // The other endpoint has a version number that is not compatible with our 01817 // Do nothing; just exit from here; the error code is already into the errbuf 01818 return -1; 01819 01820 case RPCAP_MSG_ERROR: 01821 { 01822 return -1; 01823 }; 01824 01825 default: 01826 { 01827 SOCK_ASSERT("Internal error", 0); 01828 return -1; 01829 }; 01830 } 01831 } 01832 01833 if (ntohl(header.plen) ) 01834 { 01835 if (sock_discard(sock, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE) ) 01836 return -1; 01837 } 01838 01839 return 0; 01840 } 01841 01842 01843 01865 void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length) 01866 { 01867 memset(header, 0, sizeof (struct rpcap_header) ); 01868 01869 header->ver= RPCAP_VERSION; 01870 header->type= type; 01871 header->value= htons(value); 01872 header->plen= htonl(length); 01873 } 01874 01875 01876 01920 int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...) 01921 { 01922 va_list ap; 01923 uint8 type; 01924 int32 len; 01925 01926 va_start(ap, first); 01927 01928 // Check if the present version of the protocol can handle this message 01929 if ( rpcap_checkver(sock, header, errbuf) ) 01930 { 01931 SOCK_ASSERT(errbuf, 1); 01932 01933 va_end(ap); 01934 return -1; 01935 } 01936 01937 type= first; 01938 01939 while ( type != 0 ) 01940 { 01941 // The message matches with one of the types listed 01942 // There is no need of conversions since both values are uint8 01943 01944 // Check if the other side reported an error. 01945 // If yes, it retrieves it and it returns it back to the caller 01946 if (header->type == RPCAP_MSG_ERROR) 01947 { 01948 len= ntohl(header->plen); 01949 01950 if (len >= PCAP_ERRBUF_SIZE) 01951 { 01952 if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE - 1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) 01953 return -3; 01954 01955 sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), NULL, 0); 01956 01957 // Put '\0' at the end of the string 01958 errbuf[PCAP_ERRBUF_SIZE - 1]= 0; 01959 } 01960 else 01961 { 01962 if (sock_recv(sock, errbuf, len, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1) 01963 return -3; 01964 01965 // Put '\0' at the end of the string 01966 errbuf[len]= 0; 01967 } 01968 01969 01970 va_end(ap); 01971 return header->type; 01972 } 01973 01974 if (header->type == type) 01975 { 01976 va_end(ap); 01977 return header->type; 01978 } 01979 01980 // get next argument 01981 type= va_arg(ap, int); 01982 } 01983 01984 // we already have an error, so please discard this one 01985 sock_discard(sock, ntohl(header->plen), NULL, 0); 01986 01987 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here."); 01988 SOCK_ASSERT(errbuf, 1); 01989 01990 va_end(ap); 01991 return -2; 01992 } 01993 01994 01995 02019 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf) 02020 { 02021 /* 02022 This is a sample function. 02023 02024 In the real world, you have to check at the type code, 02025 and decide accordingly. 02026 */ 02027 02028 if (header->ver != RPCAP_VERSION) 02029 { 02030 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded."); 02031 02032 // we already have an error, so please discard this one 02033 sock_discard(sock, ntohl(header->plen), NULL, 0); 02034 return -1; 02035 } 02036 02037 return 0; 02038 } 02039 02040 02041 02062 int rpcap_remoteact_getsock(const char *host, char *errbuf) 02063 { 02064 struct activehosts *temp; // temp var needed to scan the host list chain 02065 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address 02066 int retval; 02067 02068 // retrieve the network address corresponding to 'host' 02069 addrinfo = NULL; 02070 memset(&hints, 0, sizeof (struct addrinfo) ); 02071 hints.ai_family = PF_UNSPEC; 02072 hints.ai_socktype= SOCK_STREAM; 02073 02074 retval = getaddrinfo(host, "0", &hints, &addrinfo); 02075 if (retval != 0) 02076 { 02077 snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval)); 02078 return -1; 02079 } 02080 02081 temp= activeHosts; 02082 02083 while (temp) 02084 { 02085 ai_next= addrinfo; 02086 while(ai_next) 02087 { 02088 if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0) 02089 return (temp->sockctrl ); 02090 02091 ai_next= ai_next->ai_next; 02092 } 02093 temp= temp->next; 02094 } 02095 02096 if (addrinfo) 02097 freeaddrinfo(addrinfo); 02098 02099 // The host you want to get the socket ID does not have an active connection 02100 return 0; 02101 } 02102 02103 02104 02105 02106
documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.