socket.c revision bcacc87b5019dd907592a9025de8c1750269fdb0
2362N/A * Copyright (c) 1995 Danny Gasparovski. 0N/A * Please read the file COPYRIGHT for the 0N/A * terms and conditions of the copyright. 0N/A#
else /* RT_OS_WINDOWS */ 0N/A#
endif /* !RT_OS_WINDOWS */ * Create a new socket, initialise the fields * It is the responsibility of the caller to * insque() it into the correct linked-list * remque and free a socket, clobber cache * VBOX_WITH_SLIRP_MT: before sofree queue should be locked, because * in sofree we don't know from which queue item beeing removed. /* check if mbuf haven't been already freed */ * Read from so's socket into sb_snd, updating all relevant sbuf fields * NOTE: This will only be called if it is select()ed for reading, so * a read() of 0 (or less) means it's disconnected * No need to check if there's enough room to read. * soread wouldn't have been called if there weren't /* Should never succeed, but... */ /* Should never succeed, but... */ * Special case for WSAEnumNetworkEvents: If we receive 0 bytes that * _could_ mean that the connection is closed. But we will receive an * FD_CLOSE event later if the connection was _really_ closed. With * www.youtube.com I see this very often. Closing the socket too early /* nn == 0 means peer has performed an orderly shutdown */ DEBUG_MISC((
dfd,
" --- soread() disconnected, nn = %d, errno = %d-%s\n",
* If there was no error, try and read the second time round * We read again if n = 2 (ie, there's another part of the buffer) * and we read as much as we could in the first read * We don't test for <= 0 this time, because there legitimately * might not be any more data (since the socket is non-blocking), * a close will be detected on next iteration. * A return of -1 wont (shouldn't) happen, since it didn't happen above * When the socket is created, we set it SO_OOBINLINE, * so when OOB data arrives, we soread() it and everything * in the send buffer is sent as urgent data * We take a guess at how much urgent data has arrived. * In most situations, when urgent data arrives, the next * read() should get all the urgent data. This guess will * be wrong however if more data arrives just after the * urgent data, or the read() doesn't return all the * There's a lot duplicated code here, but... char buff[
2048];
/* XXX Shouldn't be sending more oob data than this */ /* We can send it directly */ DEBUG_MISC((
dfd,
" --- sent %d bytes urgent data, %d urgent bytes left\n",
* Since there's no sendv or sendtov like writev, * we must copy all data to a linear buffer then DEBUG_MISC((
dfd,
" ---2 sent %d bytes urgent data, %d urgent bytes left\n",
* Write data from so_rcv to so's socket, * updating all sbuf field as necessary * No need to check if there's something to write, * sowrite wouldn't have been called otherwise /* Should never succeed, but... */ /* Check if there's urgent data to send, and if so, send it */ /* This should never happen, but people tell me it does *shrug* */ DEBUG_MISC((
dfd,
" --- sowrite disconnected, so->so_state = %x, errno = %d\n",
* If in DRAIN mode, and there's no more data, set * recvfrom() a UDP socket /* This is a "ping" reply */ #
else /* RT_OS_WINDOWS */#
endif /* !RT_OS_WINDOWS */ /* A "normal" UDP packet */ +
sizeof(
struct ip);
/*XXX: no options atm*/ * XXX Shouldn't FIONREAD packets destined for port 53, * but I don't know the max packet size for DNS lookups /* if (so->so_fport != htons(53)) */ Log2((
" did recvfrom %d, errno = %d-%s\n",
Log2((
dfd,
" rx error, tx icmp ICMP_UNREACH:%i\n",
code));
* Hack: domain name lookup will be used the most for UDP, * and since they'll only be used once there's no need * for the 4 minute (or whatever) timeout... So we time them * out much quicker (10 seconds for now...) * If this packet was destined for CTL_ADDR, * make it look like that's where it came from, done by udp_output /* handle this case at 'default:' */ /* Send the packet to host to fully emulate broadcast */ /** @todo r=klaus: on Linux host this causes the host to receive * the packet twice for some reason. And I cannot find any place * in the man pages which states that sending a broadcast does not * reach the host itself. */ /* Don't care what port we get */ * Kill the socket if there's no reply in 4 minutes, * but only if it's an expirable socket * XXX This should really be tcp_listen /* RTMemFree(so); Not sofree() ??? free(NULL) == NOP */ /* Don't tcp_attach... we don't need so_snd nor so_rcv */ * SS_FACCEPTONCE sockets must time out. /* Restore the real errno */ int tmperrno =
errno;
/* Don't clobber the real reason we failed */ /* Restore the real errno */ * Data is available in so_rcv * Just write() the data to the socket * Data has been freed in so_snd * We have room for a read() if we want to * For now, don't read, it'll be done in the main loop * Various session state calls * XXX Should be #define's * The socket state stuff needs work, these often get call 2 or 3 * times each when only 1 was needed /* XXX close() here as well? */ * Set CANTSENDMORE once all data has been write()n Log((
"NAT: Can't find the corresponding packet for the received ICMP\n"));
/* Now ip is pointing on header we've sent from guest */ /* source address from original IP packet*/ /* overide ther tail of old packet */ ip =
mtod(m,
struct ip *);
/* ip is from mbuf we've overrided */ /* saves original ip header and options */ ip->
ip_p =
IPPROTO_ICMP;
/* the original package could be whatever, but we're response via ICMP*/ /* according RFC 793 error messages required copy of initial IP header + 64 bit */ /* Don't call m_free here*/ /*XXX: so->so_m already freed so we shouldn't call sofree */ /*close tcp should be here */ struct ip *
ip_broken;
/* ICMP returns header + 64 bit of packet */ fIcmp = 0;
/* reply processed */ for (i = 0; i <
len; ++i)
/* UNREACH error inject here */ icp = (
struct icmp *)&
ip[
1];
/* no options */ #
else /* RT_OS_WINDOWS */ /* XXX Check if reply is "correct"? */ #
endif /* !RT_OS_WINDOWS */