-
#include <oskittcp.h>
#include <oskitdebug.h>
-#include <ntddk.h>
+#include <net/raw_cb.h>
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 };
-OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
+//OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
+OSK_UINT OskitDebugTraceLevel = 0;
/* SPL */
unsigned cpl;
unsigned volatile ipending;
struct timeval boottime;
+void clock_init();
+int isprint(int c);
+int _snprintf(char * buf, size_t cnt, const char *fmt, ...);
+
+void *fbsd_malloc( unsigned int bytes, ... ) {
+ if( !OtcpEvent.TCPMalloc ) panic("no malloc");
+ return OtcpEvent.TCPMalloc
+ ( OtcpEvent.ClientData, (OSK_UINT)bytes, "*", 0 );
+}
+
+void fbsd_free( void *data, ... ) {
+ if( !OtcpEvent.TCPFree ) panic("no free");
+ OtcpEvent.TCPFree( OtcpEvent.ClientData, data, "*", 0 );
+}
+
void InitOskitTCP() {
OS_DbgPrint(OSK_MID_TRACE,("Init Called\n"));
- OS_DbgPrint(OSK_MID_TRACE,("Init fake freebsd scheduling\n"));
- init_freebsd_sched();
+ OS_DbgPrint(OSK_MID_TRACE,("MB Init\n"));
+ mbinit();
+ OS_DbgPrint(OSK_MID_TRACE,("Rawip Init\n"));
+ rip_init();
+ raw_init();
+ OS_DbgPrint(OSK_MID_TRACE,("Route Init\n"));
+ route_init();
OS_DbgPrint(OSK_MID_TRACE,("Init clock\n"));
clock_init();
OS_DbgPrint(OSK_MID_TRACE,("Init TCP\n"));
tcp_init();
OS_DbgPrint(OSK_MID_TRACE,("Init routing\n"));
domaininit();
- memset( &OtcpEvent, 0, sizeof( OtcpEvent ) );
OS_DbgPrint(OSK_MID_TRACE,("Init Finished\n"));
tcp_iss = 1024;
}
void DeinitOskitTCP() {
}
-void TimerOskitTCP() {
- tcp_slowtimo();
+void TimerOskitTCP( int FastTimer, int SlowTimer ) {
+ if ( SlowTimer ) {
+ tcp_slowtimo();
+ }
+ if ( FastTimer ) {
+ tcp_fasttimo();
+ }
}
void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
memcpy( &OtcpEvent, EventHandlers, sizeof(OtcpEvent) );
- if( OtcpEvent.PacketSend )
+ if( OtcpEvent.PacketSend )
OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n",
OtcpEvent.PacketSend));
}
-void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len ) {
- unsigned int i;
-
- for( i = 0; i < Len; i++ ) {
- if( i && !(i & 0xf) ) DbgPrint( "\n" );
- if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
- DbgPrint( " %02x", Data[i] );
- }
- DbgPrint("\n");
+void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len )
+{
+ unsigned int i;
+ char line[81];
+ static const char* hex = "0123456789abcdef";
+
+ for ( i = 0; i < Len; i++ )
+ {
+ int align = i & 0xf;
+ int align3 = (align<<1) + align;
+ unsigned char c = Data[i];
+ if ( !align )
+ {
+ if ( i ) DbgPrint( line );
+ _snprintf ( line, sizeof(line)-1, "%08x: \n", &Data[i] );
+ line[sizeof(line)-1] = '\0';
+ }
+
+ line[10+align3] = hex[(c>>4)&0xf];
+ line[11+align3] = hex[c&0xf];
+ if ( !isprint(c) )
+ c = '.';
+ line[59+align] = c;
+ }
+ if ( Len & 0xf )
+ DbgPrint ( line );
}
/* From uipc_syscalls.c */
int OskitTCPSocket( void *context,
- void **aso,
- int domain,
- int type,
- int proto )
+ void **aso,
+ int domain,
+ int type,
+ int proto )
{
struct socket *so;
int error = socreate(domain, &so, type, proto);
if( !error ) {
so->so_connection = context;
so->so_state = SS_NBIO;
+ so->so_error = 0;
+ so->so_q = so->so_q0 = NULL;
+ so->so_qlen = 0;
+ so->so_head = NULL;
*aso = so;
}
return error;
OSK_UINT Len,
OSK_UINT *OutLen,
OSK_UINT Flags ) {
- struct mbuf *paddr = 0;
- struct mbuf m, *mp;
struct uio uio = { 0 };
+ struct iovec iov = { 0 };
int error = 0;
int tcp_flags = 0;
+ *OutLen = 0;
+
+ OS_DbgPrint(OSK_MID_TRACE,
+ ("so->so_state %x\n", ((struct socket *)connection)->so_state));
+
if( Flags & OSK_MSG_OOB ) tcp_flags |= MSG_OOB;
if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT;
if( Flags & OSK_MSG_PEEK ) tcp_flags |= MSG_PEEK;
uio.uio_resid = Len;
- m.m_len = Len;
- m.m_data = Data;
- m.m_type = MT_DATA;
- m.m_flags = M_PKTHDR | M_EOR;
-
- mp = &m;
+ uio.uio_iov = &iov;
+ uio.uio_rw = UIO_READ;
+ uio.uio_iovcnt = 1;
+ iov.iov_len = Len;
+ iov.iov_base = Data;
OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
-
- error = soreceive( connection, &paddr, &uio, &mp, NULL /* SCM_RIGHTS */,
+
+ error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */,
&tcp_flags );
if( error == 0 ) {
- OS_DbgPrint(OSK_MID_TRACE,("Successful read from TCP:\n"));
- OskitDumpBuffer( m.m_data, uio.uio_resid );
+ *OutLen = Len - uio.uio_resid;
}
- *OutLen = uio.uio_resid;
return error;
}
-
-static int
-getsockaddr(namp, uaddr, len)
-/* [<][>][^][v][top][bottom][index][help] */
- struct sockaddr **namp;
-caddr_t uaddr;
-size_t len;
-{
- struct sockaddr *sa;
- int error;
- if (len > SOCK_MAXADDRLEN)
- return ENAMETOOLONG;
- MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
- error = copyin(uaddr, sa, len);
- if (error) {
- FREE(sa, M_SONAME);
- } else {
- *namp = sa;
- }
- return error;
+int OskitTCPBind( void *socket, void *connection,
+ void *nam, OSK_UINT namelen ) {
+ int error = EFAULT;
+ struct socket *so = socket;
+ struct mbuf sabuf;
+ struct sockaddr addr;
+
+ OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
+
+ if( nam )
+ addr = *((struct sockaddr *)nam);
+
+ RtlZeroMemory(&sabuf, sizeof(sabuf));
+ sabuf.m_data = (void *)&addr;
+ sabuf.m_len = sizeof(addr);
+
+ addr.sa_family = addr.sa_len;
+ addr.sa_len = sizeof(struct sockaddr);
+
+ error = sobind(so, &sabuf);
+
+ OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
+ return (error);
}
-NTSTATUS OskitTCPConnect( PVOID socket, PVOID connection,
- PVOID nam, OSK_UINT namelen ) {
+int OskitTCPConnect( void *socket, void *connection,
+ void *nam, OSK_UINT namelen ) {
struct socket *so = socket;
- struct connect_args _uap = {
- 0, nam, namelen
- }, *uap = &_uap;
- int error = EFAULT, s;
- struct mbuf sabuf = { 0 };
+ int error = EFAULT;
+ struct mbuf sabuf;
struct sockaddr addr;
OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
if( nam )
addr = *((struct sockaddr *)nam);
+ RtlZeroMemory(&sabuf, sizeof(sabuf));
sabuf.m_data = (void *)&addr;
sabuf.m_len = sizeof(addr);
-
+
addr.sa_family = addr.sa_len;
addr.sa_len = sizeof(struct sockaddr);
done:
OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
- return (error);
+ return (error);
}
-DWORD OskitTCPClose( void *socket ) {
+int OskitTCPShutdown( void *socket, int disconn_type ) {
+ return soshutdown( socket, disconn_type );
+}
+
+int OskitTCPClose( void *socket ) {
struct socket *so = socket;
so->so_connection = 0;
soclose( so );
+ return 0;
}
-int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
+int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
OSK_UINT *OutLen, OSK_UINT flags ) {
- struct mbuf mb;
- struct uio uio = { 0 };
+ struct mbuf* m = m_devget( Data, Len, 0, NULL, NULL );
int error = 0;
- OskitDumpBuffer( Data, Len );
- mb.m_data = Data;
- mb.m_len = Len;
- error = sosend( socket, NULL, &uio, (struct mbuf *)&mb, NULL, 0 );
- *OutLen = uio.uio_resid;
+ if ( !m )
+ return ENOBUFS;
+ error = sosend( socket, NULL, NULL, m, NULL, 0 );
+ *OutLen = Len;
return error;
}
-void *OskitTCPAccept( void *socket,
- void *AddrOut,
- OSK_UINT AddrLen,
- OSK_UINT *OutAddrLen ) {
- struct mbuf nam;
- int error;
+int OskitTCPAccept( void *socket,
+ void **new_socket,
+ void *AddrOut,
+ OSK_UINT AddrLen,
+ OSK_UINT *OutAddrLen,
+ OSK_UINT FinishAccepting ) {
+ struct socket *head = (void *)socket;
+ struct sockaddr *name = (struct sockaddr *)AddrOut;
+ struct socket **newso = (struct socket **)new_socket;
+ struct socket *so = socket;
+ struct sockaddr_in sa;
+ struct mbuf mnam;
+ struct inpcb *inp;
+ int namelen = 0, error = 0, s;
+
+ OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Doing accept (Finish %d)\n",
+ FinishAccepting));
+
+ *OutAddrLen = AddrLen;
+
+ if (name)
+ /* that's a copyin actually */
+ namelen = *OutAddrLen;
+
+ s = splnet();
+
+#if 0
+ if ((head->so_options & SO_ACCEPTCONN) == 0) {
+ splx(s);
+ OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: head->so_options = %x, wanted bit %x\n",
+ head->so_options, SO_ACCEPTCONN));
+ error = EINVAL;
+ goto out;
+ }
+#endif
+
+ OS_DbgPrint(OSK_MID_TRACE,("head->so_q = %x, head->so_state = %x\n",
+ head->so_q, head->so_state));
+
+ if ((head->so_state & SS_NBIO) && head->so_q == NULL) {
+ splx(s);
+ error = EWOULDBLOCK;
+ goto out;
+ }
+
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+ while (head->so_q == NULL && head->so_error == 0) {
+ if (head->so_state & SS_CANTRCVMORE) {
+ head->so_error = ECONNABORTED;
+ break;
+ }
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+ error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
+ "accept", 0);
+ if (error) {
+ splx(s);
+ goto out;
+ }
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+ }
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+
+#if 0
+ if (head->so_error) {
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+ error = head->so_error;
+ head->so_error = 0;
+ splx(s);
+ goto out;
+ }
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+#endif
- nam.m_data = AddrOut;
- nam.m_len = AddrLen;
+ /*
+ * At this point we know that there is at least one connection
+ * ready to be accepted. Remove it from the queue.
+ */
+ so = head->so_q;
- return soaccept( socket, &nam );
+ inp = so ? (struct inpcb *)so->so_pcb : NULL;
+ if( inp ) {
+ ((struct sockaddr_in *)AddrOut)->sin_addr.s_addr =
+ inp->inp_faddr.s_addr;
+ ((struct sockaddr_in *)AddrOut)->sin_port = inp->inp_fport;
+ }
+
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+ if( FinishAccepting ) {
+ head->so_q = so->so_q;
+ head->so_qlen--;
+
+ *newso = so;
+
+ /*so->so_state &= ~SS_COMP;*/
+
+ mnam.m_data = (char *)&sa;
+ mnam.m_len = sizeof(sa);
+
+ (void) soaccept(so, &mnam);
+
+ so->so_state = SS_NBIO | SS_ISCONNECTED;
+ so->so_q = so->so_q0 = NULL;
+ so->so_qlen = 0;
+ so->so_head = 0;
+
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+ if (name) {
+ /* check sa_len before it is destroyed */
+ memcpy( AddrOut, &sa, AddrLen < sizeof(sa) ? AddrLen : sizeof(sa) );
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+ *OutAddrLen = namelen; /* copyout actually */
+ }
+ OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
+ splx(s);
+ }
+out:
+ OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Returning %d\n", error));
+ return (error);
}
-void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
+/* The story so far
+ *
+ * We have a packet. While we store the fields we want in host byte order
+ * outside the original packet, the bsd stack modifies them in place.
+ */
+
+void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
OSK_UINT IpHeaderLen ) {
- struct mbuf *Ip = m_get(M_DONTWAIT, MT_DATA);
- char *NewData = malloc( Len );
+ struct mbuf *Ip = m_devget( Data, Len, 0, NULL, NULL );
+ struct ip *iph;
- OS_DbgPrint(OSK_MAX_TRACE, ("OskitTCPReceiveDatagram: %d Bytes\n", Len));
+ if( !Ip ) return; /* drop the segment */
- OskitDumpBuffer( Data, Len );
+ //memcpy( Ip->m_data, Data, Len );
+ Ip->m_pkthdr.len = IpHeaderLen;
- memset( Ip, 0, sizeof( *Ip ) );
- Ip->m_len = Len;
- Ip->m_data = NewData;
- memcpy( Ip->m_data, Data, Len );
+ /* Do the transformations on the header that tcp_input expects */
+ iph = mtod(Ip, struct ip *);
+ NTOHS(iph->ip_len);
+ iph->ip_len -= sizeof(struct ip);
+
+ OS_DbgPrint(OSK_MAX_TRACE,
+ ("OskitTCPReceiveDatagram: %d (%d header) Bytes\n", Len,
+ IpHeaderLen));
tcp_input(Ip, IpHeaderLen);
/* The buffer Ip is freed by tcp_input */
}
-void OskitTCPListen( void *socket, int backlog ) {
- return solisten( socket, backlog );
+int OskitTCPListen( void *socket, int backlog ) {
+ int error;
+
+ OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
+ error = solisten( socket, backlog );
+ OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
+
+ return error;
}
-void OskitTCPSetAddress( void *socket,
- ULONG LocalAddress,
- USHORT LocalPort,
- ULONG RemoteAddress,
- USHORT RemotePort ) {
+void OskitTCPSetAddress( void *socket,
+ OSK_UINT LocalAddress,
+ OSK_UI16 LocalPort,
+ OSK_UINT RemoteAddress,
+ OSK_UI16 RemotePort ) {
struct socket *so = socket;
- struct inpcb *inp = so->so_pcb;
+ struct inpcb *inp = (struct inpcb *)so->so_pcb;
inp->inp_laddr.s_addr = LocalAddress;
inp->inp_lport = LocalPort;
inp->inp_faddr.s_addr = RemoteAddress;
inp->inp_fport = RemotePort;
- DbgPrint("OSKIT: SET ADDR %x:%x -> %x:%x\n",
- LocalAddress, LocalPort,
- RemoteAddress, RemotePort);
}
-void OskitTCPGetAddress( void *socket,
- PULONG LocalAddress,
- PUSHORT LocalPort,
- PULONG RemoteAddress,
- PUSHORT RemotePort ) {
+void OskitTCPGetAddress( void *socket,
+ OSK_UINT *LocalAddress,
+ OSK_UI16 *LocalPort,
+ OSK_UINT *RemoteAddress,
+ OSK_UI16 *RemotePort ) {
struct socket *so = socket;
- struct inpcb *inp = so ? so->so_pcb : 0;
+ struct inpcb *inp = so ? (struct inpcb *)so->so_pcb : NULL;
if( inp ) {
*LocalAddress = inp->inp_laddr.s_addr;
*LocalPort = inp->inp_lport;
*RemoteAddress = inp->inp_faddr.s_addr;
*RemotePort = inp->inp_fport;
- DbgPrint("OSKIT: GET ADDR %x:%x -> %x:%x\n",
- *LocalAddress, *LocalPort,
- *RemoteAddress, *RemotePort);
}
}
+struct ifaddr *ifa_iffind(struct sockaddr *addr, int type)
+{
+ if( OtcpEvent.FindInterface )
+ return OtcpEvent.FindInterface( OtcpEvent.ClientData,
+ PF_INET,
+ type,
+ addr );
+ else
+ return NULL;
+}
+
void oskittcp_die( const char *file, int line ) {
DbgPrint("\n\n*** OSKITTCP: Panic Called at %s:%d ***\n", file, line);
- KeBugCheck(0);
+ *((int *)0) = 0;
+}
+
+/* Stuff supporting the BSD network-interface interface */
+struct ifaddr **ifnet_addrs;
+struct ifnet *ifnet;
+
+void
+ifinit()
+{
+}
+
+
+void
+if_attach(ifp)
+ struct ifnet *ifp;
+{
+ panic("if_attach\n");
+}
+
+struct ifnet *
+ifunit(char *name)
+{
+ return 0;
+}
+
+/*
+ * Handle interface watchdog timer routines. Called
+ * from softclock, we decrement timers (if set) and
+ * call the appropriate interface routine on expiration.
+ */
+void
+if_slowtimo(arg)
+ void *arg;
+{
+#if 0
+ register struct ifnet *ifp;
+ int s = splimp();
+
+ for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+ if (ifp->if_timer == 0 || --ifp->if_timer)
+ continue;
+ if (ifp->if_watchdog)
+ (*ifp->if_watchdog)(ifp->if_unit);
+ }
+ splx(s);
+ timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
+#endif
+}
+
+/*
+ * Locate an interface based on a complete address.
+ */
+
+/*ARGSUSED*/
+struct ifaddr *ifa_ifwithaddr(addr)
+ struct sockaddr *addr;
+{
+ struct ifaddr *ifaddr = ifa_ifwithnet( addr );
+ struct sockaddr_in *addr_in;
+ struct sockaddr_in *faddr_in;
+
+ if( !ifaddr ) {
+ OS_DbgPrint(OSK_MID_TRACE,("No ifaddr\n"));
+ return NULL;
+ } else {
+ OS_DbgPrint(OSK_MID_TRACE,("ifaddr @ %x\n", ifaddr));
+ }
+
+ addr_in = (struct sockaddr_in *)addr;
+ faddr_in = (struct sockaddr_in *)ifaddr->ifa_addr;
+
+ if( faddr_in->sin_addr.s_addr == addr_in->sin_addr.s_addr )
+ return ifaddr;
+ else
+ return NULL;
+}
+
+/*
+ * Locate the point to point interface with a given destination address.
+ */
+/*ARGSUSED*/
+struct ifaddr *
+ifa_ifwithdstaddr(addr)
+ register struct sockaddr *addr;
+{
+ OS_DbgPrint(OSK_MID_TRACE,("Called\n"));
+ return ifa_iffind(addr, IFF_POINTOPOINT);
+}
+
+/*
+ * Find an interface on a specific network. If many, choice
+ * is most specific found.
+ */
+struct ifaddr *ifa_ifwithnet(addr)
+ struct sockaddr *addr;
+{
+ struct sockaddr_in *sin;
+ struct ifaddr *ifaddr = ifa_iffind(addr, IFF_UNICAST);
+
+ if( ifaddr )
+ {
+ sin = (struct sockaddr_in *)&ifaddr->ifa_addr;
+
+ OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n",
+ sin->sin_addr.s_addr));
+ }
+
+ return ifaddr;
}