socket.c revision 0146f0c7a9442e4a2f259d37113b56393d59aa09
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#define WANT_SYS_IOCTL_H
#include <slirp.h>
#include "ip_icmp.h"
#include "main.h"
#ifdef __sun__
#endif
#ifdef VBOX_WITH_SYNC_SLIRP
#include <iprt/semaphore.h>
#endif
void
so_init()
{
/* Nothing yet */
}
struct socket *
{
break;
}
return so;
}
/*
* Create a new socket, initialise the fields
* It is the responsibility of the caller to
* insque() it into the correct linked-list
*/
struct socket *
socreate()
{
if(so) {
so->s = -1;
}
return(so);
}
/*
* remque and free a socket, clobber cache
*/
void
{
#ifndef VBOX_WITH_SYNC_SLIRP
}
if (so == tcp_last_so)
tcp_last_so = &tcb;
else if (so == udp_last_so)
udp_last_so = &udb;
#else
/*Take global mutexes of udb and tcb, because we dont know which is mutex */
/*XXX: don't forget to set correct so_type in corresponded attach operation */
}
}
}
else {
Assert(!"unknown type");
}
if (so == tcp_last_so)
tcp_last_so = &tcb;
else if (so == udp_last_so)
udp_last_so = &udb;
}
}
else {
Assert(!"unknown type");
}
/* socket's mutex could be released because socket none accessible via queue anymore*/
#endif
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}
/*
* 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
*/
int
{
DEBUG_CALL("soread");
/*
* 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... */
n = 1;
} else {
/* Should never succeed, but... */
if (len) {
n = 2;
} else {
n = 1;
}
} else
n = 2;
} else {
n = 1;
}
}
#ifdef HAVE_READV
#else
#endif
if (nn <= 0) {
return 0;
}
else {
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
return -1;
}
}
#ifndef HAVE_READV
/*
* 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
*/
int ret;
if (ret > 0)
}
#endif
/* Update fields */
return nn;
}
/*
* Get urgent data
*
* 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
*/
void
{
DEBUG_CALL("sorecvoob");
/*
* 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
* urgent data.
*/
}
/*
* Send urgent data
* There's a lot duplicated code here, but...
*/
int
{
int n, len;
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
DEBUG_CALL("sosendoob");
/* We can send it directly */
} else {
/*
* Since there's no sendv or sendtov like writev,
* we must copy all data to a linear buffer then
* send it all
*/
len += n;
}
#ifdef DEBUG
if (n != len)
#endif
}
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
return n;
}
/*
* Write data from so_rcv to so's socket,
* updating all sbuf field as necessary
*/
int
{
int n,nn;
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
DEBUG_CALL("sowrite");
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
return 0;
}
/*
* No need to check if there's something to write,
* sowrite wouldn't have been called otherwise
*/
/* Should never succeed, but... */
n = 1;
} else {
if (len) {
n = 2;
} else
n = 1;
}
/* Check if there's urgent data to send, and if so, send it */
#ifdef HAVE_READV
#else
#endif
/* This should never happen, but people tell me it does *shrug* */
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
return 0;
}
if (nn <= 0) {
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
return -1;
}
#ifndef HAVE_READV
int ret;
if (ret > 0)
}
#endif
/* Update sbuf */
/*
* If in DRAIN mode, and there's no more data, set
* it CANTSENDMORE
*/
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
return nn;
}
/*
* recvfrom() a UDP socket
*/
void
{
struct sockaddr_in addr;
DEBUG_CALL("sorecvfrom");
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
char buff[256];
int len;
/* XXX Check if reply is "correct"? */
} else {
}
/* No need for this socket anymore, udp_detach it */
} else { /* A "normal" UDP packet */
struct mbuf *m;
int len, n;
m->m_data += if_maxlinkhdr;
/*
* XXX Shouldn't FIONREAD packets destined for port 53,
* but I don't know the max packet size for DNS lookups
*/
len = M_FREEROOM(m);
/* if (so->so_fport != htons(53)) { */
if (n > len) {
m_inc(m, n);
len = M_FREEROOM(m);
}
/* } */
if(m->m_len<0) {
} else {
/*
* 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...)
*/
else
}
/* if (m->m_len == len) {
* m_inc(m, MINCSIZE);
* m->m_len = 0;
* }
*/
/*
* If this packet was destined for CTL_ADDR,
* make it look like that's where it came from, done by udp_output
*/
} /* rx error */
} /* if ping packet */
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}
/*
* sendto() a socket
*/
int
{
int ret;
struct sockaddr_in addr;
#if 0
struct sockaddr_in host_addr;
#endif
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
DEBUG_CALL("sosendto");
DEBUG_ARG("m = %lx", (long)m);
/* It's an alias */
switch(last_byte) {
#if 0
/* handle this case at 'default:' */
case CTL_BROADCAST:
# if 0
/* 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. */
# endif
break;
#endif
case CTL_DNS:
else
break;
case CTL_ALIAS:
default:
else
break;
}
} else
DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
/* Don't care what port we get */
if (ret < 0) {
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
return -1;
}
/*
* Kill the socket if there's no reply in 4 minutes,
* but only if it's an expirable socket
*/
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
return 0;
}
/*
* XXX This should really be tcp_listen
*/
struct socket *
{
struct sockaddr_in addr;
int s, opt = 1;
DEBUG_CALL("solisten");
/* free(so); Not sofree() ??? free(NULL) == NOP */
return NULL;
}
/* Don't tcp_attach... we don't need so_snd nor so_rcv */
return NULL;
}
#ifndef VBOX_WITH_SYNC_SLIRP
#else
/*after adding to global queue probably we should keep lock*/
#endif
/*
* SS_FACCEPTONCE sockets must time out.
*/
if (flags & SS_FACCEPTONCE)
(listen(s,1) < 0)) {
#ifdef RT_OS_WINDOWS
closesocket(s);
/* Restore the real errno */
#else
close(s);
/* Restore the real errno */
#endif
return NULL;
}
else
so->s = s;
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
return so;
}
/*
* Data is available in so_rcv
* Just write() the data to the socket
* XXX not yet...
*/
void
{
/* sowrite(so); */
/* FD_CLR(so->s,&writefds); */
}
/*
* 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
*/
void
{
/* Nothing, yet */
}
/*
* 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
*/
void
{
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}
void
{
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}
void
{
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}
else
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}
void
{
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}
else
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}
void
{
/* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
/* close(so->s); */
/* so->so_state = SS_ISFDISCONNECTED; */
/*
* XXX Do nothing ... ?
*/
}
/*
* Set write drain mode
* Set CANTSENDMORE once all data has been write()n
*/
void
{
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
else
#ifdef VBOX_WITH_SYNC_SLIRP
#endif
}