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 #include <pcap-int.h> // for the details of the pcap_t structure 00034 #include <pcap-remote.h> 00035 #include <sockutils.h> 00036 #include <errno.h> // for the errno variable 00037 #include <stdlib.h> // for malloc(), free(), ... 00038 #include <string.h> // for strstr, etc 00039 00040 00041 00042 /* 00043 \brief Global variable; needed to keep the message due to an error that we want to discard. 00044 00045 This can happen, for instance, because we already have an error message and we want to keep 00046 the first one. 00047 */ 00048 char fakeerrbuf[PCAP_ERRBUF_SIZE + 1]; 00049 00050 00052 extern struct activehosts *activeHosts; 00053 00054 00060 SOCKET sockmain; 00061 00062 00063 00064 00065 00066 00067 /**************************************************** 00068 * * 00069 * Function bodies * 00070 * * 00071 ****************************************************/ 00072 00073 00150 int pcap_findalldevs_ex(char *host, char *port, SOCKET sockctrl, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf) 00151 { 00152 unsigned int nread= 0; // number of bytes of the payload read from the socket 00153 struct addrinfo hints; // temp variable needed to resove hostnames into to socket representation 00154 struct addrinfo *addrinfo; // temp variable needed to resove hostnames into to socket representation 00155 struct rpcap_header header; // structure that keeps the general header of the rpcap protocol 00156 int i,j; // temp variables 00157 int naddr; // temp var needed to avoid problems with IPv6 addresses 00158 int retval; // store the return value of the functions 00159 int nif; // Number of interfaces listed 00160 int active= 0; // 'true' if we the other end-party is in active mode 00161 00162 00163 // We have to perform two controls here, because the user can call this function in two ways: 00164 // pcap_findalldevs_ex(NULL, ...) ==> address == NULL 00165 // pcap_findalldevs_ex("", ...) ==> address[0] == 0 00166 if ( (host == NULL) || (host[0] == 0) ) 00167 { 00168 // The user wants to retrieve adapters from a local host 00169 if (pcap_findalldevs(alldevs, errbuf) == -1) 00170 return -1; 00171 if ( (alldevs == NULL) || (*alldevs == NULL) ) 00172 { 00173 snprintf(errbuf, PCAP_ERRBUF_SIZE, 00174 "No interfaces found! Make sure libpcap/WinPcap is properly installed" 00175 " on the local machine."); 00176 return -1; 00177 } 00178 return 0; 00179 } 00180 00181 // Warning: this call can be the first one called by the user. 00182 // For this reason, we have to initialize the WinSock support. 00183 if (sock_init(errbuf) == -1) 00184 return -1; 00185 00186 // Check for active mode 00187 if ( (retval= rpcap_remoteact_getsock(host, errbuf)) == -1) 00188 return -1; 00189 00190 if (retval) 00191 { 00192 sockctrl= retval; 00193 active= 1; 00194 } 00195 else // we're not in active mode; let's opening a new control connection (if needed) 00196 { 00197 addrinfo= NULL; 00198 00199 memset(&hints, 0, sizeof(struct addrinfo) ); 00200 hints.ai_family = PF_UNSPEC; 00201 hints.ai_socktype = SOCK_STREAM; 00202 00203 if ( (port == NULL) || (port[0] == 0) ) 00204 { 00205 // the user chose not to specify the port 00206 if (sock_validaddr(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf) == -1) 00207 return -1; 00208 } 00209 else 00210 { 00211 if (sock_validaddr(host, port, &hints, &addrinfo, errbuf) == -1) 00212 return -1; 00213 } 00214 00215 if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf)) == -1) 00216 goto error; 00217 00218 // addrinfo is no longer used 00219 freeaddrinfo(addrinfo); 00220 addrinfo= NULL; 00221 00222 if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1) 00223 { 00224 // Control connection has to be closed only in case the remote machine is in passive mode 00225 if (!active) 00226 sock_close(sockctrl, fakeerrbuf); 00227 return -1; 00228 } 00229 } 00230 00231 // RPCAP findalldevs command 00232 rpcap_createhdr(&header, RPCAP_MSG_FINDALLIF_REQ, 0, 0); 00233 00234 if ( sock_send(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1 ) 00235 goto error; 00236 00237 if ( sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1) 00238 goto error; 00239 00240 // Checks if the message is correct 00241 retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_FINDALLIF_REPLY, RPCAP_MSG_ERROR, 0); 00242 00243 if (retval != RPCAP_MSG_FINDALLIF_REPLY) // the message is not the one expected 00244 { 00245 switch (retval) 00246 { 00247 case -3: // Unrecoverable network error 00248 case -2: // The other endpoint send a message that is not allowed here 00249 case -1: // The other endpoint has a version number that is not compatible with our 00250 break; 00251 00252 case RPCAP_MSG_ERROR: // The other endpoint reported an error 00253 break; 00254 00255 default: 00256 { 00257 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error"); 00258 break; 00259 }; 00260 } 00261 00262 if (!active) 00263 sock_close(sockctrl, fakeerrbuf); 00264 00265 return -1; 00266 } 00267 00268 // read the number of interfaces 00269 nif= ntohs(header.value); 00270 00271 // loop until all interfaces have been received 00272 for (i= 0; i < nif; i++) 00273 { 00274 struct rpcap_findalldevs_if findalldevs_if; 00275 pcap_if_t *dev; // Previous device into the pcap_if_t chain 00276 00277 // receive the findalldevs structure from remote hsot 00278 if ( (nread+= sock_recv(sockctrl, (char *) &findalldevs_if, 00279 sizeof(struct rpcap_findalldevs_if), errbuf) ) == -1) 00280 goto error; 00281 00282 findalldevs_if.namelen= ntohs(findalldevs_if.namelen); 00283 findalldevs_if.desclen= ntohs(findalldevs_if.desclen); 00284 findalldevs_if.naddr= ntohs(findalldevs_if.naddr); 00285 00286 // allocate the main structure 00287 if (i == 0) 00288 { 00289 (*alldevs)= (pcap_if_t *) malloc(sizeof(pcap_if_t) ); 00290 dev= (*alldevs); 00291 } 00292 else 00293 { 00294 dev->next= (pcap_if_t *) malloc(sizeof(pcap_if_t) ); 00295 dev= dev->next; 00296 } 00297 00298 // check that the malloc() didn't fail 00299 if (dev == NULL) 00300 { 00301 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00302 goto error; 00303 } 00304 dev->next= NULL; 00305 dev->addresses= NULL; 00306 00307 // allocate mem for name and description 00308 if (findalldevs_if.namelen) 00309 { 00310 dev->name= (char *) malloc(findalldevs_if.namelen + 1); 00311 if (dev->name == NULL) 00312 { 00313 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00314 goto error; 00315 } 00316 // Retrieve adapter name and description 00317 if ( (nread+= sock_recv(sockctrl, dev->name, findalldevs_if.namelen, errbuf) ) == -1) 00318 goto error; 00319 dev->name[findalldevs_if.namelen]= 0; 00320 } 00321 else 00322 dev->name= NULL; 00323 00324 if (findalldevs_if.desclen) 00325 { 00326 dev->description= (char *) malloc(findalldevs_if.desclen + 1); 00327 if (dev->description == NULL) 00328 { 00329 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00330 goto error; 00331 } 00332 // Retrieve adapter name and description 00333 if ( (nread+= sock_recv(sockctrl, dev->description, findalldevs_if.desclen, errbuf) ) == -1) 00334 goto error; 00335 dev->description[findalldevs_if.desclen]= 0; 00336 } 00337 else 00338 dev->description= NULL; 00339 00340 dev->flags= ntohl(findalldevs_if.flags); 00341 00342 naddr= 0; 00343 // loop until all addresses have been received 00344 for (j= 0; j < findalldevs_if.naddr; j++) 00345 { 00346 struct rpcap_findalldevs_ifaddr ifaddr; 00347 00348 // Retrieve the interface addresses 00349 if ( (nread+= sock_recv(sockctrl, (char *) &ifaddr, 00350 sizeof(struct rpcap_findalldevs_ifaddr), errbuf) ) == -1) 00351 goto error; 00352 00353 // WARNING libpcap bug: the address listing is available only for AF_INET 00354 if ( ntohs(ifaddr.addr.ss_family) == AF_INET) 00355 { 00356 struct pcap_addr *addr; 00357 00358 if (naddr == 0) 00359 { 00360 dev->addresses= (struct pcap_addr *) malloc ( sizeof(struct pcap_addr) ); 00361 addr= dev->addresses; 00362 } 00363 else 00364 { 00365 addr->next= (struct pcap_addr *) malloc ( sizeof(struct pcap_addr) ); 00366 addr= addr->next; 00367 } 00368 naddr++; 00369 00370 if (addr == NULL) 00371 { 00372 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 00373 goto error; 00374 } 00375 addr->next= NULL; 00376 00377 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.addr, 00378 (struct sockaddr_storage **) &addr->addr, errbuf) == -1) 00379 goto error; 00380 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.netmask, 00381 (struct sockaddr_storage **) &addr->netmask, errbuf) == -1) 00382 goto error; 00383 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.broadaddr, 00384 (struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1) 00385 goto error; 00386 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.dstaddr, 00387 (struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1) 00388 goto error; 00389 00390 if ( (addr->addr == NULL) && (addr->netmask == NULL) && 00391 (addr->broadaddr == NULL) && (addr->dstaddr == NULL) ) 00392 { 00393 free(addr); 00394 addr= NULL; 00395 if (naddr == 1) 00396 naddr= 0; // the first item of the list had NULL addresses 00397 } 00398 } 00399 } 00400 } 00401 00402 // Checks if all the data has been read; if not, discard the data in excess 00403 if (nread != ntohl(header.plen)) 00404 { 00405 if (sock_discard(sockctrl, ntohl(header.plen) - nread, errbuf) == 1) 00406 return -1; 00407 } 00408 00409 // Control connection has to be closed only in case the remote machine is in passive mode 00410 if (!active) 00411 { 00412 // DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources 00413 if ( sock_close(sockctrl, errbuf) ) 00414 return -1; 00415 } 00416 00417 // To avoid inconsistencies in the number of sock_init() 00418 sock_cleanup(); 00419 00420 return 0; 00421 00422 error: 00423 // In case there has been an error, I don't want to overwrite it with a new one 00424 // if the following call fails. I want to return always the original error. 00425 // 00426 // Take care: this connection can already be closed when we try to close it. 00427 // This happens because a previous error in the rpcapd, which requested to 00428 // closed the connection. In that case, we already recognized that into the 00429 // rpspck_isheaderok() and we already acknowledged the closing. 00430 // In that sense, this call is useless here (however it is needed in case 00431 // the client generates the error). 00432 00433 // Checks if all the data has been read; if not, discard the data in excess 00434 if (nread != ntohl(header.plen)) 00435 { 00436 if (sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1) 00437 return -1; 00438 } 00439 00440 // Control connection has to be closed only in case the remote machine is in passive mode 00441 if (!active) 00442 sock_close(sockctrl, fakeerrbuf); 00443 00444 // To avoid inconsistencies in the number of sock_init() 00445 sock_cleanup(); 00446 00447 return -1; 00448 } 00449 00450 00451 00452 00495 int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf) 00496 { 00497 switch (type) 00498 { 00499 case PCAP_SRC_FILE: 00500 { 00501 strncpy(source, PCAP_SRC_FILE_KEY, PCAP_BUF_SIZE); 00502 if ((name) && (*name) ) 00503 { 00504 strncat(source, name, PCAP_BUF_SIZE); 00505 return 0; 00506 } 00507 else 00508 { 00509 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name cannot be NULL."); 00510 return -1; 00511 } 00512 } 00513 case PCAP_SRC_IFREMOTE: 00514 { 00515 strncpy(source, PCAP_SRC_IF_KEY, PCAP_BUF_SIZE); 00516 if ((host) && (*host) ) 00517 { 00518 if ( (strcspn(host, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host) ) 00519 { 00520 // the host name does not contains alphabetic chars. So, it is a numeric address 00521 // In this case we have to include it between square brackets 00522 strncat(source, "[", PCAP_BUF_SIZE); 00523 strncat(source, host, PCAP_BUF_SIZE); 00524 strncat(source, "]", PCAP_BUF_SIZE); 00525 } 00526 else 00527 strncat(source, host, PCAP_BUF_SIZE); 00528 00529 if ((port) && (*port) ) 00530 { 00531 strncat(source, ":", PCAP_BUF_SIZE); 00532 strncat(source, port, PCAP_BUF_SIZE); 00533 } 00534 00535 strncat(source, "/", PCAP_BUF_SIZE); 00536 } 00537 else 00538 { 00539 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host name cannot be NULL."); 00540 return -1; 00541 } 00542 00543 if ((name) && (*name) ) 00544 { 00545 strncat(source, name, PCAP_BUF_SIZE); 00546 return 0; 00547 } 00548 else 00549 { 00550 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name cannot be NULL."); 00551 return -1; 00552 } 00553 } 00554 case PCAP_SRC_IFLOCAL: 00555 { 00556 strncpy(source, PCAP_SRC_IF_KEY, PCAP_BUF_SIZE); 00557 if ((name) && (*name) ) 00558 { 00559 strncat(source, name, PCAP_BUF_SIZE); 00560 return 0; 00561 } 00562 else 00563 { 00564 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name cannot be NULL."); 00565 return -1; 00566 } 00567 } 00568 default: 00569 { 00570 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface type is not valid."); 00571 return -1; 00572 } 00573 } 00574 } 00575 00576 00577 00578 00636 int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf) 00637 { 00638 char *ptr; 00639 int ntoken; 00640 char tmpname[PCAP_BUF_SIZE]; 00641 char tmphost[PCAP_BUF_SIZE]; 00642 char tmpport[PCAP_BUF_SIZE]; 00643 int tmptype; 00644 00645 // Initialization stuff 00646 tmpname[0]= 0; 00647 tmphost[0]= 0; 00648 tmpport[0]= 0; 00649 00650 if (host) 00651 *host= 0; 00652 if (port) 00653 *port= 0; 00654 if (name) 00655 *name= 0; 00656 00657 // Look for a 'rpcap://' identifier 00658 if ( (ptr= strstr(source, PCAP_SRC_IF_KEY)) != NULL) 00659 { 00660 ptr+= strlen(PCAP_SRC_IF_KEY); 00661 00662 if (strchr(ptr, '[')) // This is probably a numeric address 00663 { 00664 ntoken= sscanf(ptr, "[%[1234567890:.]]:%[^/]/%s", tmphost, tmpport, tmpname); 00665 00666 if (ntoken == 1) // probably the port is missing 00667 ntoken= sscanf(ptr, "[%[1234567890:.]]/%s", tmphost, tmpname); 00668 00669 tmptype= PCAP_SRC_IFREMOTE; 00670 } 00671 else 00672 { 00673 ntoken= sscanf(ptr, "%[^/:]:%[^/]/%s", tmphost, tmpport, tmpname); 00674 00675 if (ntoken == 1) 00676 { 00677 // This can be due to two reasons: 00678 // - we want a remote capture, but the network port is missing 00679 // - we want to do a local capture 00680 // To distinguish between the two, we look for the '/' char 00681 if (strchr(ptr, '/')) 00682 { 00683 // We're on a remote capture 00684 sscanf(ptr, "%[^/]/%s", tmphost, tmpname); 00685 tmptype= PCAP_SRC_IFREMOTE; 00686 } 00687 else 00688 { 00689 // We're on a local capture 00690 if (*ptr) 00691 strncpy(tmpname, ptr, PCAP_BUF_SIZE); 00692 00693 // Clean the host name, since it is a remote capture 00694 // NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line 00695 tmphost[0]= 0; 00696 00697 tmptype= PCAP_SRC_IFLOCAL; 00698 } 00699 } 00700 else 00701 tmptype= PCAP_SRC_IFREMOTE; 00702 } 00703 00704 if (tmpname[0]) 00705 { 00706 if (host) 00707 strcpy(host, tmphost); 00708 if (port) 00709 strcpy(port, tmpport); 00710 if (name) 00711 strcpy(name, tmpname); 00712 if (type) 00713 *type= tmptype; 00714 00715 return 0; 00716 } 00717 else 00718 { 00719 if (errbuf) 00720 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified."); 00721 00722 return -1; 00723 } 00724 } 00725 00726 // Look for a 'file://' identifier 00727 if ( (ptr= strstr(source, PCAP_SRC_FILE_KEY)) != NULL) 00728 { 00729 ptr+= strlen(PCAP_SRC_FILE_KEY); 00730 if (*ptr) 00731 { 00732 if (name) 00733 strncpy(name, ptr, PCAP_BUF_SIZE); 00734 00735 if (type) 00736 *type= PCAP_SRC_FILE; 00737 00738 return 0; 00739 } 00740 else 00741 { 00742 if (errbuf) 00743 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name has not been specified."); 00744 00745 return -1; 00746 } 00747 00748 } 00749 00750 // Backward compatibility; the user didn't use the 'rpcap://, file://' specifiers 00751 if ( (source) && (*source) ) 00752 { 00753 if (name) 00754 strncpy(name, source, PCAP_BUF_SIZE); 00755 00756 if (type) 00757 *type= PCAP_SRC_IFLOCAL; 00758 00759 return 0; 00760 } 00761 else 00762 { 00763 if (errbuf) 00764 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified."); 00765 00766 return -1; 00767 } 00768 }; 00769 00770 00771 00881 pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf) 00882 { 00883 char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE]; 00884 int type; 00885 pcap_t *fp; 00886 00887 if (strlen(source) > PCAP_BUF_SIZE) 00888 { 00889 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly."); 00890 return NULL; 00891 } 00892 00893 // determine the type of the source (NULL, file, local, remote) 00894 if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1) 00895 return NULL; 00896 00897 00898 switch (type) 00899 { 00900 case PCAP_SRC_FILE: 00901 fp = pcap_open_offline(name, NULL); 00902 break; 00903 00904 case PCAP_SRC_IFREMOTE: 00905 // Although we already have host, port and iface, we prefer TO PASS only 'pars' to the 00906 // pcap_open_remote() so that it has to call the pcap_parsesrcstr() again. 00907 // This is less optimized, but much clearer. 00908 fp= pcap_opensource_remote(source, auth, errbuf); 00909 00910 if (fp == NULL) 00911 return NULL; 00912 00913 fp->snapshot= snaplen; 00914 #ifdef WIN32 00915 fp->timeout= read_timeout; 00916 #else 00917 fp->md.timeout= read_timeout; 00918 #endif 00919 fp->rmt_flags= flags; 00920 break; 00921 00922 case PCAP_SRC_IFLOCAL: 00923 fp= pcap_open_live(name, snaplen, (flags & PCAP_OPENFLAG_PROMISCUOUS), read_timeout, errbuf); 00924 break; 00925 00926 default: 00927 strcpy(errbuf, "Source type not supported"); 00928 return NULL; 00929 } 00930 return fp; 00931 } 00932 00933 00934 00996 int pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf) 00997 { 00998 // socket-related variables 00999 struct addrinfo hints; // temporary struct to keep settings needed to open the new socket 01000 struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket 01001 struct sockaddr_storage from; // generic sockaddr_storage variable 01002 socklen_t fromlen; // keeps the length of the sockaddr_storage variable 01003 SOCKET sockctrl; // keeps the main socket identifier 01004 struct activehosts *temp, *prev; // temp var needed to scan he host list chain 01005 01006 *connectinghost= 0; // just in case 01007 01008 // Prepare to open a new server socket 01009 memset(&hints, 0, sizeof(struct addrinfo)); 01010 // WARNING Currently it supports only ONE socket family among ipv4 and IPv6 01011 hints.ai_family = AF_INET; // PF_UNSPEC to have both IPv4 and IPv6 server 01012 hints.ai_flags = AI_PASSIVE; // Ready to a bind() socket 01013 hints.ai_socktype = SOCK_STREAM; 01014 01015 // Warning: this call can be the first one called by the user. 01016 // For this reason, we have to initialize the WinSock support. 01017 if (sock_init(errbuf) == -1) 01018 return -1; 01019 01020 // Do the work 01021 if ((port == NULL) || (port[0] == 0) ) 01022 { 01023 if (sock_validaddr(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf) == -1) 01024 { 01025 SOCK_ASSERT(errbuf, 1); 01026 return -2; 01027 } 01028 } 01029 else 01030 { 01031 if (sock_validaddr(address, port, &hints, &addrinfo, errbuf) == -1) 01032 { 01033 SOCK_ASSERT(errbuf, 1); 01034 return -2; 01035 } 01036 } 01037 01038 01039 if ( (sockmain= sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf)) == -1) 01040 { 01041 SOCK_ASSERT(errbuf, 1); 01042 return -2; 01043 } 01044 01045 // Connection creation 01046 fromlen = sizeof(struct sockaddr_storage); 01047 01048 sockctrl= accept(sockmain, (struct sockaddr *) &from, &fromlen); 01049 01050 // We're not using sock_close, since we do not want to send a shutdown 01051 // (which is not allowed on a non-connected socket) 01052 closesocket(sockmain); 01053 sockmain= 0; 01054 01055 if (sockctrl == -1) 01056 { 01057 sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE); 01058 return -2; 01059 } 01060 01061 // Get the numeric for of the name of the connecting host 01062 if (getnameinfo( (struct sockaddr *) &from, fromlen, connectinghost, 01063 RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) ) 01064 { 01065 sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); 01066 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf); 01067 sock_close(sockctrl, fakeerrbuf); 01068 return -1; 01069 } 01070 01071 // checks if the connecting host is among the ones allowed 01072 if ( (hostlist) && (hostlist[0]) ) 01073 { 01074 if (sock_check_hostlist((char *) hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf) ) 01075 { 01076 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf); 01077 sock_close(sockctrl, fakeerrbuf); 01078 return -1; 01079 } 01080 } 01081 01082 // Send authentication to the remote machine 01083 if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1) 01084 { 01085 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf); 01086 sock_close(sockctrl, fakeerrbuf); 01087 return -3; 01088 } 01089 01090 // Checks that this host does not already have a cntrl connection in place 01091 01092 // Initialize pointers 01093 temp= activeHosts; 01094 prev= NULL; 01095 01096 while (temp) 01097 { 01098 // This host already has an active connection in place, so I don't have to update the host list 01099 if (sock_cmpaddr(&temp->host, &from) == 0) 01100 return sockctrl; 01101 01102 prev= temp; 01103 temp= temp->next; 01104 } 01105 01106 // The host does not exist in the list; so I have to update the list 01107 if (prev) 01108 { 01109 prev->next= (struct activehosts *) malloc (sizeof (struct activehosts) ); 01110 temp= prev->next; 01111 } 01112 else 01113 { 01114 activeHosts= (struct activehosts *) malloc (sizeof (struct activehosts) ); 01115 temp= activeHosts; 01116 } 01117 01118 if (temp == NULL) 01119 { 01120 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 01121 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf); 01122 sock_close(sockctrl, fakeerrbuf); 01123 return -1; 01124 } 01125 01126 memcpy(&temp->host, &from, fromlen); 01127 temp->sockctrl= sockctrl; 01128 temp->next= NULL; 01129 01130 return sockctrl; 01131 } 01132 01133 01134 01153 int pcap_remoteact_close(const char *host, char *errbuf) 01154 { 01155 struct activehosts *temp, *prev; // temp var needed to scan the host list chain 01156 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address 01157 int retval; 01158 01159 temp= activeHosts; 01160 prev= NULL; 01161 01162 // retrieve the network address corresponding to 'host' 01163 addrinfo = NULL; 01164 memset(&hints, 0, sizeof (struct addrinfo) ); 01165 hints.ai_family = PF_UNSPEC; 01166 hints.ai_socktype= SOCK_STREAM; 01167 01168 retval = getaddrinfo(host, "0", &hints, &addrinfo); 01169 if (retval != 0) 01170 { 01171 snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval)); 01172 return -1; 01173 } 01174 01175 while (temp) 01176 { 01177 ai_next= addrinfo; 01178 while(ai_next) 01179 { 01180 if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0) 01181 { 01182 struct rpcap_header header; 01183 01184 // Close this connection 01185 rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0); 01186 01187 // I don't check for errors, since I'm going to close everything 01188 sock_send(temp->sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf); 01189 01190 if (sock_close(temp->sockctrl, errbuf) ) 01191 { 01192 // To avoid inconsistencies in the number of sock_init() 01193 sock_cleanup(); 01194 01195 return -1; 01196 } 01197 01198 if (prev) 01199 prev->next= temp->next; 01200 else 01201 activeHosts= temp->next; 01202 01203 freeaddrinfo(addrinfo); 01204 01205 free(temp); 01206 01207 // To avoid inconsistencies in the number of sock_init() 01208 sock_cleanup(); 01209 01210 return 0; 01211 } 01212 01213 ai_next= ai_next->ai_next; 01214 } 01215 prev= temp; 01216 temp= temp->next; 01217 } 01218 01219 if (addrinfo) 01220 freeaddrinfo(addrinfo); 01221 01222 // To avoid inconsistencies in the number of sock_init() 01223 sock_cleanup(); 01224 01225 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known"); 01226 return -1; 01227 } 01228 01229 01249 void pcap_remoteact_cleanup() 01250 { 01251 // Very dirty, but it works 01252 if (sockmain) 01253 { 01254 closesocket(sockmain); 01255 01256 // To avoid inconsistencies in the number of sock_init() 01257 sock_cleanup(); 01258 } 01259 01260 } 01261 01262 01285 int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf) 01286 { 01287 struct activehosts *temp; // temp var needed to scan the host list chain 01288 int len; 01289 char hoststr[RPCAP_HOSTLIST_SIZE + 1]; 01290 01291 temp= activeHosts; 01292 01293 len= 0; 01294 *hostlist= 0; 01295 01296 while (temp) 01297 { 01298 // Get the numeric for of the name of the connecting host 01299 if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, 01300 RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) ) 01301 { 01302 sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); 01303 return -1; 01304 } 01305 01306 len= len + strlen(hoststr) + 1 /* the separator */; 01307 01308 if (len >= size) 01309 { 01310 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep " 01311 "the hostnames for all the active connections"); 01312 return -1; 01313 } 01314 01315 strcat(hostlist, hoststr); 01316 hostlist[len - 1]= sep; 01317 hostlist[len]= 0; 01318 01319 temp= temp->next; 01320 } 01321 01322 return 0; 01323 } 01324
documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.