15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * libslirp glue 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 2004-2008 Fabrice Bellard 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * in the Software without restriction, including without limitation the rights 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * furnished to do so, subject to the following conditions: 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The above copyright notice and this permission notice shall be included in 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * all copies or substantial portions of the Software. 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE. 235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h" 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-char.h" 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "slirp.h" 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "proxy_common.h" 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/hw.h" 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "android/utils/debug.h" /* for dprint */ 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "android/utils/bufprint.h" 325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "android/android.h" 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "sockets.h" 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define D(...) VERBOSE_PRINT(slirp,__VA_ARGS__) 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define DN(...) do { if (VERBOSE_CHECK(slirp)) dprintn(__VA_ARGS__); } while (0) 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* host address */ 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint32_t our_addr_ip; 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* host dns address */ 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint32_t dns_addr[DNS_ADDR_MAX]; 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint dns_addr_count; 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* host loopback address */ 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint32_t loopback_addr_ip; 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* address for slirp virtual addresses */ 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint32_t special_addr_ip; 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* virtual address alias for host */ 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint32_t alias_addr_ip; 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const uint8_t special_ethaddr[6] = { 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 0x52, 0x54, 0x00, 0x12, 0x35, 0x00 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* ARP cache for the guest IP addresses (XXX: allow many entries) */ 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint8_t client_ethaddr[6]; 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ipaddr_t client_ip; 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 }; 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerconst char *slirp_special_ip = CTL_SPECIAL; 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_restrict; 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int do_slowtimo; 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint link_up; 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct timeval tt; 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerFILE *lfd; 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct ex_list *exec_list; 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* XXX: suppress those select globals */ 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerfd_set *global_readfds, *global_writefds, *global_xfds; 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerchar slirp_hostname[33]; 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_add_dns_server(const SockAddress* new_dns_addr) 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int dns_ip; 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_addr_count >= DNS_ADDR_MAX) 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dns_ip = sock_address_get_ip(new_dns_addr); 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_ip < 0) 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dns_addr[dns_addr_count++] = dns_ip; 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_get_system_dns_servers(void) 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FIXED_INFO *FixedInfo=NULL; 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ULONG BufLen; 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DWORD ret; 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner IP_ADDR_STRING *pIPAddr; 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_addr_count > 0) 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return dns_addr_count; 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner BufLen = sizeof(FIXED_INFO); 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) { 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (FixedInfo) { 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner GlobalFree(FixedInfo); 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FixedInfo = NULL; 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FixedInfo = GlobalAlloc(GPTR, BufLen); 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) { 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret ); 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (FixedInfo) { 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner GlobalFree(FixedInfo); 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FixedInfo = NULL; 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner D( "DNS Servers:"); 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pIPAddr = &(FixedInfo->DnsServerList); 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (pIPAddr && dns_addr_count < DNS_ADDR_MAX) { 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t ip; 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner D( " %s", pIPAddr->IpAddress.String ); 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (inet_strtoip(pIPAddr->IpAddress.String, &ip) == 0) { 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ip == loopback_addr_ip) 1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip = our_addr_ip; 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_addr_count < DNS_ADDR_MAX) 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dns_addr[dns_addr_count++] = ip; 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pIPAddr = pIPAddr->Next; 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (FixedInfo) { 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner GlobalFree(FixedInfo); 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FixedInfo = NULL; 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_addr_count <= 0) 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return dns_addr_count; 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_get_system_dns_servers(void) 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buff[512]; 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buff2[257]; 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FILE *f; 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_addr_count > 0) 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return dns_addr_count; 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_DARWIN 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* on Darwin /etc/resolv.conf is a symlink to /private/var/run/resolv.conf 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * in some siutations, the symlink can be destroyed and the system will not 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * re-create it. Darwin-aware applications will continue to run, but "legacy" 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Unix ones will not. 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner f = fopen("/private/var/run/resolv.conf", "r"); 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!f) 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner f = fopen("/etc/resolv.conf", "r"); /* desperate attempt to sanity */ 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner f = fopen("/etc/resolv.conf", "r"); 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!f) 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DN("emulator: IP address of your DNS(s): "); 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (fgets(buff, 512, f) != NULL) { 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t tmp_ip; 1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (inet_strtoip(buff2, &tmp_ip) < 0) 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tmp_ip == loopback_addr_ip) 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp_ip = our_addr_ip; 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_addr_count < DNS_ADDR_MAX) { 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dns_addr[dns_addr_count++] = tmp_ip; 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_addr_count > 1) 1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DN(", "); 1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DN("%s", inet_iptostr(tmp_ip)); 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DN("(more)"); 1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DN("\n"); 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fclose(f); 1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!dns_addr_count) 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return dns_addr_count; 2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_state_save(QEMUFile *f, void *opaque); 2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int slirp_state_load(QEMUFile *f, void *opaque, int version_id); 2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid slirp_init(int restricted, const char *special_ip) 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if DEBUG 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int slirp_logmask = 0; 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char slirp_logfile[512]; 2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char* env = getenv( "ANDROID_SLIRP_LOGMASK" ); 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (env != NULL) 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_logmask = atoi(env); 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (VERBOSE_CHECK(slirp)) 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_logmask = DEBUG_DEFAULT; 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char* p = slirp_logfile; 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char* end = p + sizeof(slirp_logfile); 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p = bufprint_temp_file( p, end, "slirp.log" ); 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (p >= end) { 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprint( "cannot create slirp log file in temporary directory" ); 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_logmask = 0; 2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_logmask) { 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprint( "sending slirp logs with mask %x to %s", slirp_logmask, slirp_logfile ); 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner debug_init( slirp_logfile, slirp_logmask ); 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner link_up = 1; 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_restrict = restricted; 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if_init(); 2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_init(); 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Initialise mbufs *after* setting the MTU */ 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_init(); 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* set default addresses */ 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner inet_strtoip("127.0.0.1", &loopback_addr_ip); 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dns_addr_count == 0) { 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_get_system_dns_servers() < 0) { 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dns_addr[0] = loopback_addr_ip; 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dns_addr_count = 1; 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf (stderr, "Warning: No DNS servers found\n"); 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner inet_strtoip(CTL_SPECIAL, &special_addr_ip); 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner alias_addr_ip = special_addr_ip | CTL_ALIAS; 2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner getouraddr(); 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL); 2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) 2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) 2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define UPD_NFDS(x) if (nfds < (x)) nfds = (x) 2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * curtime kept to an accuracy of 1ms 2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void updtime(void) 2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct _timeb tb; 2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _ftime(&tb); 2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner curtime = (u_int)tb.time * (u_int)1000; 2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner curtime += (u_int)tb.millitm; 2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void updtime(void) 2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gettimeofday(&tt, NULL); 2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner curtime = (u_int)tt.tv_sec * (u_int)1000; 2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner curtime += (u_int)tt.tv_usec / (u_int)1000; 2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((tt.tv_usec % 1000) >= 500) 2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner curtime++; 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid slirp_select_fill(int *pnfds, 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_set *readfds, fd_set *writefds, fd_set *xfds) 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so, *so_next; 2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct timeval timeout; 2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int nfds; 2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int tmp_time; 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* fail safe */ 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_readfds = NULL; 3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_writefds = NULL; 3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_xfds = NULL; 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nfds = *pnfds; 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * First, TCP sockets 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do_slowtimo = 0; 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (link_up) { 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * *_slowtimo needs calling if there are IP fragments 3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * in the fragment queue, or there are TCP connections active 3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do_slowtimo = ((tcb.so_next != &tcb) || 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (&ipq.ip_link != ipq.ip_link.next)); 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (so = tcb.so_next; so != &tcb; so = so_next) { 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so_next = so->so_next; 3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * See if we need a tcp_fasttimo 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) 3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner time_fasttimo = curtime; /* Flag when we want a fasttimo */ 3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NOFDREF can include still connecting to local-host, 3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * newly socreated() sockets etc. Don't want to select these. 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_state & SS_NOFDREF || so->s == -1) 3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * don't register proxified socked connections here 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_state & SS_PROXIFIED) != 0) 3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Set for reading sockets which are accepting 3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_state & SS_FACCEPTCONN) { 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(so->s, readfds); 3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner UPD_NFDS(so->s); 3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Set for writing sockets which are connecting 3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_state & SS_ISFCONNECTING) { 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(so->s, writefds); 3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner UPD_NFDS(so->s); 3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Set for writing if we are connected, can send more, and 3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * we have something to send 3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) { 3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(so->s, writefds); 3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner UPD_NFDS(so->s); 3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Set for reading (and urgent data) if we are connected, can 3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * receive more, and we have room for it XXX /2 ? 3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) { 3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(so->s, readfds); 3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(so->s, xfds); 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner UPD_NFDS(so->s); 3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * UDP sockets 3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (so = udb.so_next; so != &udb; so = so_next) { 3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so_next = so->so_next; 3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_state & SS_PROXIFIED) != 0) 3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * See if it's timed out 3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_expire) { 3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_expire <= curtime) { 3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner udp_detach(so); 3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do_slowtimo = 1; /* Let socket expire */ 3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * When UDP packets are received from over the 4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * link, they're sendto()'d straight away, so 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * no need for setting for writing 4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Limit the number of packets queued by this session 4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to 4. Note that even though we try and limit this 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to 4 packets, the session could have more queued 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * if the packets needed to be fragmented 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * (XXX <= 4 ?) 4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) { 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(so->s, readfds); 4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner UPD_NFDS(so->s); 4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Setup timeout to use minimum CPU usage, especially when idle 4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * First, see the timeout needed by *timo 4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner timeout.tv_sec = 0; 4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner timeout.tv_usec = -1; 4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * If a slowtimo is needed, set timeout to 500ms from the last 4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * slow timeout. If a fast timeout is needed, set timeout within 4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 200ms of when it was requested. 4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (do_slowtimo) { 4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXX + 10000 because some select()'s aren't that accurate */ 4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000; 4335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (timeout.tv_usec < 0) 4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner timeout.tv_usec = 0; 4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (timeout.tv_usec > 510000) 4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner timeout.tv_usec = 510000; 4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Can only fasttimo if we also slowtimo */ 4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (time_fasttimo) { 4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp_time = (200 - (curtime - time_fasttimo)) * 1000; 4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tmp_time < 0) 4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp_time = 0; 4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Choose the smallest of the 2 */ 4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tmp_time < timeout.tv_usec) 4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner timeout.tv_usec = (u_int)tmp_time; 4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * now, the proxified sockets 4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner proxy_manager_select_fill(&nfds, readfds, writefds, xfds); 4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *pnfds = nfds; 4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) 4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so, *so_next; 4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_readfds = readfds; 4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_writefds = writefds; 4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_xfds = xfds; 4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Update time */ 4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner updtime(); 4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * See if anything has timed out 4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (link_up) { 4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { 4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_fasttimo(); 4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner time_fasttimo = 0; 4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) { 4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_slowtimo(); 4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_slowtimo(); 4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner last_slowtimo = curtime; 4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Check sockets 4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (link_up) { 4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Check TCP sockets 4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (so = tcb.so_next; so != &tcb; so = so_next) { 4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so_next = so->so_next; 4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * FD_ISSET is meaningless on these sockets 4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * (and they can crash the program) 4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_state & SS_NOFDREF || so->s == -1) 4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * proxified sockets are polled later in this 5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * function. 5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_state & SS_PROXIFIED) != 0) 5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Check for URG data 5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This will soread as well, so no need to 5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * test for readfds below if this succeeds 5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (FD_ISSET(so->s, xfds)) 5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sorecvoob(so); 5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Check sockets for reading 5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (FD_ISSET(so->s, readfds)) { 5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Check for incoming connections 5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_state & SS_FACCEPTCONN) { 5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_connect(so); 5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } /* else */ 5265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = soread(so); 5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Output it if we read something */ 5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret > 0) 5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_output(sototcpcb(so)); 5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Check sockets for writing 5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (FD_ISSET(so->s, writefds)) { 5375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Check for non-blocking, still-connecting sockets 5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_state & SS_ISFCONNECTING) { 5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Connected */ 5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state &= ~SS_ISFCONNECTING; 5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = socket_send(so->s, (const void *)&ret, 0); 5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXXXX Must fix, zero bytes is a NOP */ 5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (errno == EAGAIN || errno == EWOULDBLOCK || 5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno == EINPROGRESS || errno == ENOTCONN) 5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* else failed */ 5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state = SS_NOFDREF; 5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* else so->so_state &= ~SS_ISFCONNECTING; */ 5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Continue tcp_input 5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); 5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* continue; */ 5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = sowrite(so); 5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * XXXXX If we wrote something (a lot), there 5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * could be a need for a window update. 5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * In the worst case, the remote will send 5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * a window probe to get things going again 5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Probe a still-connecting, non-blocking socket 5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to check if it's still alive 5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef PROBE_CONN 5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_state & SS_ISFCONNECTING) { 5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = socket_recv(so->s, (char *)&ret, 0); 5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXX */ 5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (errno == EAGAIN || errno == EWOULDBLOCK || 5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno == EINPROGRESS || errno == ENOTCONN) 5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; /* Still connecting, continue */ 5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* else failed */ 5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state = SS_NOFDREF; 5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* tcp_input will take care of it */ 5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = socket_send(so->s, &ret, 0); 5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXX */ 5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (errno == EAGAIN || errno == EWOULDBLOCK || 5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno == EINPROGRESS || errno == ENOTCONN) 5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* else failed */ 5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state = SS_NOFDREF; 5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state &= ~SS_ISFCONNECTING; 6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_input((struct mbuf *)NULL, sizeof(struct ip),so); 6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } /* SS_ISFCONNECTING */ 6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Now UDP sockets. 6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Incoming packets are sent straight away, they're not buffered. 6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Incoming UDP data isn't buffered either. 6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (so = udb.so_next; so != &udb; so = so_next) { 6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so_next = so->so_next; 6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_state & SS_PROXIFIED) != 0) 6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->s != -1 && FD_ISSET(so->s, readfds)) { 6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sorecvfrom(so); 6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Now the proxified sockets 6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner proxy_manager_poll(readfds, writefds, xfds); 6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * See if we can start outputting 6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (if_queued && link_up) 6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if_start(); 6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* clear global file descriptor sets. 6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * these reside on the stack in vl.c 6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * so they're unusable if we're not in 6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * slirp_select_fill or slirp_select_poll. 6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_readfds = NULL; 6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_writefds = NULL; 6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner global_xfds = NULL; 6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ETH_ALEN 6 6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ETH_HLEN 14 6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ETH_P_IP 0x0800 /* Internet Protocol packet */ 6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ETH_P_ARP 0x0806 /* Address Resolution packet */ 6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ARPOP_REQUEST 1 /* ARP request */ 6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ARPOP_REPLY 2 /* ARP reply */ 6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct ethhdr 6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ 6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char h_source[ETH_ALEN]; /* source ether addr */ 6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned short h_proto; /* packet type ID field */ 6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct arphdr 6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned short ar_hrd; /* format of hardware address */ 6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned short ar_pro; /* format of protocol address */ 6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char ar_hln; /* length of hardware address */ 6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char ar_pln; /* length of protocol address */ 6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned short ar_op; /* ARP opcode (command) */ 6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Ethernet looks like this : This bit is variable sized however... 6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 6725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ 6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char ar_sip[4]; /* sender IP address */ 6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ 6755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned char ar_tip[4]; /* target IP address */ 6765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 6775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void arp_input(const uint8_t *pkt, int pkt_len) 6795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ethhdr *eh = (struct ethhdr *)pkt; 6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN); 6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)]; 6835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ethhdr *reh = (struct ethhdr *)arp_reply; 6845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN); 6855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ar_op; 6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ex_list *ex_ptr; 6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ar_op = ntohs(ah->ar_op); 6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(ar_op) { 6905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t ar_tip_ip; 6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case ARPOP_REQUEST: 6935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ar_tip_ip = ip_read32h(ah->ar_tip); 6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((ar_tip_ip & 0xffffff00) == special_addr_ip) { 6955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t ar_tip_low = ar_tip_ip & 0xff; 6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ( CTL_IS_DNS(ar_tip_low) || ar_tip_low == CTL_ALIAS) 6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto arp_ok; 6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { 6995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ex_ptr->ex_addr == ar_tip_low) 7005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto arp_ok; 7015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner arp_ok: 7045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXX: make an ARP request to have the client address */ 7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(client_ethaddr, eh->h_source, ETH_ALEN); 7065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* ARP request for alias/dns mac address */ 7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN); 7095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1); 7105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner reh->h_source[5] = ar_tip_low; 7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner reh->h_proto = htons(ETH_P_ARP); 7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_hrd = htons(1); 7145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_pro = htons(ETH_P_IP); 7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_hln = ETH_ALEN; 7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_pln = 4; 7175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_op = htons(ARPOP_REPLY); 7185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(rah->ar_sha, reh->h_source, ETH_ALEN); 7195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(rah->ar_sip, ah->ar_tip, 4); 7205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN); 7215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(rah->ar_tip, ah->ar_sip, 4); 7225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_output(arp_reply, sizeof(arp_reply)); 7235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case ARPOP_REPLY: 7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* reply to request of client mac address ? */ 7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) && 7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_equal( ip_read(ah->ar_sip), client_ip )) { 7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN); 7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid slirp_input(const uint8_t *pkt, int pkt_len) 7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct mbuf *m; 7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int proto; 7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (pkt_len < ETH_HLEN) 7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner proto = ntohs(*(uint16_t *)(pkt + 12)); 7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(proto) { 7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case ETH_P_ARP: 7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner arp_input(pkt, pkt_len); 7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case ETH_P_IP: 7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m = m_get(); 7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!m) 7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Note: we add to align the IP header */ 7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (M_FREEROOM(m) < pkt_len + 2) { 7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_inc(m, pkt_len + 2); 7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len = pkt_len + 2; 7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(m->m_data + 2, pkt, pkt_len); 7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data += 2 + ETH_HLEN; 7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len -= 2 + ETH_HLEN; 7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_input(m); 7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* output the IP packet to the ethernet device */ 7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid if_encap(const uint8_t *ip_data, int ip_data_len) 7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t buf[1600]; 7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ethhdr *eh = (struct ethhdr *)buf; 7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ip_data_len + ETH_HLEN > sizeof(buf)) 7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) { 7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)]; 7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ethhdr *reh = (struct ethhdr *)arp_req; 7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN); 7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const struct ip *iph = (const struct ip *)ip_data; 7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* If the client addr is not known, there is no point in 7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sending the packet to it. Normally the sender should have 7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner done an ARP request to get its MAC address. Here we do it 7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner in place of sending the packet and we hope that the sender 7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner will retry sending its packet. */ 7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(reh->h_dest, 0xff, ETH_ALEN); 7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1); 7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner reh->h_source[5] = CTL_ALIAS; 7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner reh->h_proto = htons(ETH_P_ARP); 7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_hrd = htons(1); 7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_pro = htons(ETH_P_IP); 7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_hln = ETH_ALEN; 7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_pln = 4; 7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_op = htons(ARPOP_REQUEST); 8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* source hw addr */ 8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1); 8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rah->ar_sha[5] = CTL_ALIAS; 8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* source IP */ 8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_write32h(alias_addr_ip, rah->ar_sip); 8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* target hw addr (none) */ 8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(rah->ar_tha, 0, ETH_ALEN); 8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* target IP */ 8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_write( iph->ip_dst, rah->ar_tip ); 8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner client_ip = iph->ip_dst; 8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_output(arp_req, sizeof(arp_req)); 8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(eh->h_dest, client_ethaddr, ETH_ALEN); 8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1); 8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXX: not correct */ 8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner eh->h_source[5] = CTL_ALIAS; 8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner eh->h_proto = htons(ETH_P_IP); 8175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len); 8185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_output(buf, ip_data_len + ETH_HLEN); 8195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void _slirp_redir_loop(void (*func)(void *opaque, int is_udp, 8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const SockAddress *laddr, 8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const SockAddress *faddr), 8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner void *opaque, int is_udp) 8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *head = (is_udp ? &udb : &tcb); 8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so; 8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (so = head->so_next; so != head; so = so->so_next) { 8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SockAddress local, foreign; 8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_init_inet(&local, so->so_laddr_ip, so->so_laddr_port); 8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_init_inet(&foreign, so->so_faddr_ip, so->so_faddr_port); 8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner func(opaque, is_udp, 8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner &local, &foreign); 8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid slirp_redir_loop(void (*func)(void *opaque, int is_udp, 8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const SockAddress *laddr, 8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const SockAddress *faddr), 8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner void *opaque) 8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _slirp_redir_loop(func, opaque, 0); 8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner _slirp_redir_loop(func, opaque, 1); 8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Unlistens a redirection 8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Return value: number of redirs removed */ 8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_redir_rm(int is_udp, int host_port) 8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so; 8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *head = (is_udp ? &udb : &tcb); 8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n = 0; 8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner loop_again: 8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (so = head->so_next; so != head; so = so->so_next) { 8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_faddr_port == host_port) { 8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(so->s); 8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sofree(so); 8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner n++; 8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto loop_again; 8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return n; 8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_redir(int is_udp, int host_port, 8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t guest_ip, int guest_port) 8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_udp) { 8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!udp_listen(host_port, 8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner guest_ip, 8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner guest_port, 0)) 8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!solisten(host_port, guest_ip, guest_port, 0)) 8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_unredir(int is_udp, int host_port) 8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_udp) 8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return udp_unlisten( host_port ); 8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return sounlisten( host_port ); 8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_add_exec(int do_pty, const void *args, int addr_low_byte, 8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int guest_port) 8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return add_exec(&exec_list, do_pty, (char *)args, 8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr_low_byte, htons(guest_port)); 8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) 9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->s == -1 && so->extra) { 9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_write(so->extra, buf, len); 9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return len; 9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return send(so->s, buf, len, flags); 9095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port) 9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so; 9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (so = tcb.so_next; so != &tcb; so = so->so_next) { 9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_faddr_ip & 0xffffff00) == 9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner special_addr_ip 9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner && ((so->so_faddr_port & 0xff) == 9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr_low_byte) 9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner && so->so_faddr_port == guest_port) 9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return so; 9225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 9255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersize_t slirp_socket_can_recv(int addr_low_byte, int guest_port) 9285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct iovec iov[2]; 9305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so; 9315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!link_up) 9335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 9345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so = slirp_find_ctl_socket(addr_low_byte, guest_port); 9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!so || so->so_state & SS_NOFDREF) 9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 9395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2)) 9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return sopreprbuf(so, iov, NULL); 9445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf, 9475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size) 9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port); 9515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!so) 9535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 9545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = soreadbuf(so, (const char *)buf, size); 9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret > 0) 9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_output(sototcpcb(so)); 9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp) 9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_state); 9665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < TCPT_NTIMERS; i++) 9675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_timer[i]); 9685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_rxtshift); 9695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_rxtcur); 9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_dupacks); 9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be16(f, tp->t_maxseg); 9725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbyte(f, tp->t_force); 9735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be16(f, tp->t_flags); 9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_una); 9755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_nxt); 9765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_up); 9775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_wl1); 9785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_wl2); 9795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->iss); 9805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_wnd); 9815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->rcv_wnd); 9825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->rcv_nxt); 9835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->rcv_up); 9845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->irs); 9855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->rcv_adv); 9865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_max); 9875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_cwnd); 9885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->snd_ssthresh); 9895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_idle); 9905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_rtt); 9915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->t_rtseq); 9925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_srtt); 9935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_rttvar); 9945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be16(f, tp->t_rttmin); 9955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->max_sndwnd); 9965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, tp->t_oobflags); 9975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, tp->t_iobc); 9985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe16(f, tp->t_softerror); 9995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, tp->snd_scale); 10005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, tp->rcv_scale); 10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, tp->request_r_scale); 10025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, tp->requested_s_scale); 10035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->ts_recent); 10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->ts_recent_age); 10055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, tp->last_ack_sent); 10065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf) 10095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t off; 10115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, sbuf->sb_cc); 10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, sbuf->sb_datalen); 10145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data); 10155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe32(f, off); 10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data); 10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_sbe32(f, off); 10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen); 10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_socket_save(QEMUFile *f, struct socket *so) 10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, so->so_urgc); 10245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, so->so_faddr_ip); 10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, so->so_laddr_ip); 10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be16(f, so->so_faddr_port); 10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be16(f, so->so_laddr_port); 10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, so->so_iptos); 10295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, so->so_emu); 10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, so->so_type); 10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_be32(f, so->so_state); 10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_sbuf_save(f, &so->so_rcv); 10335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_sbuf_save(f, &so->so_snd); 10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_tcp_save(f, so->so_tcpcb); 10355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_state_save(QEMUFile *f, void *opaque) 10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ex_list *ex_ptr; 10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) 10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ex_ptr->ex_pty == 3) { 10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so; 10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport)); 10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!so) 10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, 42); 10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_socket_save(f, so); 10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_put_byte(f, 0); 10525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp) 10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_state = qemu_get_sbe16(f); 10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < TCPT_NTIMERS; i++) 10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_timer[i] = qemu_get_sbe16(f); 10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_rxtshift = qemu_get_sbe16(f); 10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_rxtcur = qemu_get_sbe16(f); 10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_dupacks = qemu_get_sbe16(f); 10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_maxseg = qemu_get_be16(f); 10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_force = qemu_get_sbyte(f); 10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_flags = qemu_get_be16(f); 10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_una = qemu_get_be32(f); 10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_nxt = qemu_get_be32(f); 10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_up = qemu_get_be32(f); 10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_wl1 = qemu_get_be32(f); 10715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_wl2 = qemu_get_be32(f); 10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->iss = qemu_get_be32(f); 10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_wnd = qemu_get_be32(f); 10745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->rcv_wnd = qemu_get_be32(f); 10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->rcv_nxt = qemu_get_be32(f); 10765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->rcv_up = qemu_get_be32(f); 10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->irs = qemu_get_be32(f); 10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->rcv_adv = qemu_get_be32(f); 10795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_max = qemu_get_be32(f); 10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_cwnd = qemu_get_be32(f); 10815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_ssthresh = qemu_get_be32(f); 10825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_idle = qemu_get_sbe16(f); 10835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_rtt = qemu_get_sbe16(f); 10845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_rtseq = qemu_get_be32(f); 10855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_srtt = qemu_get_sbe16(f); 10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_rttvar = qemu_get_sbe16(f); 10875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_rttmin = qemu_get_be16(f); 10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->max_sndwnd = qemu_get_be32(f); 10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_oobflags = qemu_get_byte(f); 10905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_iobc = qemu_get_byte(f); 10915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->t_softerror = qemu_get_sbe16(f); 10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->snd_scale = qemu_get_byte(f); 10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->rcv_scale = qemu_get_byte(f); 10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->request_r_scale = qemu_get_byte(f); 10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->requested_s_scale = qemu_get_byte(f); 10965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->ts_recent = qemu_get_be32(f); 10975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->ts_recent_age = qemu_get_be32(f); 10985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tp->last_ack_sent = qemu_get_be32(f); 10995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_template(tp); 11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf) 11035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t off, sb_cc, sb_datalen; 11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sb_cc = qemu_get_be32(f); 11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sb_datalen = qemu_get_be32(f); 11085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbreserve(sbuf, sb_datalen); 11105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sbuf->sb_datalen != sb_datalen) 11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOMEM; 11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbuf->sb_cc = sb_cc; 11155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner off = qemu_get_sbe32(f); 11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbuf->sb_wptr = sbuf->sb_data + off; 11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner off = qemu_get_sbe32(f); 11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbuf->sb_rptr = sbuf->sb_data + off; 11205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen); 11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int slirp_socket_load(QEMUFile *f, struct socket *so) 11265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tcp_attach(so) < 0) 11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOMEM; 11295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_urgc = qemu_get_be32(f); 11315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr_ip = qemu_get_be32(f); 11325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr_ip = qemu_get_be32(f); 11335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr_port = qemu_get_be16(f); 11345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr_port = qemu_get_be16(f); 11355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_iptos = qemu_get_byte(f); 11365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_emu = qemu_get_byte(f); 11375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_type = qemu_get_byte(f); 11385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state = qemu_get_be32(f); 11395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_sbuf_load(f, &so->so_rcv) < 0) 11405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOMEM; 11415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_sbuf_load(f, &so->so_snd) < 0) 11425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOMEM; 11435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_tcp_load(f, so->so_tcpcb); 11445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 11465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int slirp_state_load(QEMUFile *f, void *opaque, int version_id) 11495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ex_list *ex_ptr; 11515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int r; 11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while ((r = qemu_get_byte(f))) { 11545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so = socreate(); 11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!so) 11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -ENOMEM; 11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = slirp_socket_load(f, so); 11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) 11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_faddr_ip & 0xffffff00) != special_addr_ip) 11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -EINVAL; 11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) 11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ex_ptr->ex_pty == 3 && 11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (so->so_faddr_ip & 0xff) == ex_ptr->ex_addr && 11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr_port == ex_ptr->ex_fport) 11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!ex_ptr) 11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -EINVAL; 11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->extra = (void *)ex_ptr->ex_exec; 11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1182