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 00133 int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf) 00134 { 00135 // Warning: we support only AF_INET and AF_INET6 00136 if ( ntohs(sockaddrin->ss_family) == AF_INET) 00137 { 00138 struct sockaddr_in *sockaddr; 00139 00140 sockaddr= (struct sockaddr_in *) sockaddrin; 00141 sockaddr->sin_family= ntohs(sockaddr->sin_family); 00142 sockaddr->sin_port= ntohs(sockaddr->sin_port); 00143 00144 (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in) ); 00145 if ( (*sockaddrout) == NULL) 00146 { 00147 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00148 return -1; 00149 } 00150 memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in) ); 00151 return 0; 00152 } 00153 if ( ntohs(sockaddrin->ss_family) == AF_INET6) 00154 { 00155 struct sockaddr_in6 *sockaddr; 00156 00157 sockaddr= (struct sockaddr_in6 *) sockaddrin; 00158 sockaddr->sin6_family= ntohs(sockaddr->sin6_family); 00159 sockaddr->sin6_port= ntohs(sockaddr->sin6_port); 00160 sockaddr->sin6_flowinfo= ntohl(sockaddr->sin6_flowinfo); 00161 sockaddr->sin6_scope_id= ntohl(sockaddr->sin6_scope_id); 00162 00163 (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in6) ); 00164 if ( (*sockaddrout) == NULL) 00165 { 00166 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00167 return -1; 00168 } 00169 memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in6) ); 00170 return 0; 00171 } 00172 00173 // It is neither AF_INET nor AF_INET6 00174 *sockaddrout= NULL; 00175 return 0; 00176 } 00177 00178 00179 00203 int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data) 00204 { 00205 int cc; 00206 register u_char *ep, *bp; 00207 00208 cc= p->cc; 00209 bp= p->bp; 00210 00211 ep = bp + cc; 00212 00213 if (bp < ep) 00214 { 00215 register int caplen, hdrlen; 00216 again: 00217 caplen = ((struct pcap_pkthdr *)bp)->caplen; 00218 hdrlen= sizeof(struct pcap_pkthdr); 00219 00220 /* 00221 * XXX A bpf_hdr matches a pcap_pkthdr. 00222 */ 00223 *pkt_header = (struct pcap_pkthdr *) bp; 00224 *pkt_data = bp + hdrlen; 00225 bp += BPF_WORDALIGN(caplen + hdrlen); 00226 00227 p->bp = bp; 00228 p->cc = ep - bp; 00229 return (1); 00230 } 00231 else 00232 { 00233 p->cc = 0; 00234 // If there are no packets, the read thread must be suspended 00235 // another horrible difference... 00236 #ifdef linux 00237 pthread_suspend(p->md.timeout); 00238 #endif 00239 #ifdef WIN32 00240 pthread_suspend(p->timeout); 00241 #endif 00242 // check if now if have data; otherwise returns 00243 cc= p->cc; 00244 bp= p->bp; 00245 00246 ep = bp + cc; 00247 00248 if (bp < ep) 00249 goto again; 00250 00251 return (0); 00252 } 00253 } 00254 00255 00270 int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 00271 { 00272 struct pcap_pkthdr *pkt_header; 00273 u_char *pkt_data; 00274 int n = 0; 00275 00276 while ( (++n <= cnt) || (cnt < 0) ) 00277 { 00278 if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) ) 00279 (*callback)(user, pkt_header, pkt_data); 00280 else 00281 return n; 00282 } 00283 return n; 00284 } 00285 00286 00300 void pcap_close_remote(pcap_t *fp) 00301 { 00302 struct rpcap_header header; // header of the RPCAP packet 00303 struct activehosts *temp; // temp var needed to scan the host list chain, to detect if we're in active mode 00304 int active= 0; // active mode or not? 00305 00306 // detect if we're in active mode 00307 temp= activeHosts; 00308 while (temp) 00309 { 00310 if (temp->sockctrl == fp->rmt_sockctrl) 00311 { 00312 active= 1; 00313 break; 00314 } 00315 temp= temp->next; 00316 } 00317 00318 if (!active) 00319 { 00320 rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0); 00321 00322 // I don't check for errors, since I'm going to close everything 00323 sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fakeerrbuf); 00324 } 00325 else 00326 { 00327 rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REQ, 0, 0); 00328 00329 // I don't check for errors, since I'm going to close everything 00330 sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fakeerrbuf); 00331 00332 // wait for the answer 00333 // Don't check what we got, since the present libpcap does not uses this pcap_t anymore 00334 sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), fakeerrbuf); 00335 00336 if ( ntohl(header.plen) != 0) 00337 sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fakeerrbuf); 00338 } 00339 00340 00341 if (fp->rmt_threaddata) 00342 { 00343 pthread_cancel(fp->rmt_threaddata); 00344 fp->rmt_threaddata= 0; 00345 } 00346 00347 if (fp->rmt_sockdata) 00348 { 00349 sock_close(fp->rmt_sockdata, fakeerrbuf); 00350 fp->rmt_sockdata= 0; 00351 } 00352 00353 if ( (!active) && (fp->rmt_sockctrl) ) 00354 sock_close(fp->rmt_sockctrl, fakeerrbuf); 00355 00356 fp->rmt_sockctrl= 0; 00357 00358 // To avoid inconsistencies in the number of sock_init() 00359 sock_cleanup(); 00360 } 00361 00362 00363 00373 int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps) 00374 { 00375 struct pcap_stat *retval; 00376 00377 retval= rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD); 00378 00379 if (retval) 00380 return 0; 00381 else 00382 return -1; 00383 } 00384 00385 00386 00396 struct pcap_stat *pcap_stats_ex_remote(pcap_t *p) 00397 { 00398 // '0' (third param) means 'standard pcap_stats()' 00399 return (rpcap_stats_remote(p, &(p->md.stat), PCAP_STATS_EX)); 00400 } 00401 00402 00403 00434 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode) 00435 { 00436 struct rpcap_header header; // header of the RPCAP packet 00437 struct rpcap_stats netstats; // statistics sent on the network 00438 unsigned int nread= 0; // number of bytes of the payload read from the socket 00439 int retval; // temp variable which stores functions return value 00440 00441 rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0); 00442 00443 // Send the PCAP_STATS command 00444 if (sock_send(p->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), p->errbuf) ) 00445 goto error; 00446 00447 // Receive the RPCAP stats reply message 00448 if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), p->errbuf) == -1) 00449 goto error; 00450 00451 // Checks if the message is correct 00452 retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0); 00453 00454 if (retval != RPCAP_MSG_STATS_REPLY) // the message is not the one expected 00455 { 00456 switch (retval) 00457 { 00458 case -3: // Unrecoverable network error 00459 case -2: // The other endpoint send a message that is not allowed here 00460 case -1: // The other endpoint has a version number that is not compatible with our 00461 goto error; 00462 00463 case RPCAP_MSG_ERROR: // The other endpoint reported an error 00464 // Update nread, since the rpcap_checkmsg() already purged the buffer 00465 nread = ntohl(header.plen); 00466 00467 // Do nothing; just exit; the error code is already into the errbuf 00468 goto error; 00469 00470 default: 00471 { 00472 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 00473 goto error; 00474 }; 00475 } 00476 } 00477 00478 if ( (nread= sock_recv(p->rmt_sockctrl, (char *) &netstats, sizeof(struct rpcap_stats), p->errbuf)) == -1) 00479 goto error; 00480 00481 if (mode == PCAP_STATS_STANDARD) 00482 { 00483 ps->ps_drop= ntohl(netstats.krnldrop); 00484 ps->ps_ifdrop= ntohl(netstats.ifdrop); 00485 ps->ps_recv= ntohl(netstats.ifrecv); 00486 } 00487 else 00488 { 00489 ps->ps_capt= p->md.TotCapt; 00490 ps->ps_drop= ntohl(netstats.krnldrop); 00491 ps->ps_ifdrop= ntohl(netstats.ifdrop); 00492 ps->ps_netdrop= p->md.TotNetDrops; 00493 ps->ps_recv= ntohl(netstats.ifrecv); 00494 ps->ps_sent= ntohl(netstats.svrcapt); 00495 } 00496 00497 // Checks if all the data has been read; if not, discard the data in excess 00498 if (nread != ntohl(header.plen)) 00499 { 00500 if (sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1) 00501 goto error; 00502 } 00503 00504 return ps; 00505 00506 error: 00507 if (nread != ntohl(header.plen)) 00508 sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf); 00509 00510 return NULL; 00511 } 00512 00513 00514 00515 00554 pcap_t *pcap_opensource_remote(const char *source, struct pcap_rmtauth *auth, char *errbuf) 00555 { 00556 char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE]; 00557 00558 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 00559 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00560 pthread_t threaddata= 0; // handle to the receiving thread 00561 struct pcap *fp= NULL; // pcap_t main variable 00562 unsigned int nread= 0; // number of bytes of the payload read from the socket 00563 int retval; // store the return value of the functions 00564 int active= 0; // '1' if we're in active mode 00565 00566 // socket-related variables 00567 struct addrinfo hints; // temp, needed to open a socket connection 00568 struct addrinfo *addrinfo; // temp, needed to open a socket connection 00569 SOCKET sockctrl= 0; // socket descriptor of the control connection 00570 00571 // RPCAP-related variables 00572 struct rpcap_header header; // header of the RPCAP packet 00573 struct rpcap_openreply openreply; // open reply message 00574 00575 00576 // determine the type of the source (NULL, file, local, remote) 00577 // You must have a valid source string even if we're in active mode, because otherwise 00578 // the call to the following funciton will fail. 00579 if (pcap_parsesrcstr(source, &retval, host, ctrlport, iface, errbuf) == -1) 00580 return NULL; 00581 00582 if ( retval != PCAP_SRC_IFREMOTE) 00583 { 00584 snprintf(errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces"); 00585 return NULL; 00586 } 00587 00588 addrinfo= NULL; 00589 00590 // Warning: this call can be the first one called by the user. 00591 // For this reason, we have to initialize the WinSock support. 00592 if (sock_init(errbuf) == -1) 00593 return NULL; 00594 00595 retval= rpcap_remoteact_getsock(host, errbuf); 00596 00597 if (retval == -1) 00598 return NULL; 00599 00600 // The capturing machine is in active mode 00601 if (retval) 00602 { 00603 sockctrl= retval; 00604 active= 1; 00605 } 00606 else 00607 { 00608 memset(&hints, 0, sizeof(struct addrinfo) ); 00609 hints.ai_family = PF_UNSPEC; 00610 hints.ai_socktype = SOCK_STREAM; 00611 00612 if ( (ctrlport == NULL) || (ctrlport[0] == 0) ) 00613 { 00614 // the user chose not to specify the port 00615 if (sock_validaddr(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf) == -1) 00616 return NULL; 00617 } 00618 else 00619 { 00620 // the user chose not to specify the port 00621 if (sock_validaddr(host, ctrlport, &hints, &addrinfo, errbuf) == -1) 00622 return NULL; 00623 } 00624 00625 if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf)) == -1) 00626 goto error; 00627 00628 freeaddrinfo(addrinfo); 00629 addrinfo= NULL; 00630 00631 if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1) 00632 goto error; 00633 } 00634 00635 00636 // Now it's time to start playing with the RPCAP protocol 00637 // RPCAP open command: create the request message 00638 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) ) 00639 goto error; 00640 00641 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, strlen(iface) ); 00642 00643 if ( sock_bufferize(iface, strlen(iface), sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) ) 00644 goto error; 00645 00646 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf) ) 00647 goto error; 00648 00649 // Receive the RPCAP open reply message 00650 if (sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1) 00651 goto error; 00652 00653 // Checks if the message is correct 00654 retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0); 00655 00656 if (retval != RPCAP_MSG_OPEN_REPLY) // the message is not the one expected 00657 { 00658 switch (retval) 00659 { 00660 case -3: // Unrecoverable network error 00661 case -2: // The other endpoint send a message that is not allowed here 00662 case -1: // The other endpoint has a version number that is not compatible with our 00663 goto error; 00664 00665 case RPCAP_MSG_ERROR: // The other endpoint reported an error 00666 // Update nread, since the rpcap_checkmsg() already purged the buffer 00667 nread = ntohl(header.plen); 00668 // Do nothing; just exit; the error code is already into the errbuf 00669 goto error; 00670 00671 default: 00672 { 00673 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 00674 goto error; 00675 }; 00676 } 00677 } 00678 00679 00680 if ( (nread+= sock_recv(sockctrl, (char *) &openreply, sizeof(struct rpcap_openreply), errbuf)) == -1) 00681 goto error; 00682 00683 // Allocates a pcap_t struct for this end of the connection 00684 fp = (pcap_t *) malloc( sizeof(pcap_t) ); 00685 if (fp == NULL) 00686 { 00687 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00688 goto error; 00689 } 00690 00691 memset(fp, 0, sizeof(pcap_t)); 00692 00693 // Set proper fields into the pcap_t struct 00694 fp->linktype= ntohl(openreply.linktype); 00695 fp->tzoff= ntohl(openreply.tzoff); 00696 fp->rmt_sockctrl= sockctrl; 00697 fp->rmt_clientside= 1; 00698 00699 00700 // Checks if all the data has been read; if not, discard the data in excess 00701 if (nread != ntohl(header.plen)) 00702 { 00703 if (sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1) 00704 goto error; 00705 } 00706 return fp; 00707 00708 error: 00709 // When the connection has been established, we have to close it. So, at the 00710 // beginning of this function, if an error occur we return immediately with 00711 // a return NULL; when the connection is established, we have to come here 00712 // ('goto error;') in order to close everything properly. 00713 00714 // Checks if all the data has been read; if not, discard the data in excess 00715 if (nread != ntohl(header.plen)) 00716 sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf); 00717 00718 if (addrinfo) 00719 freeaddrinfo(addrinfo); 00720 00721 if (!active) 00722 sock_close(sockctrl, fakeerrbuf); 00723 00724 if (fp) 00725 { 00726 pcap_close(fp); 00727 fp= NULL; 00728 } 00729 00730 return NULL; 00731 } 00732 00733 00734 00735 00736 00737 00738 00761 int pcap_startcapture_remote(pcap_t *fp) 00762 { 00763 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 00764 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00765 char portdata[PCAP_BUF_SIZE]; // temp variable needed to keep the network port for the the data connection 00766 pthread_t threaddata= 0; // handle to the receiving thread 00767 unsigned int nread= 0; // number of bytes of the payload read from the socket 00768 int retval; // store the return value of the functions 00769 int active= 0; // '1' if we're in active mode 00770 struct activehosts *temp; // temp var needed to scan the host list chain, to detect if we're in active mode 00771 char host[INET6_ADDRSTRLEN + 1]; // numeric name of the other host 00772 00773 // socket-related variables 00774 struct addrinfo hints; // temp, needed to open a socket connection 00775 struct addrinfo *addrinfo; // temp, needed to open a socket connection 00776 SOCKET sockdata= 0; // socket descriptor of the data connection 00777 struct sockaddr_storage saddr; // temp, needed to retrieve the network data port chosen on the local machine 00778 socklen_t saddrlen; // temp, needed to retrieve the network data port chosen on the local machine 00779 int ai_family; // temp, keeps the address family used by the control connection 00780 00781 // RPCAP-related variables 00782 struct rpcap_header header; // header of the RPCAP packet 00783 struct rpcap_startcapreq *startcapreq; // start capture request message 00784 struct rpcap_startcapreply startcapreply; // start capture reply message 00785 00786 00787 // detect if we're in active mode 00788 temp= activeHosts; 00789 while (temp) 00790 { 00791 if (temp->sockctrl == fp->rmt_sockctrl) 00792 { 00793 active= 1; 00794 break; 00795 } 00796 temp= temp->next; 00797 } 00798 00799 addrinfo= NULL; 00800 00801 // Gets the complete sockaddr structure used in the ctrl connection 00802 // This is needed to get the address family of the control socket 00803 // Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct, 00804 // since the ctrl socket can already be open in case of active mode; 00805 // so I would have to call getpeername() anyway 00806 saddrlen = sizeof(struct sockaddr_storage); 00807 if (getpeername(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1) 00808 { 00809 sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00810 goto error; 00811 } 00812 ai_family= ((struct sockaddr_storage *) &saddr)->ss_family; 00813 00814 // Get the numeric address of the remote host we are connected to 00815 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, host, 00816 sizeof(host), NULL, 0, NI_NUMERICHOST) ) 00817 { 00818 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00819 goto error; 00820 } 00821 00822 /* 00823 Data connection is opened by the server toward the client if: 00824 - we're using TCP, and the user wants us to be in active mode 00825 - we're using UDP 00826 */ 00827 if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ) 00828 { 00829 // We have to create a new socket to receive packets 00830 // We have to do that immediately, since we have to tell the other 00831 // end which network port we picked up 00832 memset(&hints, 0, sizeof(struct addrinfo) ); 00833 // TEMP addrinfo is NULL in case of active 00834 hints.ai_family = ai_family; // Use the same address family of the control socket 00835 hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ? SOCK_DGRAM : SOCK_STREAM; 00836 hints.ai_flags = AI_PASSIVE; // Data connection is opened by the server toward the client 00837 00838 // Let's the server pick up a free network port for us 00839 if (sock_validaddr(NULL, "0", &hints, &addrinfo, fp->errbuf) == -1) 00840 goto error; 00841 00842 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, fp->errbuf)) == -1) 00843 goto error; 00844 00845 // addrinfo is no longer used 00846 freeaddrinfo(addrinfo); 00847 addrinfo= NULL; 00848 00849 // get the complete sockaddr structure used in the data connection 00850 saddrlen = sizeof(struct sockaddr_storage); 00851 if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1) 00852 { 00853 sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00854 goto error; 00855 } 00856 00857 // Get the local port the system picked up 00858 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 00859 0, portdata, sizeof(portdata), NI_NUMERICSERV) ) 00860 { 00861 sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 00862 goto error; 00863 } 00864 } 00865 00866 // Now it's time to start playing with the RPCAP protocol 00867 // RPCAP start ca[ture command: create the request message 00868 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) ) 00869 goto error; 00870 00871 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0, 00872 sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn) ); 00873 00874 // Fill the structure needed to open an adapter remotely 00875 startcapreq= (struct rpcap_startcapreq *) &sendbuf[sendbufidx]; 00876 00877 if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) ) 00878 goto error; 00879 00880 memset(startcapreq, 0, sizeof(struct rpcap_startcapreq) ); 00881 00882 // By default, apply half the timeout on one side, half of the other 00883 #ifdef linux 00884 fp->md.timeout= fp->md.timeout/2; 00885 startcapreq->read_timeout= htonl(fp->md.timeout); 00886 #endif 00887 #ifdef WIN32 00888 fp->timeout= fp->timeout/2; 00889 startcapreq->read_timeout= htonl(fp->timeout); 00890 #endif 00891 00892 // portdata on the openreq is meaningful only if we're in active mode 00893 if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ) 00894 { 00895 sscanf(portdata, "%d", &(startcapreq->portdata)); 00896 startcapreq->portdata= htons(startcapreq->portdata); 00897 } 00898 00899 startcapreq->snaplen= htonl(fp->snapshot); 00900 startcapreq->flags= 0; 00901 if (fp->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS) 00902 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_PROMISC; 00903 if (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) 00904 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_DGRAM; 00905 if (active) 00906 startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN; 00907 00908 startcapreq->flags= htons(startcapreq->flags); 00909 00910 // Pack the capture filter 00911 if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode) ) 00912 goto error; 00913 00914 if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf) ) 00915 goto error; 00916 00917 00918 // Receive the RPCAP start capture reply message 00919 if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), fp->errbuf) == -1) 00920 goto error; 00921 00922 // Checks if the message is correct 00923 retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0); 00924 00925 if (retval != RPCAP_MSG_STARTCAP_REPLY) // the message is not the one expected 00926 { 00927 switch (retval) 00928 { 00929 case -3: // Unrecoverable network error 00930 case -2: // The other endpoint send a message that is not allowed here 00931 case -1: // The other endpoint has a version number that is not compatible with our 00932 goto error; 00933 00934 case RPCAP_MSG_ERROR: // The other endpoint reported an error 00935 // Update nread, since the rpcap_checkmsg() already purged the buffer 00936 nread = ntohl(header.plen); 00937 // Do nothing; just exit; the error code is already into the errbuf 00938 goto error; 00939 00940 default: 00941 { 00942 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 00943 goto error; 00944 }; 00945 } 00946 } 00947 00948 00949 if ( (nread+= sock_recv(fp->rmt_sockctrl, (char *) &startcapreply, sizeof(struct rpcap_startcapreply), fp->errbuf)) == -1) 00950 goto error; 00951 00952 // Data connection is opened by the client toward the server 00953 // This happens because (a) we're not in active mode, and (b) we're not using UDP 00954 // So, let's start the connection 00955 if ( (!active) && !(fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ) 00956 { 00957 memset(&hints, 0, sizeof(struct addrinfo) ); 00958 hints.ai_family = ai_family; // Use the same address family of the control socket 00959 hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ? SOCK_DGRAM : SOCK_STREAM; 00960 00961 sprintf(portdata, "%d", ntohs(startcapreply.portdata) ); 00962 00963 // Let's the server pick up a free network port for us 00964 if (sock_validaddr(host, portdata, &hints, &addrinfo, fp->errbuf) == -1) 00965 goto error; 00966 00967 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf)) == -1) 00968 goto error; 00969 00970 // addrinfo is no longer used 00971 freeaddrinfo(addrinfo); 00972 addrinfo= NULL; 00973 } 00974 00975 00976 // Allocates WinPcap/libpcap user buffer 00977 // It has the same size of the one used on the other side of the connection 00978 fp->bufsize= ntohl(startcapreply.bufsize); 00979 00980 /* 00981 Warning: on some kernels (e.g. linux), the size of the user buffer does not take 00982 into account the pcap_header and such, and it is set equal to the snaplen. 00983 In our view, this is wrong (the meaning of the bufsize becames a bit strange). 00984 So, in our view, bufsize is the whole size of the user buffer. 00985 In case the bufsize returned is too small, adjust it accordingly. 00986 */ 00987 if (fp->bufsize <= fp->snapshot) 00988 fp->bufsize+= sizeof (struct pcap_pkthdr); 00989 00990 fp->buffer = (u_char *) malloc(fp->bufsize); 00991 if (fp->buffer == NULL) 00992 { 00993 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 00994 goto error; 00995 } 00996 00997 // The server is trying to connect to me; so it have to block on an accept() call 00998 // However, if the data connection is UDP, I don't have to call accept() 00999 if ( (active) && !(fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ) 01000 { 01001 SOCKET socktemp; // We need another socket, since we're going to accept() a connection 01002 01003 // Connection creation 01004 saddrlen = sizeof(struct sockaddr_storage); 01005 01006 socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen); 01007 01008 if (socktemp == -1) 01009 { 01010 sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE); 01011 goto error; 01012 } 01013 01014 // Now that I accepted the connection, the server socket is no longer needed 01015 sock_close(sockdata, fp->errbuf); 01016 sockdata= socktemp; 01017 } 01018 01019 fp->rmt_sockdata= sockdata; 01020 01021 // Now we have to create a new thread to receive packets 01022 if (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) 01023 { 01024 if ( pthread_create( &threaddata, NULL, (void *) &rpcap_thrdatamain_dgram, (void *) fp) ) 01025 { 01026 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread"); 01027 goto error; 01028 } 01029 } 01030 else 01031 { 01032 if ( pthread_create( &threaddata, NULL, (void *) &rpcap_thrdatamain_stream, (void *) fp) ) 01033 { 01034 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread"); 01035 goto error; 01036 } 01037 } 01038 01039 fp->rmt_threaddata= threaddata; 01040 01041 // Checks if all the data has been read; if not, discard the data in excess 01042 if (nread != ntohl(header.plen)) 01043 { 01044 if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1) 01045 goto error; 01046 } 01047 return 0; 01048 01049 error: 01050 // When the connection has been established, we have to close it. So, at the 01051 // beginning of this function, if an error occur we return immediately with 01052 // a return NULL; when the connection is established, we have to come here 01053 // ('goto error;') in order to close everything properly. 01054 01055 // Checks if all the data has been read; if not, discard the data in excess 01056 if (nread != ntohl(header.plen)) 01057 sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf); 01058 01059 if (threaddata) 01060 pthread_cancel(threaddata); 01061 01062 if ((sockdata) && (sockdata != -1)) // we can be here because sockdata said 'error' 01063 sock_close(sockdata, fakeerrbuf); 01064 01065 if (!active) 01066 sock_close(fp->rmt_sockctrl, fakeerrbuf); 01067 01068 if (fp) 01069 { 01070 pcap_close(fp); 01071 fp= NULL; 01072 } 01073 01074 return -1; 01075 } 01076 01077 01078 01079 01080 01104 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog) 01105 { 01106 struct rpcap_filter *filter; 01107 struct rpcap_filterbpf_insn *insn; 01108 struct bpf_insn *bf_insn; 01109 unsigned int i; 01110 01111 filter= (struct rpcap_filter *) sendbuf; 01112 01113 if ( sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) ) 01114 return -1; 01115 01116 filter->filtertype= htons(RPCAP_UPDATEFILTER_BPF); 01117 filter->nitems= htonl( (int32) prog->bf_len); 01118 01119 if ( sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn), NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) ) 01120 return -1; 01121 01122 insn= (struct rpcap_filterbpf_insn *) (filter + 1); 01123 bf_insn= prog->bf_insns; 01124 01125 for (i= 0; i < prog->bf_len; i++) 01126 { 01127 insn->code= htons(bf_insn->code); 01128 insn->jf= bf_insn->jf; 01129 insn->jt= bf_insn->jt; 01130 insn->k= htonl(bf_insn->k); 01131 01132 insn++; 01133 bf_insn++; 01134 } 01135 return 0; 01136 } 01137 01138 01139 01140 01141 01161 int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog) 01162 { 01163 int retval; // general variable used to keep the return value of other functions 01164 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered 01165 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01166 struct rpcap_header header; // To keep the reply message 01167 01168 01169 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) ) 01170 return -1; 01171 01172 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0, 01173 sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn)); 01174 01175 if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog) ) 01176 return -1; 01177 01178 if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf) ) 01179 return -1; 01180 01181 // Waits for the answer 01182 if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), fp->errbuf) == -1) 01183 return -1; 01184 01185 // Checks if the message is correct 01186 retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0); 01187 01188 if (retval != RPCAP_MSG_UPDATEFILTER_REPLY) // the message is not the one expected 01189 { 01190 switch (retval) 01191 { 01192 case -3: // Unrecoverable network error 01193 case -2: // The other endpoint sent a message that is not allowed here 01194 case -1: // The other endpoint has a version number that is not compatible with our 01195 // Do nothing; just exit from here; the error code is already into the errbuf 01196 return -1; 01197 01198 default: 01199 { 01200 SOCK_ASSERT("Internal error", 0); 01201 return -1; 01202 }; 01203 } 01204 } 01205 01206 if (ntohl(header.plen) != 0) // the message has an unexpected size 01207 { 01208 if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fp->errbuf) == -1) 01209 return -1; 01210 } 01211 01212 return 0; 01213 } 01214 01215 01216 01217 01228 int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog) 01229 { 01230 if (!fp->rmt_capstarted) 01231 { 01232 // copy filter into the pcap_t structure 01233 if (install_bpf_program(fp, prog) == -1) 01234 return -1; 01235 return 0; 01236 } 01237 01238 // we have to update a filter during run-time 01239 if (pcap_updatefilter_remote(fp, prog) ) 01240 return -1; 01241 01242 return 0; 01243 } 01244 01245 01246 01252 void pthread_suspend(int msec) 01253 { 01254 #ifdef WIN32 01255 Sleep(msec); 01256 #else 01257 struct timespec abstime; 01258 struct timeval now; 01259 01260 pthread_cond_t cond; 01261 pthread_mutex_t mutex; 01262 pthread_mutexattr_t attr; 01263 01264 pthread_mutexattr_init(&attr); 01265 pthread_mutex_init(&mutex, &attr); 01266 pthread_mutex_lock(&mutex); 01267 01268 pthread_cond_init(&cond, NULL); 01269 01270 gettimeofday(&now, NULL); 01271 01272 abstime.tv_sec = now.tv_sec + msec/1000; 01273 abstime.tv_nsec = now.tv_usec * 1000 + (msec%1000) * 1000 * 1000; 01274 01275 pthread_cond_timedwait(&cond, &mutex, &abstime); 01276 01277 pthread_mutex_destroy(&mutex); 01278 pthread_cond_destroy(&cond); 01279 #endif 01280 } 01281 01282 01283 01298 void rpcap_thrdatamain_stream(void *ptr) 01299 { 01300 char errbuf[PCAP_ERRBUF_SIZE + 1]; // error buffer 01301 pcap_t *fp; // pointer to a 'pcap' structure 01302 int retval; // general variable used to keep the return value of other functions 01303 struct rpcap_pkthdr net_pkt_header; // header of the packet 01304 struct pcap_pkthdr *pkt_header; // pointer to the buffer that contains the header of the current packet 01305 struct rpcap_header header; // general header according to the RPCAP format 01306 int cc; // number of bytes of data available into the user buffer 01307 unsigned int nread; // number of bytes (of payload) currently read from the network (referred to the current pkt) 01308 int pending= 0; // '1' if we've already read the pkt header, but there was not enough space to read the pkt data 01309 01310 // Structures needed for the select() call 01311 fd_set rfds; // set of socket descriptors we have to check 01312 struct timeval tv; // maximum time the select() can block waiting for data 01313 01314 fp= (pcap_t *) ptr; 01315 01316 *errbuf= 0; // Initialize errbuf 01317 01318 // Modify thread params so that it can be killed at any time 01319 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) ) 01320 goto error; 01321 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) ) 01322 goto error; 01323 01324 // Watch out sockdata to see if it has input 01325 FD_ZERO(&rfds); 01326 01327 // We do not have to block on the select() 01328 tv.tv_sec = 0; 01329 tv.tv_usec = 0; 01330 01331 /* 01332 The algorithm chosen to manage ths user buffer is quite simple, although 01333 not completely optimized. For instance, this is the same algorithm that 01334 is implemented when a packet is read from the kernel. 01335 01336 The producer (i.e. this thread) reads data from the network only when the 01337 user has already consumed all the data into the buffer. 01338 When data is read, it is copied at the beginning of the buffer. 01339 So, this is not a circular buffer. 01340 This job ends when (1) there is no data coming from the network, (2) 01341 the user buffer is completely full. 01342 01343 The consumer (i.e. the thread that calls pcap_next_ex) can read only when 01344 the producer finished its job. In other words, even if there is already 01345 data into the user buffer, the consumer cannot read it because the producer 01346 updates the status variables (fp->cc, fp->bp) only when it ends its job. 01347 This is the reason we do not need spinlocks. 01348 01349 This algorithm has two main drawbacks: 01350 - even if there is data into the user buffer, the application could not be 01351 able to see it 01352 - the producer reads the data from the network all at once, so the resulting 01353 behaviour is that all of a sudden the socket buffer is emptied and the TCP 01354 starts sending several acknowledges at the same time. This could lead to 01355 bursty traffic patterns. 01356 */ 01357 while (1) 01358 { 01359 if (fp->cc == 0) 01360 { 01361 u_char *bp= fp->buffer; 01362 cc= 0; 01363 01364 /* 01365 We will exit from this cycle while when: 01366 - the socket does not have data in it 01367 - the buffer does not have space left 01368 01369 In all cases, the pcap status variables will be updated 01370 before calling 'break'. 01371 */ 01372 while (1) 01373 { 01374 again: 01375 // 'fp->rmt_sockdata' has always to be set before calling the select(), 01376 // since it is cleared by the select() 01377 FD_SET(fp->rmt_sockdata, &rfds); 01378 01379 retval = select(fp->rmt_sockdata + 1, &rfds, NULL, NULL, &tv); 01380 if (retval == -1) 01381 { 01382 sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE); 01383 goto error; 01384 } 01385 01386 // There is no data waiting 01387 if (retval == 0) 01388 { 01389 // Update the pcap_t pointers so that the user application can read from the buffer 01390 fp->bp= fp->buffer; 01391 fp->cc= cc; 01392 01393 pthread_suspend(100); // Suspend 100 ms 01394 break; 01395 } 01396 01397 if (!pending) 01398 { 01399 // I'm going to read a new packet; so I reset the number of bytes (payload only) read 01400 nread= 0; 01401 01402 if (sock_recv(fp->rmt_sockdata, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1) 01403 goto error; 01404 01405 // Checks if the message is correct 01406 retval= rpcap_checkmsg(errbuf, fp->rmt_sockdata, &header, RPCAP_MSG_PACKET, 0); 01407 01408 if (retval != RPCAP_MSG_PACKET) // the message is not the one expected 01409 { 01410 switch (retval) 01411 { 01412 case -3: // Unrecoverable network error 01413 goto error; // Do nothing; just exit from here; the error code is already into the errbuf 01414 01415 case -2: // The other endpoint sent a message that is not allowed here 01416 case -1: // The other endpoint has a version number that is not compatible with our 01417 goto again; 01418 01419 default: 01420 { 01421 SOCK_ASSERT("Internal error", 1); 01422 goto error; 01423 }; 01424 } 01425 } 01426 01427 // Read the RPCAP packet header from the network 01428 if ( (nread= sock_recv(fp->rmt_sockdata, (char *) &net_pkt_header, sizeof(struct rpcap_pkthdr), errbuf)) == -1) 01429 goto error; 01430 } 01431 01432 if ( (cc + ntohl(net_pkt_header.caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) fp->bufsize) ) 01433 { 01434 pending= 0; 01435 01436 pkt_header= (struct pcap_pkthdr *) bp; 01437 pkt_header->caplen= ntohl(net_pkt_header.caplen); 01438 pkt_header->len= ntohl(net_pkt_header.len); 01439 pkt_header->ts.tv_sec= ntohl(net_pkt_header.timestamp_sec); 01440 pkt_header->ts.tv_usec= ntohl(net_pkt_header.timestamp_usec); 01441 01442 // I don't update the counter of the packets dropped by the network since we're using TCP; 01443 // therefore no packets are dropped. Just update the number of packets received correctly 01444 fp->md.TotCapt++; 01445 01446 // Copies the packet into the data buffer 01447 if ( (nread+= sock_recv(fp->rmt_sockdata, (char *) bp + sizeof(struct pcap_pkthdr), pkt_header->caplen, errbuf)) == -1) 01448 goto error; 01449 01450 bp += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr)); 01451 cc += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr)); 01452 01453 // Checks if all the data has been read; if not, discard the data in excess 01454 if (nread != ntohl(header.plen)) 01455 sock_discard(fp->rmt_sockdata, ntohl(header.plen) - nread, fakeerrbuf); 01456 01457 } 01458 else 01459 { 01460 pending= 1; 01461 01462 // Update the pcap_t pointers so that the user application can read from the buffer 01463 fp->bp= fp->buffer; 01464 fp->cc= cc; 01465 01466 break; 01467 } 01468 } // end while (1) 01469 } 01470 else 01471 { 01472 pthread_suspend(100); // Suspend 100 ms 01473 } 01474 01475 } // end main while(1) 01476 01477 error: 01478 SOCK_ASSERT("Exiting from the child data thread", 1); 01479 SOCK_ASSERT(errbuf, 1); 01480 01481 // Removes the descriptor s from set 01482 FD_CLR(fp->rmt_sockdata, &rfds); 01483 01484 closesocket(fp->rmt_sockdata); 01485 fp->rmt_sockdata= 0; 01486 fp->rmt_threaddata= 0; 01487 } 01488 01489 01490 01514 void rpcap_thrdatamain_dgram(void *ptr) 01515 { 01516 char errbuf[PCAP_ERRBUF_SIZE + 1]; // error buffer 01517 char netbuf[RPCAP_NETBUF_SIZE]; // size of the network buffer in which the packet is copied 01518 pcap_t *fp; // pointer to a 'pcap' structure 01519 int retval; // general variable used to keep the return value of other functions 01520 struct rpcap_header *header; // general header according to the RPCAP format 01521 struct rpcap_pkthdr *net_pkt_header;// header of the packet 01522 struct pcap_pkthdr *pkt_header; // pointer to the buffer that contains the header of the current packet 01523 int cc; // number of bytes of data available into the user buffer 01524 int pending= 0; // '1' if we've already read the pkt header, but there was not enough space to read the pkt data 01525 01526 // Structures needed for the select() call 01527 fd_set rfds; // set of socket descriptors we have to check 01528 struct timeval tv; // maximum time the select() can block waiting for data 01529 01530 01531 // See the rpcap_thrdatamain_stream() for any comment about the code 01532 fp= (pcap_t *) ptr; 01533 01534 *errbuf= 0; // Initialize errbuf 01535 01536 // Modify thread params so that it can be killed at any time 01537 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) ) 01538 goto error; 01539 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) ) 01540 goto error; 01541 01542 // Watch out sockdata to see if it has input 01543 FD_ZERO(&rfds); 01544 01545 // We do not have to block here 01546 tv.tv_sec = 0; 01547 tv.tv_usec = 0; 01548 01549 while (1) 01550 { 01551 if (fp->cc == 0) 01552 { 01553 u_char *bp= fp->buffer; 01554 cc= 0; 01555 01556 while (1) 01557 { 01558 again: 01559 FD_SET(fp->rmt_sockdata, &rfds); 01560 01561 retval = select(1, &rfds, NULL, NULL, &tv); 01562 if (retval == -1) 01563 { 01564 sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE); 01565 goto error; 01566 } 01567 01568 // There is no data waiting 01569 if (retval == 0) 01570 { 01571 // Update the pcap_t pointers so that the user application can read from the buffer 01572 fp->bp= fp->buffer; 01573 fp->cc= cc; 01574 01575 pthread_suspend(100); // Suspend 100 ms 01576 break; 01577 } 01578 01579 if (!pending) 01580 { 01581 // Read the entire message from the network 01582 if (sock_recv_dgram(fp->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, errbuf) == -1) 01583 goto error; 01584 header= (struct rpcap_header *) netbuf; 01585 01586 // Checks if the message is correct 01587 retval= rpcap_checkmsg(errbuf, fp->rmt_sockdata, (struct rpcap_header *) netbuf, RPCAP_MSG_PACKET, 0); 01588 01589 if (retval != RPCAP_MSG_PACKET) // the message is not the one expected 01590 { 01591 switch (retval) 01592 { 01593 case -3: // Unrecoverable network error 01594 goto error; // Do nothing; just exit from here; the error code is already into the errbuf 01595 01596 case -2: // The other endpoint sent a message that is not allowed here 01597 case -1: // The other endpoint has a version number that is not compatible with our 01598 goto again; 01599 01600 default: 01601 { 01602 SOCK_ASSERT("Internal error", 0); 01603 goto error; 01604 }; 01605 } 01606 } 01607 01608 // Set a pointer to the RPCAP packet header 01609 net_pkt_header= (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header)); 01610 } 01611 01612 if ( (cc + ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) fp->bufsize) ) 01613 { 01614 unsigned int npkt; 01615 pending= 0; 01616 01617 pkt_header= (struct pcap_pkthdr *) bp; 01618 pkt_header->caplen= ntohl(net_pkt_header->caplen); 01619 pkt_header->len= ntohl(net_pkt_header->len); 01620 pkt_header->ts.tv_sec= ntohl(net_pkt_header->timestamp_sec); 01621 pkt_header->ts.tv_usec= ntohl(net_pkt_header->timestamp_usec); 01622 01623 // Update the number of packets received correctly 01624 fp->md.TotCapt++; 01625 01626 // We're using UDP, so I need to update the counter of the packets dropped by the network 01627 npkt= ntohl(net_pkt_header->npkt); 01628 01629 if (fp->md.TotCapt != npkt) 01630 { 01631 fp->md.TotNetDrops+= (npkt - fp->md.TotCapt); 01632 fp->md.TotCapt= npkt; 01633 } 01634 01635 // Copies the packet into the data buffer 01636 memcpy( bp + sizeof(struct pcap_pkthdr), netbuf + sizeof(struct rpcap_header), pkt_header->caplen); 01637 01638 bp += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr)); 01639 cc += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr)); 01640 } 01641 else 01642 { 01643 pending= 1; 01644 01645 // Update the pcap_t pointers so that the user application can read from the buffer 01646 fp->bp= fp->buffer; 01647 fp->cc= cc; 01648 01649 break; 01650 } 01651 } // end while (1) 01652 } 01653 else 01654 { 01655 pthread_suspend(100); // Suspend 100 ms 01656 } 01657 } // end main while(1) 01658 01659 error: 01660 SOCK_ASSERT("Exiting from the child data thread", 1); 01661 SOCK_ASSERT(errbuf, 1); 01662 01663 // Removes the descriptor s from set 01664 FD_CLR(fp->rmt_sockdata, &rfds); 01665 01666 closesocket(fp->rmt_sockdata); 01667 fp->rmt_sockdata= 0; 01668 fp->rmt_threaddata= 0; 01669 } 01670 01671 01672 01673 01674 01675 01676 /********************************************************* 01677 * * 01678 * Miscellaneous functions * 01679 * * 01680 *********************************************************/ 01681 01682 01707 int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf) 01708 { 01709 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered 01710 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01711 uint16 length; 01712 01713 length= (uint16) strlen(error); 01714 01715 if (length > PCAP_ERRBUF_SIZE) 01716 length= PCAP_ERRBUF_SIZE; 01717 01718 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length); 01719 01720 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) ) 01721 return -1; 01722 01723 if ( sock_bufferize(error, length, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) ) 01724 return -1; 01725 01726 if ( sock_send(sock, sendbuf, sendbufidx, errbuf) ) 01727 return -1; 01728 01729 return 0; 01730 } 01731 01732 01733 01752 int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf) 01753 { 01754 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data that has to be sent is buffered 01755 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01756 uint16 length; // length of the payload of this message 01757 struct rpcap_auth *rpauth; 01758 uint16 auth_type; 01759 struct rpcap_header header; 01760 int retval; // temp variable which stores functions return value 01761 01762 if (auth) 01763 { 01764 auth_type= auth->type; 01765 01766 switch (auth->type) 01767 { 01768 case RPCAP_RMTAUTH_NULL: 01769 length= sizeof (struct rpcap_auth); 01770 break; 01771 01772 case RPCAP_RMTAUTH_PWD: 01773 length= sizeof (struct rpcap_auth); 01774 if (auth->username) length+= strlen(auth->username); 01775 if (auth->password) length+= strlen(auth->password); 01776 break; 01777 01778 default: 01779 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized."); 01780 return -1; 01781 } 01782 } 01783 else 01784 { 01785 auth_type= RPCAP_RMTAUTH_NULL; 01786 length= sizeof (struct rpcap_auth); 01787 } 01788 01789 01790 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) ) 01791 return -1; 01792 01793 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length); 01794 01795 rpauth= (struct rpcap_auth *) &sendbuf[sendbufidx]; 01796 01797 if ( sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) ) 01798 return -1; 01799 01800 memset(rpauth, 0, sizeof (struct rpcap_auth) ); 01801 01802 rpauth->type= htons(auth_type); 01803 01804 if (auth_type == RPCAP_RMTAUTH_PWD) 01805 { 01806 01807 if (auth->username) 01808 rpauth->slen1= strlen(auth->username); 01809 else 01810 rpauth->slen1= 0; 01811 01812 if ( sock_bufferize(auth->username, rpauth->slen1, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) ) 01813 return -1; 01814 01815 if (auth->password) 01816 rpauth->slen2= strlen(auth->password); 01817 else 01818 rpauth->slen2= 0; 01819 01820 if ( sock_bufferize(auth->password, rpauth->slen2, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) ) 01821 return -1; 01822 01823 rpauth->slen1= htons (rpauth->slen1); 01824 rpauth->slen2= htons (rpauth->slen2); 01825 } 01826 01827 if ( sock_send(sock, sendbuf, sendbufidx, errbuf) ) 01828 return -1; 01829 01830 if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1) 01831 return -1; 01832 01833 retval= rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0); 01834 01835 if (retval != RPCAP_MSG_AUTH_REPLY) // the message is not the one expected 01836 { 01837 switch (retval) 01838 { 01839 case -3: // Unrecoverable network error 01840 case -2: // The other endpoint sent a message that is not allowed here 01841 case -1: // The other endpoint has a version number that is not compatible with our 01842 // Do nothing; just exit from here; the error code is already into the errbuf 01843 return -1; 01844 01845 case RPCAP_MSG_ERROR: 01846 { 01847 return -1; 01848 }; 01849 01850 default: 01851 { 01852 SOCK_ASSERT("Internal error", 0); 01853 return -1; 01854 }; 01855 } 01856 } 01857 01858 if (ntohl(header.plen) ) 01859 { 01860 if (sock_discard(sock, ntohl(header.plen), errbuf) ) 01861 return -1; 01862 } 01863 01864 return 0; 01865 } 01866 01867 01868 01890 void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length) 01891 { 01892 memset(header, 0, sizeof (struct rpcap_header) ); 01893 01894 header->ver= RPCAP_VERSION; 01895 header->type= type; 01896 header->value= htons(value); 01897 header->plen= htonl(length); 01898 } 01899 01900 01901 01945 int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...) 01946 { 01947 va_list ap; 01948 uint8 type; 01949 int32 len; 01950 01951 va_start(ap, first); 01952 01953 // Check if the present version of the protocol can handle this message 01954 if ( rpcap_checkver(sock, header, errbuf) ) 01955 { 01956 SOCK_ASSERT(errbuf, 1); 01957 01958 va_end(ap); 01959 return -1; 01960 } 01961 01962 type= first; 01963 01964 while ( type != 0 ) 01965 { 01966 // The message matches with one of the types listed 01967 // There is no need of conversions since both values are uint8 01968 01969 // Check if the other side reported an error. 01970 // If yes, it retrieves it and it returns it back to the caller 01971 if (header->type == RPCAP_MSG_ERROR) 01972 { 01973 len= ntohl(header->plen); 01974 01975 if (len >= PCAP_ERRBUF_SIZE) 01976 { 01977 if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE -1, errbuf) ) 01978 return -3; 01979 sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), fakeerrbuf); 01980 01981 // Put '\0' at the end of the string 01982 errbuf[PCAP_ERRBUF_SIZE - 1]= 0; 01983 } 01984 else 01985 { 01986 if (sock_recv(sock, errbuf, len, errbuf) == -1) 01987 return -3; 01988 01989 // Put '\0' at the end of the string 01990 errbuf[len]= 0; 01991 } 01992 01993 01994 va_end(ap); 01995 return header->type; 01996 } 01997 01998 if (header->type == type) 01999 { 02000 va_end(ap); 02001 return header->type; 02002 } 02003 02004 // get next argument 02005 type= va_arg(ap, int); 02006 } 02007 02008 // we already have an error, so please discard this one 02009 sock_discard(sock, ntohl(header->plen), fakeerrbuf); 02010 02011 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here."); 02012 SOCK_ASSERT(errbuf, 1); 02013 02014 va_end(ap); 02015 return -2; 02016 } 02017 02018 02019 02043 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf) 02044 { 02045 /* 02046 This is a sample function. 02047 02048 In the real world, you have to check at the type code, 02049 and decide accordingly. 02050 */ 02051 02052 if (header->ver != RPCAP_VERSION) 02053 { 02054 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded."); 02055 02056 // we already have an error, so please discard this one 02057 sock_discard(sock, ntohl(header->plen), fakeerrbuf); 02058 return -1; 02059 } 02060 02061 return 0; 02062 } 02063 02064 02065 02086 int rpcap_remoteact_getsock(const char *host, char *errbuf) 02087 { 02088 struct activehosts *temp; // temp var needed to scan the host list chain 02089 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address 02090 int retval; 02091 02092 // retrieve the network address corresponding to 'host' 02093 addrinfo = NULL; 02094 memset(&hints, 0, sizeof (struct addrinfo) ); 02095 hints.ai_family = PF_UNSPEC; 02096 hints.ai_socktype= SOCK_STREAM; 02097 02098 retval = getaddrinfo(host, "0", &hints, &addrinfo); 02099 if (retval != 0) 02100 { 02101 snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval)); 02102 return -1; 02103 } 02104 02105 temp= activeHosts; 02106 02107 while (temp) 02108 { 02109 ai_next= addrinfo; 02110 while(ai_next) 02111 { 02112 if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0) 02113 return (temp->sockctrl ); 02114 02115 ai_next= ai_next->ai_next; 02116 } 02117 temp= temp->next; 02118 } 02119 02120 if (addrinfo) 02121 freeaddrinfo(addrinfo); 02122 02123 // The host you want to get the socket ID does not have an active connection 02124 return 0; 02125 } 02126 02127 02128 02129 02130
documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.