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 00069 /* 00070 \brief Global variable; needed to keep the message due to an error that we want to discard. 00071 00072 This can happen, for instance, because we already have an error message and we want to keep 00073 the first one. 00074 */ 00075 char fakeerrbuf[PCAP_ERRBUF_SIZE + 1]; 00076 00077 00079 struct activehosts *activeHosts; 00080 00081 00082 /**************************************************** 00083 * * 00084 * Locally defined functions * 00085 * * 00086 ****************************************************/ 00087 void rpcap_thrdatamain_stream(void *ptr); 00088 void rpcap_thrdatamain_dgram(void *ptr); 00089 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf); 00090 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode); 00091 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog); 00092 00093 00094 00095 00096 /**************************************************** 00097 * * 00098 * Function bodies * 00099 * * 00100 ****************************************************/ 00101 00135 int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf) 00136 { 00137 // Warning: we support only AF_INET and AF_INET6 00138 if ( ntohs(sockaddrin->ss_family) == AF_INET) 00139 { 00140 struct sockaddr_in *sockaddr; 00141 00142 sockaddr= (struct sockaddr_in *) sockaddrin; 00143 sockaddr->sin_family= ntohs(sockaddr->sin_family); 00144 sockaddr->sin_port= ntohs(sockaddr->sin_port); 00145 00146 (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in) ); 00147 if ( (*sockaddrout) == NULL) 00148 { 00149 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00150 return -1; 00151 } 00152 memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in) ); 00153 return 0; 00154 } 00155 if ( ntohs(sockaddrin->ss_family) == AF_INET6) 00156 { 00157 struct sockaddr_in6 *sockaddr; 00158 00159 sockaddr= (struct sockaddr_in6 *) sockaddrin; 00160 sockaddr->sin6_family= ntohs(sockaddr->sin6_family); 00161 sockaddr->sin6_port= ntohs(sockaddr->sin6_port); 00162 sockaddr->sin6_flowinfo= ntohl(sockaddr->sin6_flowinfo); 00163 sockaddr->sin6_scope_id= ntohl(sockaddr->sin6_scope_id); 00164 00165 (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in6) ); 00166 if ( (*sockaddrout) == NULL) 00167 { 00168 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00169 return -1; 00170 } 00171 memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in6) ); 00172 return 0; 00173 } 00174 00175 // It is neither AF_INET nor AF_INET6 00176 *sockaddrout= NULL; 00177 return 0; 00178 } 00179 00180 00181 00205 int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data) 00206 { 00207 struct rpcap_header *header; // general header according to the RPCAP format 00208 struct rpcap_pkthdr *net_pkt_header; // header of the packet 00209 char netbuf[RPCAP_NETBUF_SIZE]; // size of the network buffer in which the packet is copied, just for UDP 00210 unsigned int nread; // number of bytes (of payload) currently read from the network (referred to the current pkt) 00211 int retval; // generic return value 00212 00213 // Structures needed for the select() call 00214 fd_set rfds; // set of socket descriptors we have to check 00215 struct timeval tv; // maximum time the select() can block waiting for data 00216 00217 00218 // Define the read timeout, to be used in the select() 00219 // 'timeout', in pcap_t, is in milliseconds; we have to convert it into sec and microsec 00220 #ifdef linux 00221 tv.tv_sec = p->md.timeout/1000; 00222 tv.tv_usec = (p->md.timeout - tv.tv_sec * 1000 )* 1000; 00223 #else 00224 tv.tv_sec = p->timeout/1000; 00225 tv.tv_usec = (p->timeout - tv.tv_sec * 1000 )* 1000; 00226 #endif 00227 00228 // Watch out sockdata to see if it has input 00229 FD_ZERO(&rfds); 00230 00231 // 'fp->rmt_sockdata' has always to be set before calling the select(), 00232 // since it is cleared by the select() 00233 FD_SET(p->rmt_sockdata, &rfds); 00234 00235 retval = select(p->rmt_sockdata + 1, &rfds, NULL, NULL, &tv); 00236 if (retval == -1) 00237 { 00238 sock_geterror("select(): ", p->errbuf, PCAP_ERRBUF_SIZE); 00239 return -1; 00240 } 00241 00242 // There is no data waiting, so return '0' 00243 if (retval == 0) 00244 return 0; 00245 00246 // data is here; so, let's copy it into the user buffer 00247 // I'm going to read a new packet; so I reset the number of bytes (payload only) read 00248 nread= 0; 00249 00250 // We have to define 'header' as a pointer to a larger buffer, 00251 // because in case of UDP we have to read all the message within a single call 00252 header= (struct rpcap_header *) netbuf; 00253 net_pkt_header= (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header) ); 00254 00255 if (p->rmt_flags & PCAP_OPENFLAG_UDP_DP) 00256 { 00257 // Read the entire message from the network 00258 if (sock_recv(p->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, SOCK_RECEIVEALL_NO, p->errbuf, PCAP_ERRBUF_SIZE) == -1) 00259 return -1; 00260 } 00261 else 00262 { 00263 if (sock_recv(p->rmt_sockdata, netbuf, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1) 00264 return -1; 00265 } 00266 00267 // Checks if the message is correct 00268 retval= rpcap_checkmsg(p->errbuf, p->rmt_sockdata, header, RPCAP_MSG_PACKET, 0); 00269 00270 if (retval != RPCAP_MSG_PACKET) // the message is not the one expected 00271 { 00272 switch (retval) 00273 { 00274 case -3: // Unrecoverable network error 00275 return -1; // Do nothing; just exit from here; the error code is already into the errbuf 00276 00277 case -2: // The other endpoint sent a message that is not allowed here 00278 case -1: // The other endpoint has a version number that is not compatible with our 00279 return 0; // Return 'no packets received' 00280 00281 default: 00282 { 00283 SOCK_ASSERT("Internal error", 1); 00284 return 0; // Return 'no packets received 00285 }; 00286 } 00287 } 00288 00289 // In case of TCP, read the remaining of the packet from the socket 00290 if ( !(p->rmt_flags & PCAP_OPENFLAG_UDP_DP)) 00291 { 00292 // Read the RPCAP packet header from the network 00293 if ( (nread= sock_recv(p->rmt_sockdata, (char *) net_pkt_header, 00294 sizeof(struct rpcap_pkthdr), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1) 00295 return -1; 00296 } 00297 00298 if ( (ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) p->bufsize) ) 00299 { 00300 // Initialize returned structures 00301 *pkt_header= (struct pcap_pkthdr *) p->buffer; 00302 *pkt_data= p->buffer + sizeof(struct pcap_pkthdr); 00303 00304 (*pkt_header)->caplen= ntohl(net_pkt_header->caplen); 00305 (*pkt_header)->len= ntohl(net_pkt_header->len); 00306 (*pkt_header)->ts.tv_sec= ntohl(net_pkt_header->timestamp_sec); 00307 (*pkt_header)->ts.tv_usec= ntohl(net_pkt_header->timestamp_usec); 00308 00309 // I don't update the counter of the packets dropped by the network since we're using TCP; 00310 // therefore no packets are dropped. Just update the number of packets received correctly 00311 p->md.TotCapt++; 00312 00313 // Copies the packet into the data buffer 00314 if (p->rmt_flags & PCAP_OPENFLAG_UDP_DP) 00315 { 00316 unsigned int npkt; 00317 00318 // In case of UDP the packet has already been read; we have to copy it into 'buffer' 00319 // Another option should bne to declare 'netbuf' as 'static'; however this prevents 00320 // using several pcap instances within the same process (because the static buffer is shared among 00321 // all processes) 00322 strncpy(*pkt_data, netbuf + sizeof(struct rpcap_header) + sizeof(struct pcap_pkthdr), (*pkt_header)->caplen); 00323 00324 // We're using UDP, so we need to update the counter of the packets dropped by the network 00325 npkt= ntohl(net_pkt_header->npkt); 00326 00327 if (p->md.TotCapt != npkt) 00328 { 00329 p->md.TotNetDrops+= (npkt - p->md.TotCapt); 00330 p->md.TotCapt= npkt; 00331 } 00332 00333 } 00334 else 00335 { 00336 // In case of TCP, read the remaining of the packet from the socket 00337 if ( (nread+= sock_recv(p->rmt_sockdata, *pkt_data, (*pkt_header)->caplen, SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1) 00338 return -1; 00339 00340 // Checks if all the data has been read; if not, discard the data in excess 00341 // This check has to be done only on TCP connections 00342 if (nread != ntohl(header->plen)) 00343 sock_discard(p->rmt_sockdata, ntohl(header->plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE); 00344 } 00345 00346 00347 // Packet read successfully 00348 return 1; 00349 } 00350 else 00351 { 00352 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Received a packet that is larger than the internal buffer size."); 00353 return -1; 00354 } 00355 00356 } 00357 00358 00373 int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 00374 { 00375 struct pcap_pkthdr *pkt_header; 00376 u_char *pkt_data; 00377 int n = 0; 00378 00379 while ( (++n <= cnt) || (cnt < 0) ) 00380 { 00381 if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) ) 00382 (*callback)(user, pkt_header, pkt_data); 00383 else 00384 return n; 00385 } 00386 return n; 00387 } 00388 00389 00403 void pcap_close_remote(pcap_t *fp) 00404 { 00405 struct rpcap_header header; // header of the RPCAP packet 00406 struct activehosts *temp; // temp var needed to scan the host list chain, to detect if we're in active mode 00407 int active= 0; // active mode or not? 00408 00409 // detect if we're in active mode 00410 temp= activeHosts; 00411 while (temp) 00412 { 00413 if (temp->sockctrl == fp->rmt_sockctrl) 00414 { 00415 active= 1; 00416 break; 00417 } 00418 temp= temp->next; 00419 } 00420 00421 if (!active) 00422 { 00423 rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0); 00424 00425 // I don't check for errors, since I'm going to close everything 00426 sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fakeerrbuf, PCAP_ERRBUF_SIZE); 00427 } 00428 else 00429 { 00430 rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REQ, 0, 0); 00431 00432 // I don't check for errors, since I'm going to close everything 00433 sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fakeerrbuf, PCAP_ERRBUF_SIZE); 00434 00435 // wait for the answer 00436 // Don't check what we got, since the present libpcap does not uses this pcap_t anymore 00437 sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fakeerrbuf, PCAP_ERRBUF_SIZE); 00438 00439 if ( ntohl(header.plen) != 0) 00440 sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fakeerrbuf, PCAP_ERRBUF_SIZE); 00441 } 00442 00443 if (fp->rmt_sockdata) 00444 { 00445 sock_close(fp->rmt_sockdata, fakeerrbuf, PCAP_ERRBUF_SIZE); 00446 fp->rmt_sockdata= 0; 00447 } 00448 00449 if ( (!active) && (fp->rmt_sockctrl) ) 00450 sock_close(fp->rmt_sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE); 00451 00452 fp->rmt_sockctrl= 0; 00453 00454 // To avoid inconsistencies in the number of sock_init() 00455 sock_cleanup(); 00456 } 00457 00458 00459 00469 int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps) 00470 { 00471 struct pcap_stat *retval; 00472 00473 retval= rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD); 00474 00475 if (retval) 00476 return 0; 00477 else 00478 return -1; 00479 } 00480 00481 00482 00492 struct pcap_stat *pcap_stats_ex_remote(pcap_t *p) 00493 { 00494 // '0' (third param) means 'standard pcap_stats()' 00495 return (rpcap_stats_remote(p, &(p->md.stat), PCAP_STATS_EX)); 00496 } 00497 00498 00499 00530 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode) 00531 { 00532 struct rpcap_header header; // header of the RPCAP packet 00533 struct rpcap_stats netstats; // statistics sent on the network 00534 unsigned int nread= 0; // number of bytes of the payload read from the socket 00535 int retval; // temp variable which stores functions return value 00536 00537 rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0); 00538 00539 // Send the PCAP_STATS command 00540 if (sock_send(p->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE) ) 00541 goto error; 00542 00543 // Receive the RPCAP stats reply message 00544 if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1) 00545 goto error; 00546 00547 // Checks if the message is correct 00548 retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0); 00549 00550 if (retval != RPCAP_MSG_STATS_REPLY) // the message is not the one expected 00551 { 00552 switch (retval) 00553 { 00554 case -3: // Unrecoverable network error 00555 case -2: // The other endpoint send a message that is not allowed here 00556 case -1: // The other endpoint has a version number that is not compatible with our 00557 goto error; 00558 00559 case RPCAP_MSG_ERROR: // The other endpoint reported an error 00560 // Update nread, since the rpcap_checkmsg() already purged the buffer 00561 nread = ntohl(header.plen); 00562 00563 // Do nothing; just exit; the error code is already into the errbuf 00564 goto error; 00565 00566 default: 00567 { 00568 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 00569 goto error; 00570 }; 00571 } 00572 } 00573 00574 if ( (nread= sock_recv(p->rmt_sockctrl, (char *) &netstats, sizeof(struct rpcap_stats), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1) 00575 goto error; 00576 00577 if (mode == PCAP_STATS_STANDARD) 00578 { 00579 ps->ps_drop= ntohl(netstats.krnldrop); 00580 ps->ps_ifdrop= ntohl(netstats.ifdrop); 00581 ps->ps_recv= ntohl(netstats.ifrecv); 00582 } 00583 else 00584 { 00585 ps->ps_capt= p->md.TotCapt; 00586 ps->ps_drop= ntohl(netstats.krnldrop); 00587 ps->ps_ifdrop= ntohl(netstats.ifdrop); 00588 ps->ps_netdrop= p->md.TotNetDrops; 00589 ps->ps_recv= ntohl(netstats.ifrecv); 00590 ps->ps_sent= ntohl(netstats.svrcapt); 00591 } 00592 00593 // Checks if all the data has been read; if not, discard the data in excess 00594 if (nread != ntohl(header.plen)) 00595 { 00596 if (sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE) == 1) 00597 goto error; 00598 } 00599 00600 return ps; 00601 00602 error: 00603 if (nread != ntohl(header.plen)) 00604 sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE); 00605 00606 return NULL; 00607 } 00608 00609 00610 00611 00650 pcap_t *pcap_opensource_remote(const char *source, struct pcap_rmtauth *auth, char *errbuf) 00651 { 00652 char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE]; 00653 00654 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 00655 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00656 struct pcap *fp= NULL; // pcap_t main variable 00657 unsigned int nread= 0; // number of bytes of the payload read from the socket 00658 int retval; // store the return value of the functions 00659 int active= 0; // '1' if we're in active mode 00660 00661 // socket-related variables 00662 struct addrinfo hints; // temp, needed to open a socket connection 00663 struct addrinfo *addrinfo; // temp, needed to open a socket connection 00664 SOCKET sockctrl= 0; // socket descriptor of the control connection 00665 00666 // RPCAP-related variables 00667 struct rpcap_header header; // header of the RPCAP packet 00668 struct rpcap_openreply openreply; // open reply message 00669 00670 00671 // determine the type of the source (NULL, file, local, remote) 00672 // You must have a valid source string even if we're in active mode, because otherwise 00673 // the call to the following funciton will fail. 00674 if (pcap_parsesrcstr(source, &retval, host, ctrlport, iface, errbuf) == -1) 00675 return NULL; 00676 00677 if ( retval != PCAP_SRC_IFREMOTE) 00678 { 00679 snprintf(errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces"); 00680 return NULL; 00681 } 00682 00683 addrinfo= NULL; 00684 00685 // Warning: this call can be the first one called by the user. 00686 // For this reason, we have to initialize the WinSock support. 00687 if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1) 00688 return NULL; 00689 00690 retval= rpcap_remoteact_getsock(host, errbuf); 00691 00692 if (retval == -1) 00693 return NULL; 00694 00695 // The capturing machine is in active mode 00696 if (retval) 00697 { 00698 sockctrl= retval; 00699 active= 1; 00700 } 00701 else 00702 { 00703 memset(&hints, 0, sizeof(struct addrinfo) ); 00704 hints.ai_family = PF_UNSPEC; 00705 hints.ai_socktype = SOCK_STREAM; 00706 00707 if ( (ctrlport == NULL) || (ctrlport[0] == 0) ) 00708 { 00709 // the user chose not to specify the port 00710 if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) 00711 return NULL; 00712 } 00713 else 00714 { 00715 // the user chose not to specify the port 00716 if (sock_initaddress(host, ctrlport, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) 00717 return NULL; 00718 } 00719 00720 if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1) 00721 goto error; 00722 00723 freeaddrinfo(addrinfo); 00724 addrinfo= NULL; 00725 00726 if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1) 00727 goto error; 00728 } 00729 00730 00731 // Now it's time to start playing with the RPCAP protocol 00732 // RPCAP open command: create the request message 00733 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 00734 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) ) 00735 goto error; 00736 00737 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, strlen(iface) ); 00738 00739 if ( sock_bufferize(iface, strlen(iface), sendbuf, &sendbufidx, 00740 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) ) 00741 goto error; 00742 00743 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) ) 00744 goto error; 00745 00746 // Receive the RPCAP open reply message 00747 if (sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1) 00748 goto error; 00749 00750 // Checks if the message is correct 00751 retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0); 00752 00753 if (retval != RPCAP_MSG_OPEN_REPLY) // the message is not the one expected 00754 { 00755 switch (retval) 00756 { 00757 case -3: // Unrecoverable network error 00758 case -2: // The other endpoint send a message that is not allowed here 00759 case -1: // The other endpoint has a version number that is not compatible with our 00760 goto error; 00761 00762 case RPCAP_MSG_ERROR: // The other endpoint reported an error 00763 // Update nread, since the rpcap_checkmsg() already purged the buffer 00764 nread = ntohl(header.plen); 00765 // Do nothing; just exit; the error code is already into the errbuf 00766 goto error; 00767 00768 default: 00769 { 00770 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 00771 goto error; 00772 }; 00773 } 00774 } 00775 00776 00777 if ( (nread+= sock_recv(sockctrl, (char *) &openreply, sizeof(struct rpcap_openreply), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1) 00778 goto error; 00779 00780 // Allocates a pcap_t struct for this end of the connection 00781 fp = (pcap_t *) malloc( sizeof(pcap_t) ); 00782 if (fp == NULL) 00783 { 00784 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00785 goto error; 00786 } 00787 00788 memset(fp, 0, sizeof(pcap_t)); 00789 00790 // Set proper fields into the pcap_t struct 00791 fp->linktype= ntohl(openreply.linktype); 00792 fp->tzoff= ntohl(openreply.tzoff); 00793 fp->rmt_sockctrl= sockctrl; 00794 fp->rmt_clientside= 1; 00795 00796 00797 // Checks if all the data has been read; if not, discard the data in excess 00798 if (nread != ntohl(header.plen)) 00799 { 00800 if (sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE) == 1) 00801 goto error; 00802 } 00803 return fp; 00804 00805 error: 00806 // When the connection has been established, we have to close it. So, at the 00807 // beginning of this function, if an error occur we return immediately with 00808 // a return NULL; when the connection is established, we have to come here 00809 // ('goto error;') in order to close everything properly. 00810 00811 // Checks if all the data has been read; if not, discard the data in excess 00812 if (nread != ntohl(header.plen)) 00813 sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE); 00814 00815 if (addrinfo) 00816 freeaddrinfo(addrinfo); 00817 00818 if (!active) 00819 sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE); 00820 00821 if (fp) 00822 { 00823 pcap_close(fp); 00824 fp= NULL; 00825 } 00826 00827 return NULL; 00828 } 00829 00830 00831 00832 00833 00834 00835 00858 int pcap_startcapture_remote(pcap_t *fp) 00859 { 00860 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 00861 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00862 char portdata[PCAP_BUF_SIZE]; // temp variable needed to keep the network port for the the data connection 00863 unsigned int nread= 0; // number of bytes of the payload read from the socket 00864 int retval; // store the return value of the functions 00865 int active= 0; // '1' if we're in active mode 00866 struct activehosts *temp; // temp var needed to scan the host list chain, to detect if we're in active mode 00867 char host[INET6_ADDRSTRLEN + 1]; // numeric name of the other host 00868 00869 // socket-related variables 00870 struct addrinfo hints; // temp, needed to open a socket connection 00871 struct addrinfo *addrinfo; // temp, needed to open a socket connection 00872 SOCKET sockdata= 0; // socket descriptor of the data connection 00873 struct sockaddr_storage saddr; // temp, needed to retrieve the network data port chosen on the local machine 00874 socklen_t saddrlen; // temp, needed to retrieve the network data port chosen on the local machine 00875 int ai_family; // temp, keeps the address family used by the control connection 00876 00877 // RPCAP-related variables 00878 struct rpcap_header header; // header of the RPCAP packet 00879 struct rpcap_startcapreq *startcapreq; // start capture request message 00880 struct rpcap_startcapreply startcapreply; // start capture reply message 00881 00882 // Variables related to the buffer setting 00883 int res, itemp; 00884 int sockbufsize= 0; 00885 00886 00887 // Let's check if sampling has been required. 00888 // If so, let's set it first 00889 if (pcap_setsampling_remote(fp) != 0) 00890 return -1; 00891 00892 00893 // detect if we're in active mode 00894 temp= activeHosts; 00895 while (temp) 00896 { 00897 if (temp->sockctrl == fp->rmt_sockctrl) 00898 { 00899 active= 1; 00900 break; 00901 } 00902 temp= temp->next; 00903 } 00904 00905 addrinfo= NULL; 00906 00907 // Gets the complete sockaddr structure used in the ctrl connection 00908 // This is needed to get the address family of the control socket 00909 // Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct, 00910 // since the ctrl socket can already be open in case of active mode; 00911 // so I would have to call getpeername() anyway 00912 saddrlen = sizeof(struct sockaddr_storage); 00913 if (getpeername(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1) 00914 { 00915 sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00916 goto error; 00917 } 00918 ai_family= ((struct sockaddr_storage *) &saddr)->ss_family; 00919 00920 // Get the numeric address of the remote host we are connected to 00921 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, host, 00922 sizeof(host), NULL, 0, NI_NUMERICHOST) ) 00923 { 00924 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00925 goto error; 00926 } 00927 00928 /* 00929 Data connection is opened by the server toward the client if: 00930 - we're using TCP, and the user wants us to be in active mode 00931 - we're using UDP 00932 */ 00933 if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ) 00934 { 00935 // We have to create a new socket to receive packets 00936 // We have to do that immediately, since we have to tell the other 00937 // end which network port we picked up 00938 memset(&hints, 0, sizeof(struct addrinfo) ); 00939 // TEMP addrinfo is NULL in case of active 00940 hints.ai_family = ai_family; // Use the same address family of the control socket 00941 hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ? SOCK_DGRAM : SOCK_STREAM; 00942 hints.ai_flags = AI_PASSIVE; // Data connection is opened by the server toward the client 00943 00944 // Let's the server pick up a free network port for us 00945 if (sock_initaddress(NULL, "0", &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 00946 goto error; 00947 00948 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 00949 1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1) 00950 goto error; 00951 00952 // addrinfo is no longer used 00953 freeaddrinfo(addrinfo); 00954 addrinfo= NULL; 00955 00956 // get the complete sockaddr structure used in the data connection 00957 saddrlen = sizeof(struct sockaddr_storage); 00958 if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1) 00959 { 00960 sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00961 goto error; 00962 } 00963 00964 // Get the local port the system picked up 00965 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 00966 0, portdata, sizeof(portdata), NI_NUMERICSERV) ) 00967 { 00968 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00969 goto error; 00970 } 00971 } 00972 00973 // Now it's time to start playing with the RPCAP protocol 00974 // RPCAP start ca[ture command: create the request message 00975 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 00976 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 00977 goto error; 00978 00979 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0, 00980 sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn) ); 00981 00982 // Fill the structure needed to open an adapter remotely 00983 startcapreq= (struct rpcap_startcapreq *) &sendbuf[sendbufidx]; 00984 00985 if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL, 00986 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 00987 goto error; 00988 00989 memset(startcapreq, 0, sizeof(struct rpcap_startcapreq) ); 00990 00991 // By default, apply half the timeout on one side, half of the other 00992 #ifdef linux 00993 fp->md.timeout= fp->md.timeout/2; 00994 startcapreq->read_timeout= htonl(fp->md.timeout); 00995 #else 00996 fp->timeout= fp->timeout/2; 00997 startcapreq->read_timeout= htonl(fp->timeout); 00998 #endif 00999 01000 // portdata on the openreq is meaningful only if we're in active mode 01001 if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ) 01002 { 01003 sscanf(portdata, "%d", &(startcapreq->portdata)); 01004 startcapreq->portdata= htons(startcapreq->portdata); 01005 } 01006 01007 startcapreq->snaplen= htonl(fp->snapshot); 01008 startcapreq->flags= 0; 01009 if (fp->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS) 01010 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_PROMISC; 01011 if (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) 01012 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_DGRAM; 01013 if (active) 01014 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN; 01015 01016 startcapreq->flags= htons(startcapreq->flags); 01017 01018 // Pack the capture filter 01019 if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode) ) 01020 goto error; 01021 01022 if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01023 goto error; 01024 01025 01026 // Receive the RPCAP start capture reply message 01027 if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01028 goto error; 01029 01030 // Checks if the message is correct 01031 retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0); 01032 01033 if (retval != RPCAP_MSG_STARTCAP_REPLY) // the message is not the one expected 01034 { 01035 switch (retval) 01036 { 01037 case -3: // Unrecoverable network error 01038 case -2: // The other endpoint send a message that is not allowed here 01039 case -1: // The other endpoint has a version number that is not compatible with our 01040 goto error; 01041 01042 case RPCAP_MSG_ERROR: // The other endpoint reported an error 01043 // Update nread, since the rpcap_checkmsg() already purged the buffer 01044 nread = ntohl(header.plen); 01045 // Do nothing; just exit; the error code is already into the errbuf 01046 goto error; 01047 01048 default: 01049 { 01050 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 01051 goto error; 01052 }; 01053 } 01054 } 01055 01056 01057 if ( (nread+= sock_recv(fp->rmt_sockctrl, (char *) &startcapreply, 01058 sizeof(struct rpcap_startcapreply), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1) 01059 goto error; 01060 01061 // In case of UDP data stream, the connection is always opened by the daemon 01062 // So, this case is already covered by the code above. 01063 // Now, we have still to handle TCP connections, because: 01064 // - if we're in active mode, we have to wait for a remote connection 01065 // - if we're in passive more, we have to start a connection 01066 // 01067 // We have to do he job in two steps because in case we're opening a tcp connection, we have 01068 // to tell the port we're using to the remote side; in case we're accepting a TCP 01069 // connection, we have to wait this info from the remote side. 01070 01071 if (!(fp->rmt_flags & PCAP_OPENFLAG_UDP_DP)) 01072 { 01073 if (!active) 01074 { 01075 memset(&hints, 0, sizeof(struct addrinfo) ); 01076 hints.ai_family = ai_family; // Use the same address family of the control socket 01077 hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ? SOCK_DGRAM : SOCK_STREAM; 01078 01079 sprintf(portdata, "%d", ntohs(startcapreply.portdata) ); 01080 01081 // Let's the server pick up a free network port for us 01082 if (sock_initaddress(host, portdata, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01083 goto error; 01084 01085 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1) 01086 goto error; 01087 01088 // addrinfo is no longer used 01089 freeaddrinfo(addrinfo); 01090 addrinfo= NULL; 01091 } 01092 else 01093 { 01094 SOCKET socktemp; // We need another socket, since we're going to accept() a connection 01095 01096 // Connection creation 01097 saddrlen = sizeof(struct sockaddr_storage); 01098 01099 socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen); 01100 01101 if (socktemp == -1) 01102 { 01103 sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01104 goto error; 01105 } 01106 01107 // Now that I accepted the connection, the server socket is no longer needed 01108 sock_close(sockdata, fp->errbuf, PCAP_ERRBUF_SIZE); 01109 sockdata= socktemp; 01110 } 01111 } 01112 01113 // Let's save the socket of the data connection 01114 fp->rmt_sockdata= sockdata; 01115 01116 // Allocates WinPcap/libpcap user buffer, which is a socket buffer in case of a remote capture 01117 // It has the same size of the one used on the other side of the connection 01118 fp->bufsize= ntohl(startcapreply.bufsize); 01119 01120 // Let's get the actual size of the socket buffer 01121 itemp= sizeof(sockbufsize); 01122 01123 res= getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &itemp); 01124 if (res == -1) 01125 { 01126 sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE); 01127 SOCK_ASSERT(fp->errbuf, 1); 01128 } 01129 01130 /* 01131 Warning: on some kernels (e.g. linux), the size of the user buffer does not take 01132 into account the pcap_header and such, and it is set equal to the snaplen. 01133 In my view, this is wrong (the meaning of the bufsize becames a bit strange). 01134 So, here bufsize is the whole size of the user buffer. 01135 In case the bufsize returned is too small, let's adjust it accordingly. 01136 */ 01137 if (fp->bufsize <= fp->snapshot) 01138 fp->bufsize+= sizeof (struct pcap_pkthdr); 01139 01140 // if the current socket buffer is smaller than the desired one 01141 if (sockbufsize < fp->bufsize) 01142 { 01143 // Loop until the buffer size is OK or the original socket buffer size is larger than this one 01144 while (1) 01145 { 01146 res= setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &(fp->bufsize), sizeof(fp->bufsize) ); 01147 01148 if (res == 0) 01149 break; 01150 01151 // If something goes wrong, half the buffer size (checking that it does not become smaller than 01152 // the current one) 01153 fp->bufsize/= 2; 01154 01155 if (sockbufsize >= fp->bufsize) 01156 { 01157 fp->bufsize= sockbufsize; 01158 break; 01159 } 01160 } 01161 } 01162 01163 // Let's allocate the packet; this is required in order to put the packet somewhere when 01164 // extracting data from the socket 01165 // Since buffering has already been done in the socket buffer, here we need just a buffer, 01166 // whose size is equal to the pcap header plus the snapshot length 01167 fp->bufsize= fp->snapshot + sizeof (struct pcap_pkthdr); 01168 01169 fp->buffer = (u_char *) malloc(fp->bufsize); 01170 if (fp->buffer == NULL) 01171 { 01172 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 01173 goto error; 01174 } 01175 01176 01177 // Checks if all the data has been read; if not, discard the data in excess 01178 if (nread != ntohl(header.plen)) 01179 { 01180 if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE) == 1) 01181 goto error; 01182 } 01183 return 0; 01184 01185 error: 01186 // When the connection has been established, we have to close it. So, at the 01187 // beginning of this function, if an error occur we return immediately with 01188 // a return NULL; when the connection is established, we have to come here 01189 // ('goto error;') in order to close everything properly. 01190 01191 // Checks if all the data has been read; if not, discard the data in excess 01192 if (nread != ntohl(header.plen)) 01193 sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE); 01194 01195 if ((sockdata) && (sockdata != -1)) // we can be here because sockdata said 'error' 01196 sock_close(sockdata, fakeerrbuf, PCAP_ERRBUF_SIZE); 01197 01198 if (!active) 01199 sock_close(fp->rmt_sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE); 01200 01201 if (fp) 01202 { 01203 pcap_close(fp); 01204 fp= NULL; 01205 } 01206 01207 return -1; 01208 } 01209 01210 01211 01212 01213 01237 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog) 01238 { 01239 struct rpcap_filter *filter; 01240 struct rpcap_filterbpf_insn *insn; 01241 struct bpf_insn *bf_insn; 01242 unsigned int i; 01243 01244 filter= (struct rpcap_filter *) sendbuf; 01245 01246 if ( sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx, 01247 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01248 return -1; 01249 01250 filter->filtertype= htons(RPCAP_UPDATEFILTER_BPF); 01251 filter->nitems= htonl( (int32) prog->bf_len); 01252 01253 if ( sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn), 01254 NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01255 return -1; 01256 01257 insn= (struct rpcap_filterbpf_insn *) (filter + 1); 01258 bf_insn= prog->bf_insns; 01259 01260 for (i= 0; i < prog->bf_len; i++) 01261 { 01262 insn->code= htons(bf_insn->code); 01263 insn->jf= bf_insn->jf; 01264 insn->jt= bf_insn->jt; 01265 insn->k= htonl(bf_insn->k); 01266 01267 insn++; 01268 bf_insn++; 01269 } 01270 return 0; 01271 } 01272 01273 01274 01275 01276 01296 int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog) 01297 { 01298 int retval; // general variable used to keep the return value of other functions 01299 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 01300 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01301 struct rpcap_header header; // To keep the reply message 01302 01303 01304 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 01305 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01306 return -1; 01307 01308 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0, 01309 sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn)); 01310 01311 if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog) ) 01312 return -1; 01313 01314 if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) ) 01315 return -1; 01316 01317 // Waits for the answer 01318 if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01319 return -1; 01320 01321 // Checks if the message is correct 01322 retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0); 01323 01324 if (retval != RPCAP_MSG_UPDATEFILTER_REPLY) // the message is not the one expected 01325 { 01326 switch (retval) 01327 { 01328 case -3: // Unrecoverable network error 01329 case -2: // The other endpoint sent a message that is not allowed here 01330 case -1: // The other endpoint has a version number that is not compatible with our 01331 // Do nothing; just exit from here; the error code is already into the errbuf 01332 return -1; 01333 01334 default: 01335 { 01336 SOCK_ASSERT("Internal error", 0); 01337 return -1; 01338 }; 01339 } 01340 } 01341 01342 if (ntohl(header.plen) != 0) // the message has an unexpected size 01343 { 01344 if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01345 return -1; 01346 } 01347 01348 return 0; 01349 } 01350 01351 01352 01353 01365 int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog) 01366 { 01367 if (!fp->rmt_capstarted) 01368 { 01369 // copy filter into the pcap_t structure 01370 if (install_bpf_program(fp, prog) == -1) 01371 return -1; 01372 return 0; 01373 } 01374 01375 // we have to update a filter during run-time 01376 if (pcap_updatefilter_remote(fp, prog) ) 01377 return -1; 01378 01379 return 0; 01380 } 01381 01382 01383 01398 int pcap_setsampling_remote(pcap_t *p) 01399 { 01400 int retval; // general variable used to keep the return value of other functions 01401 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 01402 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01403 struct rpcap_header header; // To keep the reply message 01404 struct rpcap_sampling *sampling_pars; // Structure that is needed to send sampling parameters to the remote host 01405 01406 // If no samping is requested, return 'ok' 01407 if (p->rmt_samp.method == PCAP_SAMP_NOSAMP) 01408 return 0; 01409 01410 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 01411 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) ) 01412 return -1; 01413 01414 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling) ); 01415 01416 // Fill the structure needed to open an adapter remotely 01417 sampling_pars= (struct rpcap_sampling *) &sendbuf[sendbufidx]; 01418 01419 if ( sock_bufferize(NULL, sizeof(struct rpcap_sampling), NULL, 01420 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) ) 01421 return -1; 01422 01423 memset(sampling_pars, 0, sizeof(struct rpcap_sampling) ); 01424 01425 sampling_pars->method= p->rmt_samp.method; 01426 sampling_pars->value= htonl(p->rmt_samp.value); 01427 01428 if ( sock_send(p->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE) ) 01429 return -1; 01430 01431 // Waits for the answer 01432 if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1) 01433 return -1; 01434 01435 // Checks if the message is correct 01436 retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0); 01437 01438 if (retval != RPCAP_MSG_SETSAMPLING_REPLY) // the message is not the one expected 01439 { 01440 switch (retval) 01441 { 01442 case -3: // Unrecoverable network error 01443 case -2: // The other endpoint sent a message that is not allowed here 01444 case -1: // The other endpoint has a version number that is not compatible with our 01445 case RPCAP_MSG_ERROR: 01446 // Do nothing; just exit from here; the error code is already into the errbuf 01447 return -1; 01448 01449 default: 01450 { 01451 SOCK_ASSERT("Internal error", 0); 01452 return -1; 01453 }; 01454 } 01455 } 01456 01457 if (ntohl(header.plen) != 0) // the message has an unexpected size 01458 { 01459 if (sock_discard(p->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1) 01460 return -1; 01461 } 01462 01463 return 0; 01464 01465 } 01466 01467 01468 01469 01470 01471 /********************************************************* 01472 * * 01473 * Miscellaneous functions * 01474 * * 01475 *********************************************************/ 01476 01477 01502 int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf) 01503 { 01504 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered 01505 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01506 uint16 length; 01507 01508 length= (uint16) strlen(error); 01509 01510 if (length > PCAP_ERRBUF_SIZE) 01511 length= PCAP_ERRBUF_SIZE; 01512 01513 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length); 01514 01515 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 01516 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) ) 01517 return -1; 01518 01519 if ( sock_bufferize(error, length, sendbuf, &sendbufidx, 01520 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) ) 01521 return -1; 01522 01523 if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) ) 01524 return -1; 01525 01526 return 0; 01527 } 01528 01529 01530 01549 int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf) 01550 { 01551 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data that has to be sent is buffered 01552 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01553 uint16 length; // length of the payload of this message 01554 struct rpcap_auth *rpauth; 01555 uint16 auth_type; 01556 struct rpcap_header header; 01557 int retval; // temp variable which stores functions return value 01558 01559 if (auth) 01560 { 01561 auth_type= auth->type; 01562 01563 switch (auth->type) 01564 { 01565 case RPCAP_RMTAUTH_NULL: 01566 length= sizeof (struct rpcap_auth); 01567 break; 01568 01569 case RPCAP_RMTAUTH_PWD: 01570 length= sizeof (struct rpcap_auth); 01571 if (auth->username) length+= strlen(auth->username); 01572 if (auth->password) length+= strlen(auth->password); 01573 break; 01574 01575 default: 01576 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized."); 01577 return -1; 01578 } 01579 } 01580 else 01581 { 01582 auth_type= RPCAP_RMTAUTH_NULL; 01583 length= sizeof (struct rpcap_auth); 01584 } 01585 01586 01587 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 01588 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) ) 01589 return -1; 01590 01591 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length); 01592 01593 rpauth= (struct rpcap_auth *) &sendbuf[sendbufidx]; 01594 01595 if ( sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL, 01596 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) ) 01597 return -1; 01598 01599 memset(rpauth, 0, sizeof (struct rpcap_auth) ); 01600 01601 rpauth->type= htons(auth_type); 01602 01603 if (auth_type == RPCAP_RMTAUTH_PWD) 01604 { 01605 01606 if (auth->username) 01607 rpauth->slen1= strlen(auth->username); 01608 else 01609 rpauth->slen1= 0; 01610 01611 if ( sock_bufferize(auth->username, rpauth->slen1, sendbuf, 01612 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) ) 01613 return -1; 01614 01615 if (auth->password) 01616 rpauth->slen2= strlen(auth->password); 01617 else 01618 rpauth->slen2= 0; 01619 01620 if ( sock_bufferize(auth->password, rpauth->slen2, sendbuf, 01621 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) ) 01622 return -1; 01623 01624 rpauth->slen1= htons (rpauth->slen1); 01625 rpauth->slen2= htons (rpauth->slen2); 01626 } 01627 01628 if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) ) 01629 return -1; 01630 01631 if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1) 01632 return -1; 01633 01634 retval= rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0); 01635 01636 if (retval != RPCAP_MSG_AUTH_REPLY) // the message is not the one expected 01637 { 01638 switch (retval) 01639 { 01640 case -3: // Unrecoverable network error 01641 case -2: // The other endpoint sent a message that is not allowed here 01642 case -1: // The other endpoint has a version number that is not compatible with our 01643 // Do nothing; just exit from here; the error code is already into the errbuf 01644 return -1; 01645 01646 case RPCAP_MSG_ERROR: 01647 { 01648 return -1; 01649 }; 01650 01651 default: 01652 { 01653 SOCK_ASSERT("Internal error", 0); 01654 return -1; 01655 }; 01656 } 01657 } 01658 01659 if (ntohl(header.plen) ) 01660 { 01661 if (sock_discard(sock, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE) ) 01662 return -1; 01663 } 01664 01665 return 0; 01666 } 01667 01668 01669 01691 void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length) 01692 { 01693 memset(header, 0, sizeof (struct rpcap_header) ); 01694 01695 header->ver= RPCAP_VERSION; 01696 header->type= type; 01697 header->value= htons(value); 01698 header->plen= htonl(length); 01699 } 01700 01701 01702 01746 int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...) 01747 { 01748 va_list ap; 01749 uint8 type; 01750 int32 len; 01751 01752 va_start(ap, first); 01753 01754 // Check if the present version of the protocol can handle this message 01755 if ( rpcap_checkver(sock, header, errbuf) ) 01756 { 01757 SOCK_ASSERT(errbuf, 1); 01758 01759 va_end(ap); 01760 return -1; 01761 } 01762 01763 type= first; 01764 01765 while ( type != 0 ) 01766 { 01767 // The message matches with one of the types listed 01768 // There is no need of conversions since both values are uint8 01769 01770 // Check if the other side reported an error. 01771 // If yes, it retrieves it and it returns it back to the caller 01772 if (header->type == RPCAP_MSG_ERROR) 01773 { 01774 len= ntohl(header->plen); 01775 01776 if (len >= PCAP_ERRBUF_SIZE) 01777 { 01778 if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE - 1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) 01779 return -3; 01780 01781 sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), fakeerrbuf, PCAP_ERRBUF_SIZE); 01782 01783 // Put '\0' at the end of the string 01784 errbuf[PCAP_ERRBUF_SIZE - 1]= 0; 01785 } 01786 else 01787 { 01788 if (sock_recv(sock, errbuf, len, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1) 01789 return -3; 01790 01791 // Put '\0' at the end of the string 01792 errbuf[len]= 0; 01793 } 01794 01795 01796 va_end(ap); 01797 return header->type; 01798 } 01799 01800 if (header->type == type) 01801 { 01802 va_end(ap); 01803 return header->type; 01804 } 01805 01806 // get next argument 01807 type= va_arg(ap, int); 01808 } 01809 01810 // we already have an error, so please discard this one 01811 sock_discard(sock, ntohl(header->plen), fakeerrbuf, PCAP_ERRBUF_SIZE); 01812 01813 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here."); 01814 SOCK_ASSERT(errbuf, 1); 01815 01816 va_end(ap); 01817 return -2; 01818 } 01819 01820 01821 01845 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf) 01846 { 01847 /* 01848 This is a sample function. 01849 01850 In the real world, you have to check at the type code, 01851 and decide accordingly. 01852 */ 01853 01854 if (header->ver != RPCAP_VERSION) 01855 { 01856 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded."); 01857 01858 // we already have an error, so please discard this one 01859 sock_discard(sock, ntohl(header->plen), fakeerrbuf, PCAP_ERRBUF_SIZE); 01860 return -1; 01861 } 01862 01863 return 0; 01864 } 01865 01866 01867 01888 int rpcap_remoteact_getsock(const char *host, char *errbuf) 01889 { 01890 struct activehosts *temp; // temp var needed to scan the host list chain 01891 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address 01892 int retval; 01893 01894 // retrieve the network address corresponding to 'host' 01895 addrinfo = NULL; 01896 memset(&hints, 0, sizeof (struct addrinfo) ); 01897 hints.ai_family = PF_UNSPEC; 01898 hints.ai_socktype= SOCK_STREAM; 01899 01900 retval = getaddrinfo(host, "0", &hints, &addrinfo); 01901 if (retval != 0) 01902 { 01903 snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval)); 01904 return -1; 01905 } 01906 01907 temp= activeHosts; 01908 01909 while (temp) 01910 { 01911 ai_next= addrinfo; 01912 while(ai_next) 01913 { 01914 if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0) 01915 return (temp->sockctrl ); 01916 01917 ai_next= ai_next->ai_next; 01918 } 01919 temp= temp->next; 01920 } 01921 01922 if (addrinfo) 01923 freeaddrinfo(addrinfo); 01924 01925 // The host you want to get the socket ID does not have an active connection 01926 return 0; 01927 } 01928 01929 01930 01931 01932
documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.