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