sosend( ) will not process mbuf if you pass it a uio (according to arty)
[reactos.git] / reactos / drivers / lib / oskittcp / oskittcp / interface.c
index 08ef28f..21af3a3 100644 (file)
@@ -1,6 +1,5 @@
 #include <oskittcp.h>
 #include <oskitdebug.h>
-#include <ntddk.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/socket.h>
@@ -27,8 +26,28 @@ unsigned net_imask;
 unsigned volatile ipending;
 struct timeval boottime;
 
+void *fbsd_malloc( unsigned int bytes, const char *file, int line, ... ) {
+    if( !OtcpEvent.TCPMalloc ) panic("no malloc");
+    return OtcpEvent.TCPMalloc
+       ( OtcpEvent.ClientData,
+         (OSK_UINT)bytes, (OSK_PCHAR)file, (OSK_UINT)line );
+}
+
+void fbsd_free( void *data, const char *file, int line, ... ) {
+    if( !OtcpEvent.TCPFree ) panic("no free");
+    OtcpEvent.TCPFree( OtcpEvent.ClientData,
+                   data, (OSK_PCHAR)file, (OSK_UINT)line );
+}
+
 void InitOskitTCP() {
     OS_DbgPrint(OSK_MID_TRACE,("Init Called\n"));
+    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 fake freebsd scheduling\n"));
     init_freebsd_sched();
     OS_DbgPrint(OSK_MID_TRACE,("Init clock\n"));
@@ -47,6 +66,7 @@ void DeinitOskitTCP() {
 
 void TimerOskitTCP() {
     tcp_slowtimo();
+    tcp_fasttimo();
 }
 
 void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
@@ -54,9 +74,6 @@ void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
     if( OtcpEvent.PacketSend ) 
        OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n",
                                   OtcpEvent.PacketSend));
-    if( OtcpEvent.Bind )
-       OS_DbgPrint(OSK_MID_TRACE,("Bind handler registered: %x\n",
-                                  OtcpEvent.Bind));
 }
 
 void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len ) {
@@ -64,7 +81,7 @@ void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len ) {
     
     for( i = 0; i < Len; i++ ) {
        if( i && !(i & 0xf) ) DbgPrint( "\n" );
-       if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
+       if( !(i & 0xf) ) DbgPrint( "%08x: ", (OSK_UINT)(Data + i) );
        DbgPrint( " %02x", Data[i] );
     }
     DbgPrint("\n");
@@ -82,45 +99,49 @@ int OskitTCPSocket( void *context,
     int error = socreate(domain, &so, type, proto);
     if( !error ) {
        so->so_connection = context;
+       so->so_state = SS_NBIO;
        *aso = so;
     }
     return error;
-#if 0
-    register struct protosw *prp;
-    register struct socket *so;
-    register int error;
+}
 
-    if (proto) {
-       prp = pffindproto(domain, proto, type);
-    } else {
-       prp = pffindtype(domain, type);
-    }
-    if (prp == 0 || prp->pr_usrreq == 0) {
-       return (EPROTONOSUPPORT);
-    }
-    if (prp->pr_type != type) {
-       return (EPROTOTYPE);
+int OskitTCPRecv( void *connection,
+                 OSK_PCHAR Data,
+                 OSK_UINT Len,
+                 OSK_UINT *OutLen,
+                 OSK_UINT Flags ) {
+    struct mbuf *paddr = 0;
+    struct mbuf m, *mp;
+    struct uio uio = { 0 };
+    int error = 0;
+    int tcp_flags = 0;
+
+    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;
+
+    OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
+       
+    error = soreceive( connection, &paddr, &uio, &mp, 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 );
     }
-    MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT);
-    bzero((caddr_t)so, sizeof(*so));
-    so->so_type = type;
-    so->so_proto = prp;
-    error =
-       (*prp->pr_usrreq)(so, PRU_ATTACH,
-                         (struct mbuf *)0, 
-                         (struct mbuf *)proto, 
-                         (struct mbuf *)0);
-    if (error) {
-       so->so_state |= SS_NOFDREF;
-       sofree(so);
-       return (error);
-    }
-    *aso = so;
-    OS_DbgPrint(OSK_MAX_TRACE,("Returning Socket %x\n", so));
-    return STATUS_SUCCESS;
-#endif
-}
 
+    *OutLen = uio.uio_resid;
+    return error;
+}
+                 
 static int
 getsockaddr(namp, uaddr, len)
 /* [<][>][^][v][top][bottom][index][help] */
@@ -143,8 +164,34 @@ size_t len;
     return error;
 }
 
-NTSTATUS OskitTCPConnect( PVOID socket, PVOID connection, 
-                         PVOID nam, OSK_UINT namelen ) {
+int OskitTCPBind( void *socket, void *connection,
+                 void *nam, OSK_UINT namelen ) {
+    int error = EFAULT;
+    struct socket *so = socket;
+    struct mbuf sabuf = { 0 };
+    struct sockaddr addr;
+
+    OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
+
+    if( nam )
+       addr = *((struct sockaddr *)nam);
+
+    sabuf.m_data = (void *)&addr;
+    sabuf.m_len = sizeof(addr);
+    
+    addr.sa_family = addr.sa_len;
+    addr.sa_len = sizeof(struct sockaddr);
+
+    OskitDumpBuffer( (OSK_PCHAR)&addr, sizeof(addr) );
+
+    error = sobind(so, &sabuf);
+
+    OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
+    return (error);    
+}
+
+int OskitTCPConnect( void *socket, void *connection, 
+                    void *nam, OSK_UINT namelen ) {
     struct socket *so = socket;
     struct connect_args _uap = {
        0, nam, namelen
@@ -182,22 +229,6 @@ NTSTATUS OskitTCPConnect( PVOID socket, PVOID connection,
        goto done;
     }
 
-    s = splnet();
-
-    while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
-       error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
-                      "connect", 0);
-       if (error)
-           break;
-    }
-
-    if (error == 0) {
-       error = so->so_error;
-       so->so_error = 0;
-    }
-
-    splx(s);
-
 bad:
     so->so_state &= ~SS_ISCONNECTING;
 
@@ -209,54 +240,83 @@ done:
     return (error);    
 }
 
-DWORD OskitTCPClose( VOID *socket ) {
+int OskitTCPClose( void *socket ) {
+    struct socket *so = socket;
+    so->so_connection = 0;
+    soclose( so );
+    return 0;
 }
 
-DWORD OskitTCPSend( VOID *socket, OSK_PCHAR Data, OSK_UINT Len, int flags ) {
-    OskitDumpBuffer( Data, Len );
+int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len, 
+                 OSK_UINT *OutLen, OSK_UINT flags ) {
     struct mbuf mb;
+    /*struct uio uio = { 0 };*/
+    int error = 0;
+    OskitDumpBuffer( Data, Len );
+    /*uio.uio_resid = Len;*/
     mb.m_data = Data;
     mb.m_len  = Len;
-    return sosend( socket, NULL, NULL, (struct mbuf *)&mb, NULL, 0 );
+    mb.m_flags = M_EOR;
+    error = sosend( socket, NULL, NULL /*&uio*/, (struct mbuf *)&mb, NULL, 0 );
+    /*printf("uio.uio_resid = %d\n", uio.uio_resid);*/
+    *OutLen = Len /*uio.uio_resid*/;
+    return error;
 }
 
-void OskitTCPReceive( VOID *socket, PVOID AddrOut, 
-                     OSK_PCHAR Data, OSK_UINT Len, OSK_UINT *OutLen ) {
-}
+int OskitTCPAccept( void *socket, 
+                   void *AddrOut, 
+                   OSK_UINT AddrLen,
+                   OSK_UINT *OutAddrLen ) {
+    struct mbuf nam;
+    int error;
 
-VOID *OskitTCPAccept( VOID *socket, PVOID AddrOut ) {
+    nam.m_data = AddrOut;
+    nam.m_len  = AddrLen;
+
+    return soaccept( socket, &nam );
 }
 
+/* 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;
+    
+    if( !Ip ) return; /* drop the segment */
 
-    OS_DbgPrint(OSK_MAX_TRACE, ("OskitTCPReceiveDatagram: %d Bytes\n", Len));
+    memcpy( Ip->m_data, Data, Len );
+    Ip->m_pkthdr.len = IpHeaderLen;
 
-    OskitDumpBuffer( 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);
 
-    memset( Ip, 0, sizeof( *Ip ) );
-    Ip->m_len = Len;
-    Ip->m_data = NewData;
-    memcpy( Ip->m_data, Data, Len );
+    OS_DbgPrint(OSK_MAX_TRACE, 
+               ("OskitTCPReceiveDatagram: %d (%d header) Bytes\n", Len,
+                IpHeaderLen));
+
+    OskitDumpBuffer( Data, Len );
 
     tcp_input(Ip, IpHeaderLen);
 
     /* The buffer Ip is freed by tcp_input */
 }
 
-void OskitTCPBind( VOID *socket, PVOID name ) {
-}
-
-void OskitTCPListen( VOID *socket, int backlog ) {
+int OskitTCPListen( void *socket, int backlog ) {
+    return solisten( socket, backlog );
 }
 
-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;
     inp->inp_laddr.s_addr = LocalAddress;
@@ -268,11 +328,11 @@ void OskitTCPSetAddress( VOID *socket,
             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;
     if( inp ) {
@@ -286,7 +346,123 @@ void OskitTCPGetAddress( VOID *socket,
     }
 }
 
+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);
+
+    sin = (struct sockaddr *)&ifaddr->ifa_addr;
+
+    OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n", sin->sin_addr.s_addr));
+
+    return ifaddr;
+}
+