This is a merge onto head of the last two months worth of changes to the

networking code.

There is individual change info on the branch arty_20040329.

Here is a summary of what changed:

tcpip:

- Added a mostly working transport/tcp branch based on oskittcp
  (checked in at drivers/lib/oskittcp).  This code shares almost nothing
  with the previous version.

- Regularized IRP handling

- Fixed ownership of buffers throughout tcpip.sys.  Buffers are now
  required to be copied in a few more cases, but everybody can call
  anybody else and not have to worry about keeping a buffer alive
  for any specific reason.

- Also moved lots more operations onto the stack (small datastructures
  and pointers).  This will result in a further simplification of the
  code here.

- Made each completion routine solely responsible for freeing memory
  from the corresponding action.

- Removed reference counted small address structures in favor if inlines

- Changed and clarified ownership rules almost everwhere

- Fixed a few more type punning style errors

- Added more info used by iphlpapi

- Added some memory tracing stuff

ndis:

- Fixed one or two type punning errors

ws2_32:

- Added getservbyname and getprotobyname (partial)

oskittcp:

- Diagnostics everywhere

- Eliminated dependence on raw_ip input

- Simplified buffering and signalling model a bit

- Added memory checking as in tcpip

- more to come

svn path=/trunk/; revision=9647
This commit is contained in:
Art Yerkes 2004-06-09 18:11:39 +00:00
parent 25e4bf3404
commit c1d0686eaa
77 changed files with 3363 additions and 15749 deletions

View file

@ -97,8 +97,7 @@ struct inpcb *
in_pcblookuphash __P((struct inpcbinfo *, in_pcblookuphash __P((struct inpcbinfo *,
struct in_addr, u_int, struct in_addr, u_int)); struct in_addr, u_int, struct in_addr, u_int));
void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *, void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int))); u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));void in_pcbrehash __P((struct inpcb *));
void in_pcbrehash __P((struct inpcb *));
void in_rtchange __P((struct inpcb *, int)); void in_rtchange __P((struct inpcb *, int));
void in_setpeeraddr __P((struct inpcb *, struct mbuf *)); void in_setpeeraddr __P((struct inpcb *, struct mbuf *));
void in_setsockaddr __P((struct inpcb *, struct mbuf *)); void in_setsockaddr __P((struct inpcb *, struct mbuf *));

View file

@ -351,7 +351,7 @@ union mcluster {
if ((m)->m_flags & M_EXT) { \ if ((m)->m_flags & M_EXT) { \
MCLFREE((m)->m_ext.ext_buf); \ MCLFREE((m)->m_ext.ext_buf); \
} \ } \
(nn) = (m)->m_next; \ /* (nn) = (m)->m_next; */ \
FREE((m), mbtypes[(m)->m_type]); \ FREE((m), mbtypes[(m)->m_type]); \
} }
#endif /* OSKIT */ #endif /* OSKIT */

View file

@ -62,6 +62,7 @@
#include <sys/rtprio.h> /* For struct rtprio. */ #include <sys/rtprio.h> /* For struct rtprio. */
#include <sys/select.h> /* For struct selinfo. */ #include <sys/select.h> /* For struct selinfo. */
#include <sys/time.h> /* For structs itimerval, timeval. */ #include <sys/time.h> /* For structs itimerval, timeval. */
#include <sys/socketvar.h>
#ifdef OSKIT #ifdef OSKIT
#include <oskit/dev/dev.h> #include <oskit/dev/dev.h>
@ -319,7 +320,7 @@ void cpu_switch __P((struct proc *));
void sleep __P((void *chan, int pri)); void sleep __P((void *chan, int pri));
int tsleep __P((void *chan, int pri, char *wmesg, int timo)); int tsleep __P((void *chan, int pri, char *wmesg, int timo));
void unsleep __P((struct proc *)); void unsleep __P((struct proc *));
void wakeup __P((void *chan)); void wakeup __P((struct socket *so, struct selinfo *si, void *chan));
__dead void cpu_exit __P((struct proc *)) __dead2; __dead void cpu_exit __P((struct proc *)) __dead2;
__dead void exit1 __P((struct proc *, int)) __dead2; __dead void exit1 __P((struct proc *, int)) __dead2;

View file

@ -181,11 +181,11 @@ struct socket {
((sb)->sb_flags |= SB_LOCK), 0) ((sb)->sb_flags |= SB_LOCK), 0)
/* release lock on sockbuf sb */ /* release lock on sockbuf sb */
#define sbunlock(sb) { \ #define sbunlock(so, sb) { \
(sb)->sb_flags &= ~SB_LOCK; \ (sb)->sb_flags &= ~SB_LOCK; \
if ((sb)->sb_flags & SB_WANT) { \ if ((sb)->sb_flags & SB_WANT) { \
(sb)->sb_flags &= ~SB_WANT; \ (sb)->sb_flags &= ~SB_WANT; \
wakeup((caddr_t)&(sb)->sb_flags); \ wakeup(so, &(sb)->sb_sel, (caddr_t)&(sb)->sb_flags); \
} \ } \
} }
@ -195,6 +195,7 @@ struct socket {
} }
#define sowwakeup(so) sowakeup((so), &(so)->so_snd) #define sowwakeup(so) sowakeup((so), &(so)->so_snd)
#define socwakeup(so) sowakeup((so), &(so)->so_snd)
#ifdef KERNEL #ifdef KERNEL
extern u_long sb_max; extern u_long sb_max;

View file

@ -68,6 +68,11 @@ static inline VOID ExFreePoolX( PVOID Data, PCHAR File, ULONG Line ) {
#define Untrack(x) #define Untrack(x)
#define TrackTag(x) #define TrackTag(x)
#define FreeNdisPacket FreeNdisPacketX #define FreeNdisPacket FreeNdisPacketX
#define exFreePool(x) ExFreePool(x)
#define exAllocatePool(x,y) ExAllocatePool(x,y)
#define exAllocatePoolWithTag(x,y,z) ExAllocatePoolWithTag(x,y,z)
#define TrackWithTag(a,b,c,d)
#define UntrackFL(a,b,c)
#endif #endif
#endif/*MEMMTRAC_H*/ #endif/*MEMMTRAC_H*/

View file

@ -51,7 +51,7 @@ extern int errno; /* global error number */
#define OSK_ENOENT 2 /* No such file or directory */ #define OSK_ENOENT 2 /* No such file or directory */
#define OSK_ESRCH 3 /* No such process */ #define OSK_ESRCH 3 /* No such process */
#define OSK_EINTR 4 /* Interrupted system call */ #define OSK_EINTR 4 /* Interrupted system call */
#define OSK_EIO 5 /* Input/output error */ #define OSK_EIO 5 /* Input/output error */
#define OSK_ENXIO 6 /* Device not configured */ #define OSK_ENXIO 6 /* Device not configured */
#define OSK_E2BIG 7 /* Argument list too long */ #define OSK_E2BIG 7 /* Argument list too long */
#define OSK_ENOEXEC 8 /* Exec format error */ #define OSK_ENOEXEC 8 /* Exec format error */

View file

@ -39,46 +39,34 @@ struct connect_args {
#include <oskittypes.h> #include <oskittypes.h>
#define IPHDR_SIZE 20 #define IPHDR_SIZE 20
#define SEL_CONNECT 1
#define SEL_FIN 2
#define SEL_RST 4
#define SEL_ABRT 8
#define SEL_READ 16
#define SEL_WRITE 32
#define SEL_ACCEPT 64
#define SEL_OOB 128
#define SEL_ERROR 256
#define SEL_FINOUT 512
typedef void (*OSKITTCP_SOCKET_DATA_AVAILABLE) typedef void (*OSKITTCP_SOCKET_STATE)
( void *ClientData, ( void *ClientData,
void *WhichSocket, void *WhichSocket,
void *WhichConnection, void *WhichConnection,
OSK_PCHAR Data, OSK_UINT SelFlags,
OSK_UINT Len ); OSK_UINT SocketState );
typedef void (*OSKITTCP_SOCKET_CONNECT_INDICATION)
( void *ClientData,
void *WhichSocket,
void *WhichConnection );
typedef void (*OSKITTCP_SOCKET_CLOSE_INDICATION)
( void *WhichSocket );
typedef void (*OSKITTCP_SOCKET_PENDING_CONNECT_INDICATION)
( void *WhichSocket );
typedef void (*OSKITTCP_SOCKET_RESET_INDICATION)
( void *WhichSocket );
typedef int (*OSKITTCP_SEND_PACKET) typedef int (*OSKITTCP_SEND_PACKET)
( void *ClientData, ( void *ClientData,
void *WhichSocket, void *WhichSocket,
void *WhichConnection, void *WhichConnection,
OSK_PCHAR Data, OSK_PCHAR Data,
OSK_UINT Len ); OSK_UINT Len );
typedef int (*OSKITTCP_NEED_BIND)
( void *ClientData,
void *WhichSocket,
void *WhichConnection,
struct sockaddr *address,
OSK_UINT addrlen,
OSK_UINT reuseport );
typedef struct _OSKITTCP_EVENT_HANDLERS { typedef struct _OSKITTCP_EVENT_HANDLERS {
void *ClientData; void *ClientData;
OSKITTCP_SOCKET_DATA_AVAILABLE SocketDataAvailable; OSKITTCP_SOCKET_STATE SocketState;
OSKITTCP_SOCKET_CONNECT_INDICATION SocketConnectIndication;
OSKITTCP_SOCKET_CLOSE_INDICATION SocketCloseIndication;
OSKITTCP_SOCKET_PENDING_CONNECT_INDICATION SocketPendingConnectIndication;
OSKITTCP_SOCKET_RESET_INDICATION SocketResetIndication;
OSKITTCP_SEND_PACKET PacketSend; OSKITTCP_SEND_PACKET PacketSend;
OSKITTCP_NEED_BIND Bind;
} OSKITTCP_EVENT_HANDLERS, *POSKITTCP_EVENT_HANDLERS; } OSKITTCP_EVENT_HANDLERS, *POSKITTCP_EVENT_HANDLERS;
extern OSKITTCP_EVENT_HANDLERS OtcpEvent; extern OSKITTCP_EVENT_HANDLERS OtcpEvent;
@ -92,7 +80,12 @@ extern void RegisterOskitTCPEventHandlers
( POSKITTCP_EVENT_HANDLERS EventHandlers ); ( POSKITTCP_EVENT_HANDLERS EventHandlers );
extern void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len, extern void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
OSK_UINT IpHeaderLen ); OSK_UINT IpHeaderLen );
extern int OskitTCPReceive( void *socket,
void *Addr,
OSK_PCHAR Data,
OSK_UINT Len,
OSK_UINT *OutLen,
OSK_UINT Flags );
#undef errno #undef errno
#define malloc(x,...) fbsd_malloc(x,__FILE__,__LINE__) #define malloc(x,...) fbsd_malloc(x,__FILE__,__LINE__)
@ -103,4 +96,8 @@ extern void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
#define SOCK_MAXADDRLEN 255 #define SOCK_MAXADDRLEN 255
#define OSK_MSG_OOB 0x01
#define OSK_MSG_PEEK 0x02
#define OSK_MSG_DONTWAIT 0x80
#endif/*OSKITTCP_H*/ #endif/*OSKITTCP_H*/

View file

@ -64,38 +64,6 @@ struct multi_kludge {
struct in_multihead mk_head; struct in_multihead mk_head;
}; };
/*
* Return the network number from an internet address.
*/
u_long
in_netof(in)
struct in_addr in;
{
register u_long i = ntohl(in.s_addr);
register u_long net;
register struct in_ifaddr *ia;
if (IN_CLASSA(i))
net = i & IN_CLASSA_NET;
else if (IN_CLASSB(i))
net = i & IN_CLASSB_NET;
else if (IN_CLASSC(i))
net = i & IN_CLASSC_NET;
else if (IN_CLASSD(i))
net = i & IN_CLASSD_NET;
else
return (0);
/*
* Check whether network is a subnet;
* if so, return subnet number.
*/
for (ia = in_ifaddr; ia; ia = ia->ia_next)
if (net == ia->ia_net)
return (i & ia->ia_subnetmask);
return (net);
}
#ifndef SUBNETSARELOCAL #ifndef SUBNETSARELOCAL
#define SUBNETSARELOCAL 1 #define SUBNETSARELOCAL 1
#endif #endif

View file

@ -54,9 +54,6 @@ void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
if( OtcpEvent.PacketSend ) if( OtcpEvent.PacketSend )
OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n", OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n",
OtcpEvent.PacketSend)); 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 ) { void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len ) {
@ -85,42 +82,49 @@ int OskitTCPSocket( void *context,
*aso = so; *aso = so;
} }
return error; 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);
}
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
} }
int OskitTCPRecv( void *connection,
void *Addr,
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 );
}
if( paddr )
memcpy( Addr, paddr, min(sizeof(struct sockaddr),paddr->m_len) );
*OutLen = uio.uio_resid;
return error;
}
static int static int
getsockaddr(namp, uaddr, len) getsockaddr(namp, uaddr, len)
/* [<][>][^][v][top][bottom][index][help] */ /* [<][>][^][v][top][bottom][index][help] */
@ -209,10 +213,13 @@ done:
return (error); return (error);
} }
DWORD OskitTCPClose( VOID *socket ) { DWORD OskitTCPClose( void *socket ) {
struct socket *so = socket;
so->so_connection = 0;
soclose( so );
} }
DWORD OskitTCPSend( VOID *socket, OSK_PCHAR Data, OSK_UINT Len, int flags ) { DWORD OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len, int flags ) {
OskitDumpBuffer( Data, Len ); OskitDumpBuffer( Data, Len );
struct mbuf mb; struct mbuf mb;
mb.m_data = Data; mb.m_data = Data;
@ -220,11 +227,17 @@ DWORD OskitTCPSend( VOID *socket, OSK_PCHAR Data, OSK_UINT Len, int flags ) {
return sosend( socket, NULL, NULL, (struct mbuf *)&mb, NULL, 0 ); return sosend( socket, NULL, NULL, (struct mbuf *)&mb, NULL, 0 );
} }
void OskitTCPReceive( VOID *socket, PVOID AddrOut, void *OskitTCPAccept( void *socket,
OSK_PCHAR Data, OSK_UINT Len, OSK_UINT *OutLen ) { 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 );
} }
void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len, void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
@ -246,13 +259,11 @@ void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
/* The buffer Ip is freed by tcp_input */ /* The buffer Ip is freed by tcp_input */
} }
void OskitTCPBind( VOID *socket, PVOID name ) { void OskitTCPListen( void *socket, int backlog ) {
return solisten( socket, backlog );
} }
void OskitTCPListen( VOID *socket, int backlog ) { void OskitTCPSetAddress( void *socket,
}
void OskitTCPSetAddress( VOID *socket,
ULONG LocalAddress, ULONG LocalAddress,
USHORT LocalPort, USHORT LocalPort,
ULONG RemoteAddress, ULONG RemoteAddress,
@ -268,7 +279,7 @@ void OskitTCPSetAddress( VOID *socket,
RemoteAddress, RemotePort); RemoteAddress, RemotePort);
} }
void OskitTCPGetAddress( VOID *socket, void OskitTCPGetAddress( void *socket,
PULONG LocalAddress, PULONG LocalAddress,
PUSHORT LocalPort, PUSHORT LocalPort,
PULONG RemoteAddress, PULONG RemoteAddress,
@ -290,3 +301,4 @@ void oskittcp_die( const char *file, int line ) {
DbgPrint("\n\n*** OSKITTCP: Panic Called at %s:%d ***\n", file, line); DbgPrint("\n\n*** OSKITTCP: Panic Called at %s:%d ***\n", file, line);
KeBugCheck(0); KeBugCheck(0);
} }

View file

@ -132,47 +132,11 @@ ip_output(so, m0, opt, ro, flags, imo)
m->m_data + IPHDR_SIZE, m->m_len - IPHDR_SIZE ); m->m_data + IPHDR_SIZE, m->m_len - IPHDR_SIZE );
} }
OS_DbgPrint(OSK_MID_TRACE,("Error from upper layer: %d\n", error));
return (error); return (error);
} }
/*
* Copy options from ip to jp,
* omitting those not copied during fragmentation.
*/
int
ip_optcopy(ip, jp)
struct ip *ip, *jp;
{
register u_char *cp, *dp;
int opt, optlen, cnt;
cp = (u_char *)(ip + 1);
dp = (u_char *)(jp + 1);
cnt = (ip->ip_hl << 2) - sizeof (struct ip);
for (; cnt > 0; cnt -= optlen, cp += optlen) {
opt = cp[0];
if (opt == IPOPT_EOL)
break;
if (opt == IPOPT_NOP) {
/* Preserve for IP mcast tunnel's LSRR alignment. */
*dp++ = IPOPT_NOP;
optlen = 1;
continue;
} else
optlen = cp[IPOPT_OLEN];
/* bogus lengths should have been caught by ip_dooptions */
if (optlen > cnt)
optlen = cnt;
if (IPOPT_COPIED(opt)) {
(void)memcpy(dp, cp, (unsigned)optlen);
dp += optlen;
}
}
for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
*dp++ = IPOPT_EOL;
return (optlen);
}
/* /*
* IP socket option processing. * IP socket option processing.
*/ */

View file

@ -139,59 +139,6 @@ int ticks;
volatile struct timeval time; volatile struct timeval time;
volatile struct timeval mono_time; volatile struct timeval mono_time;
/*
* The real-time timer, interrupting hz times per second.
*/
void bsd_hardclock(void)
{
register struct callout *p1;
register int needsoft;
unsigned cpl;
int s;
save_cpl(&cpl);
splhigh();
/*
* Update real-time timeout queue.
* At front of queue are some number of events which are ``due''.
* The time to these is <= 0 and if negative represents the
* number of ticks which have passed since it was supposed to happen.
* The rest of the q elements (times > 0) are events yet to happen,
* where the time for each is given as a delta from the previous.
* Decrementing just the first of these serves to decrement the time
* to all events.
*/
needsoft = 0;
for (p1 = calltodo.c_next; p1 != NULL; p1 = p1->c_next) {
if (--p1->c_time > 0)
break;
needsoft = 1;
if (p1->c_time == 0)
break;
}
/*
* Increment the time-of-day.
*/
ticks++;
BUMPTIME(&mono_time, tick);
BUMPTIME(&time, tick);
/*
* At this point, we might need a soft interrupt. We say, what the
* heck, let's do the work now. Reduce priority level to softclock
* first, though. The alternative (postponing it) would be called
* 'setsoftclock'
*/
if (needsoft) {
(void)splsoftclock();
softclock();
}
restore_cpl(cpl);
}
/* /*
* Software (low priority) clock interrupt. * Software (low priority) clock interrupt.
* Run periodic events from timeout queue. * Run periodic events from timeout queue.

View file

@ -12,18 +12,18 @@ typedef struct _SLEEPING_THREAD {
} SLEEPING_THREAD, *PSLEEPING_THREAD; } SLEEPING_THREAD, *PSLEEPING_THREAD;
LIST_ENTRY SleepingThreadsList; LIST_ENTRY SleepingThreadsList;
KSPIN_LOCK SleepingThreadsLock; FAST_MUTEX SleepingThreadsLock;
/* clock_init */ /* clock_init */
int ncallout = 256; int ncallout = 256;
struct callout *callout; struct callout *callout;
void init_freebsd_sched() { void init_freebsd_sched() {
KeInitializeSpinLock( &SleepingThreadsLock ); ExInitializeFastMutex( &SleepingThreadsLock );
InitializeListHead( &SleepingThreadsList ); InitializeListHead( &SleepingThreadsList );
} }
void tsleep( void *token, int priority, char *wmesg, int tmio ) { int tsleep( void *token, int priority, char *wmesg, int tmio ) {
KIRQL OldIrql; KIRQL OldIrql;
KEVENT Event; KEVENT Event;
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
@ -37,43 +37,65 @@ void tsleep( void *token, int priority, char *wmesg, int tmio ) {
if( SleepingThread ) { if( SleepingThread ) {
KeInitializeEvent( &SleepingThread->Event, NotificationEvent, FALSE ); KeInitializeEvent( &SleepingThread->Event, NotificationEvent, FALSE );
SleepingThread->SleepToken = token; SleepingThread->SleepToken = token;
ExInterlockedInsertTailList( &SleepingThreadsList,
&SleepingThread->Entry,
&SleepingThreadsLock );
}
OS_DbgPrint(OSK_MID_TRACE,("Waiting on %x\n", token)); ExAcquireFastMutex( &SleepingThreadsLock );
KeWaitForSingleObject( &SleepingThread->Event, InsertTailList( &SleepingThreadsList, &SleepingThread->Entry );
WrSuspended, ExReleaseFastMutex( &SleepingThreadsLock );
KernelMode,
TRUE, OS_DbgPrint(OSK_MID_TRACE,("Waiting on %x\n", token));
NULL ); KeWaitForSingleObject( &SleepingThread->Event,
WrSuspended,
KernelMode,
TRUE,
NULL );
ExAcquireFastMutex( &SleepingThreadsLock );
RemoveEntryList( &SleepingThread->Entry );
ExReleaseFastMutex( &SleepingThreadsLock );
ExFreePool( SleepingThread );
}
OS_DbgPrint(OSK_MID_TRACE,("Waiting finished: %x\n", token)); OS_DbgPrint(OSK_MID_TRACE,("Waiting finished: %x\n", token));
return 0;
} }
void wakeup( void *token ) { void wakeup( struct socket *so, struct selinfo *si, void *token ) {
KIRQL OldIrql; KIRQL OldIrql;
KEVENT Event; KEVENT Event;
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
PSLEEPING_THREAD SleepingThread; PSLEEPING_THREAD SleepingThread;
OS_DbgPrint(OSK_MID_TRACE,("Wakeup %x!\n",token));
KeAcquireSpinLock( &SleepingThreadsLock, &OldIrql ); OS_DbgPrint
(OSK_MID_TRACE,("XXX Bytes to receive: %d\n", so->so_rcv.sb_cc));
if( so->so_rcv.sb_cc && si )
si->si_flags |= SEL_READ;
OS_DbgPrint(OSK_MID_TRACE,("Wakeup %x (socket %x, si_flags %x, state %x)!\n",
token, so, si ? si->si_flags : 0,
so->so_state));
if( OtcpEvent.SocketState ) {
OS_DbgPrint(OSK_MID_TRACE,("Calling client's socket state fn\n"));
OtcpEvent.SocketState( OtcpEvent.ClientData,
so,
so->so_connection,
si ? si->si_flags : 0,
so->so_state );
}
ExAcquireFastMutex( &SleepingThreadsLock );
Entry = SleepingThreadsList.Flink; Entry = SleepingThreadsList.Flink;
while( Entry != &SleepingThreadsList ) { while( Entry != &SleepingThreadsList ) {
SleepingThread = CONTAINING_RECORD(Entry, SLEEPING_THREAD, Entry); SleepingThread = CONTAINING_RECORD(Entry, SLEEPING_THREAD, Entry);
OS_DbgPrint(OSK_MID_TRACE,("Sleeper @ %x\n", SleepingThread));
if( SleepingThread->SleepToken == token ) { if( SleepingThread->SleepToken == token ) {
RemoveEntryList(Entry);
KeReleaseSpinLock( &SleepingThreadsLock, OldIrql );
OS_DbgPrint(OSK_MID_TRACE,("Setting event to wake %x\n", token)); OS_DbgPrint(OSK_MID_TRACE,("Setting event to wake %x\n", token));
KeSetEvent( &SleepingThread->Event, IO_NO_INCREMENT, FALSE ); KeSetEvent( &SleepingThread->Event, IO_NETWORK_INCREMENT, FALSE );
ExFreePool( SleepingThread );
return;
} }
Entry = Entry->Flink; Entry = Entry->Flink;
} }
KeReleaseSpinLock( &SleepingThreadsLock, OldIrql ); ExReleaseFastMutex( &SleepingThreadsLock );
OS_DbgPrint(OSK_MID_TRACE,("Wakeup done %x\n", token)); OS_DbgPrint(OSK_MID_TRACE,("Wakeup done %x\n", token));
} }
@ -142,32 +164,6 @@ static __inline int name(void) \
return (x); \ return (x); \
} }
#if 0
GENSPL(splbio, cpl |= bio_imask)
GENSPL(splclock, cpl = HWI_MASK | SWI_MASK)
GENSPL(splhigh, cpl = HWI_MASK | SWI_MASK)
GENSPL(splimp, cpl |= net_imask)
GENSPL(splnet, cpl |= SWI_NET_MASK)
GENSPL(splsoftclock, cpl = SWI_CLOCK_MASK)
GENSPL(splsofttty, cpl |= SWI_TTY_MASK)
GENSPL(splstatclock, cpl |= stat_imask)
GENSPL(spltty, cpl |= tty_imask)
#endif
#if 0
void spl0(void) {
cpl = SWI_AST_MASK;
if (ipending & ~SWI_AST_MASK)
splz();
}
void splx(int ipl) {
cpl = ipl;
if (ipending & ~ipl)
splz();
}
#endif
void splz(void) { void splz(void) {
OS_DbgPrint(OSK_MID_TRACE,("Called SPLZ\n")); OS_DbgPrint(OSK_MID_TRACE,("Called SPLZ\n"));
} }
@ -184,26 +180,3 @@ void restore_cpl(unsigned x)
{ {
cpl = x; cpl = x;
} }
void selrecord( struct proc *selector, struct selinfo *sip) {
OS_DbgPrint(OSK_MID_TRACE,("Called selrecord\n"));
}
void wakeupsocket( struct socket *so, struct selinfo *sel ) {
void *connection = so->so_connection;
char *data = 0;
int datalen = 0;
int flags = 0;
OS_DbgPrint(OSK_MID_TRACE,("Wakeup: %x\n", so));
#if 0
if( soreceive(so, &paddr, 0, &mp0, &controlp, flags) == 0 ) {
/* We have data available */
OS_DbgPrint(OSK_MID_TRACE,("Data available on %x\n", so));
}
#endif
}
void selwakeup( struct selinfo *sel ) {
OS_DbgPrint(OSK_MID_TRACE,("Called selwakeup\n"));
}

View file

@ -74,58 +74,30 @@ struct inpcbinfo tcbinfo;
#endif /* TUBA_INCLUDE */ #endif /* TUBA_INCLUDE */
/*
* Insert segment ti into reassembly queue of tcp with
* control block tp. Return TH_FIN if reassembly now includes
* a segment with FIN. The macro form does the common case inline
* (segment is the next to be received on an established connection,
* and the queue is empty), avoiding linkage into and removal
* from the queue and repetition of various conversions.
* Set DELACK for segments received in order, but ack immediately
* when segments are out of order (so fast retransmit can work).
*/
#ifdef TCP_ACK_HACK
#define TCP_REASS(tp, ti, m, so, flags) { \
if ((ti)->ti_seq == (tp)->rcv_nxt && \
(tp)->seg_next == (struct tcpiphdr *)(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) { \
if (ti->ti_flags & TH_PUSH) \
tp->t_flags |= TF_ACKNOW; \
else \
tp->t_flags |= TF_DELACK; \
(tp)->rcv_nxt += (ti)->ti_len - IPHDR_SIZE; \
OS_DbgPrint(OSK_MID_TRACE,("Added %d to rcv_nxt\n", \
(ti)->ti_len - IPHDR_SIZE)); \
flags = (ti)->ti_flags & TH_FIN; \
tcpstat.tcps_rcvpack++;\
tcpstat.tcps_rcvbyte += (ti)->ti_len;\
sbappend(so, &(so)->so_rcv, (m)); \
sorwakeup(so); \
} else { \
(flags) = tcp_reass((tp), (ti), (m)); \
tp->t_flags |= TF_ACKNOW; \
} \
}
#else
#define TCP_REASS(tp, ti, m, so, flags) { \ #define TCP_REASS(tp, ti, m, so, flags) { \
if ((ti)->ti_seq == (tp)->rcv_nxt && \ if ((ti)->ti_seq == (tp)->rcv_nxt && \
(tp)->seg_next == (struct tcpiphdr *)(tp) && \ (tp)->seg_next == (struct tcpiphdr *)(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) { \ (tp)->t_state == TCPS_ESTABLISHED) { \
tp->t_flags |= TF_DELACK; \ tp->t_flags |= TF_DELACK; \
(tp)->rcv_nxt += (ti)->ti_len - IPHDR_SIZE; \ if (!(ti)->ti_flags & TH_FIN && \
OS_DbgPrint(OSK_MID_TRACE,("Added %d to rcv_nxt\n", \ !(ti)->ti_flags & TH_RST) { \
(ti)->ti_len - IPHDR_SIZE)); \ (tp)->rcv_nxt += (ti)->ti_len - sizeof(struct ip); \
OS_DbgPrint(OSK_MID_TRACE,("(REASS2) Added %d to rcv_nxt\n", \
(ti)->ti_len - sizeof(struct ip))); \
} else { \
so->so_rcv.sb_sel.si_flags |= SEL_FIN; \
} \
flags = (ti)->ti_flags & TH_FIN; \ flags = (ti)->ti_flags & TH_FIN; \
tcpstat.tcps_rcvpack++;\ tcpstat.tcps_rcvpack++; \
tcpstat.tcps_rcvbyte += (ti)->ti_len;\ tcpstat.tcps_rcvbyte += (ti)->ti_len; \
sbappend(so, &(so)->so_rcv, (m)); \ sbappend(so, &so->so_rcv, (m)); \
sorwakeup(so); \ sorwakeup(so); \
} else { \ } else { \
(flags) = tcp_reass((tp), (ti), (m)); \ (flags) = tcp_reass((tp), (ti), (m)); \
tp->t_flags |= TF_ACKNOW; \ tp->t_flags |= TF_ACKNOW; \
} \ } \
} }
#endif
#ifndef TUBA_INCLUDE #ifndef TUBA_INCLUDE
int int
@ -231,13 +203,30 @@ present:
ti = (struct tcpiphdr *)ti->ti_next; ti = (struct tcpiphdr *)ti->ti_next;
if (so->so_state & SS_CANTRCVMORE) if (so->so_state & SS_CANTRCVMORE)
m_freem(m); m_freem(m);
else else {
sbappend(so, &so->so_rcv, m); sbappend(so, &so->so_rcv, (m));
}
} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
sorwakeup(so); sorwakeup(so);
return (flags); return (flags);
} }
void rip_input_mini(so, ti, m)
struct socket *so;
struct tcpiphdr *ti;
struct mbuf *m;
{
register struct ip *ip = mtod(m, struct ip *);
register struct inpcb *inp;
struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
ripsrc.sin_addr = ti->ti_src;
sbappendaddr(&so->so_rcv,
(struct sockaddr *)&ripsrc, m,
(struct mbuf *)0);
}
/* /*
* TCP input routine, follows pages 65-76 of the * TCP input routine, follows pages 65-76 of the
* protocol specification dated September, 1981 very closely. * protocol specification dated September, 1981 very closely.
@ -249,6 +238,8 @@ tcp_input(m, iphlen)
{ {
register struct tcpiphdr *ti; register struct tcpiphdr *ti;
register struct inpcb *inp; register struct inpcb *inp;
struct sockaddr_in addr = { 0 };
struct mbuf mhdr = { 0 }, mpayload = { 0 };
caddr_t optp = NULL; caddr_t optp = NULL;
int optlen = 0; int optlen = 0;
int len, tlen, off; int len, tlen, off;
@ -342,6 +333,8 @@ tcp_input(m, iphlen)
m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
OskitDumpBuffer(m->m_data, m->m_len);
/* /*
* Locate pcb for segment. * Locate pcb for segment.
*/ */
@ -380,6 +373,22 @@ findpcb:
tiwin = ti->ti_win; tiwin = ti->ti_win;
so = inp->inp_socket; so = inp->inp_socket;
#if 0
mhdr.m_type = MT_HEADER;
memcpy(mhdr.m_pktdat, ti, sizeof(ti));
mhdr.m_data = mhdr.m_pktdat;
mhdr.m_len = 0;
mhdr.m_flags = M_PKTHDR | M_EOR;
mhdr.m_next = &mpayload;
mpayload.m_type = MT_DATA;
mpayload.m_data = m->m_data + sizeof(*ti);
mpayload.m_len = m->m_len - sizeof(*ti);
mpayload.m_flags = M_EOR;
rip_input_mini(so, ti, &mhdr);
#endif
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
#ifdef TCPDEBUG #ifdef TCPDEBUG
if (so->so_options & SO_DEBUG) { if (so->so_options & SO_DEBUG) {
@ -589,14 +598,17 @@ findpcb:
*/ */
++tcpstat.tcps_preddat; ++tcpstat.tcps_preddat;
tp->rcv_nxt += ti->ti_len; tp->rcv_nxt += ti->ti_len;
OS_DbgPrint(OSK_MID_TRACE,("Added %d to rcv_nxt\n",
ti->ti_len));
tcpstat.tcps_rcvpack++; tcpstat.tcps_rcvpack++;
tcpstat.tcps_rcvbyte += ti->ti_len; tcpstat.tcps_rcvbyte += ti->ti_len;
/* /*
* Add data to socket buffer. * Add data to socket buffer.
*/ */
sbappend(so, &so->so_rcv, m); OS_DbgPrint
(OSK_MID_TRACE,("Adding %d to socket buffer\n",
m->m_len));
sbappend(so, &so->so_rcv, (m));
so->so_rcv.sb_cc += m->m_len;
sorwakeup(so); sorwakeup(so);
#ifdef TCP_ACK_HACK #ifdef TCP_ACK_HACK
/* /*
@ -879,6 +891,7 @@ findpcb:
so)); so));
tp->t_state = TCPS_ESTABLISHED; tp->t_state = TCPS_ESTABLISHED;
tp->t_timer[TCPT_KEEP] = tcp_keepidle; tp->t_timer[TCPT_KEEP] = tcp_keepidle;
socwakeup(so);
} }
} else { } else {
/* /*
@ -1173,8 +1186,9 @@ trimthenstep6:
* error and we send an RST and drop the connection. * error and we send an RST and drop the connection.
*/ */
if (tiflags & TH_SYN) { if (tiflags & TH_SYN) {
tp = tcp_drop(tp, ECONNRESET); OS_DbgPrint(OSK_MID_TRACE,("SYN In window\n"));
goto dropwithreset; tp = tcp_drop(tp, ECONNRESET);
goto dropwithreset;
} }
/* /*
@ -1415,7 +1429,7 @@ process_ACK:
ourfinisacked = 0; ourfinisacked = 0;
} }
if (so->so_snd.sb_flags & SB_NOTIFY) if (so->so_snd.sb_flags & SB_NOTIFY)
sowwakeup(so); sowwakeup(so);
tp->snd_una = ti->ti_ack; tp->snd_una = ti->ti_ack;
if (SEQ_LT(tp->snd_nxt, tp->snd_una)) if (SEQ_LT(tp->snd_nxt, tp->snd_una))
tp->snd_nxt = tp->snd_una; tp->snd_nxt = tp->snd_una;
@ -1522,6 +1536,9 @@ step6:
* actually wanting to send this much urgent data. * actually wanting to send this much urgent data.
*/ */
if (ti->ti_urp + so->so_rcv.sb_cc > sb_max) { if (ti->ti_urp + so->so_rcv.sb_cc > sb_max) {
OS_DbgPrint(OSK_MID_TRACE,
("%x: Urgent pointer out of range: %x\n",
ti->ti_urp));
ti->ti_urp = 0; /* XXX */ ti->ti_urp = 0; /* XXX */
tiflags &= ~TH_URG; /* XXX */ tiflags &= ~TH_URG; /* XXX */
goto dodata; /* XXX */ goto dodata; /* XXX */
@ -1579,6 +1596,9 @@ dodata: /* XXX */
* case PRU_RCVD). If a FIN has already been received on this * case PRU_RCVD). If a FIN has already been received on this
* connection then we just ignore the text. * connection then we just ignore the text.
*/ */
OS_DbgPrint(OSK_MID_TRACE,("TIFlags: %x\n", tiflags));
if ((ti->ti_len || (tiflags&TH_FIN)) && if ((ti->ti_len || (tiflags&TH_FIN)) &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) { TCPS_HAVERCVDFIN(tp->t_state) == 0) {
TCP_REASS(tp, ti, m, so, tiflags); TCP_REASS(tp, ti, m, so, tiflags);
@ -1589,7 +1609,7 @@ dodata: /* XXX */
*/ */
len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt); len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt);
} else { } else {
m_freem(m); /*m_freem(m);*/
tiflags &= ~TH_FIN; tiflags &= ~TH_FIN;
} }

View file

@ -85,8 +85,7 @@ tcp_output(tp)
struct rmxp_tao *taop; struct rmxp_tao *taop;
struct rmxp_tao tao_noncached; struct rmxp_tao tao_noncached;
OS_DbgPrint(OSK_MID_TRACE, OS_DbgPrint(OSK_MID_TRACE,("Start\n"));
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* Determine length of data that should be transmitted, * Determine length of data that should be transmitted,
@ -102,7 +101,9 @@ tcp_output(tp)
* slow start to get ack "clock" running again. * slow start to get ack "clock" running again.
*/ */
tp->snd_cwnd = tp->t_maxseg; tp->snd_cwnd = tp->t_maxseg;
again: again:
OS_DbgPrint(OSK_MID_TRACE,("Again...\n"));
sendalot = 0; sendalot = 0;
off = tp->snd_nxt - tp->snd_una; off = tp->snd_nxt - tp->snd_una;
win = min(tp->snd_wnd, tp->snd_cwnd); win = min(tp->snd_wnd, tp->snd_cwnd);
@ -237,9 +238,6 @@ again:
goto send; goto send;
} }
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* Compare available window to amount of window * Compare available window to amount of window
* known to peer (as advertised window less * known to peer (as advertised window less
@ -262,9 +260,6 @@ again:
goto send; goto send;
} }
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* Send if we owe peer an ACK. * Send if we owe peer an ACK.
*/ */
@ -284,9 +279,6 @@ again:
((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
goto send; goto send;
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* TCP window updates are not reliable, rather a polling protocol * TCP window updates are not reliable, rather a polling protocol
* using ``persist'' packets is used to insure receipt of window * using ``persist'' packets is used to insure receipt of window
@ -321,9 +313,6 @@ again:
/*return (0);*/ /*return (0);*/
send: send:
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* Before ESTABLISHED, force sending of initial options * Before ESTABLISHED, force sending of initial options
* unless TCP set not to do any options. * unless TCP set not to do any options.
@ -358,9 +347,6 @@ send:
} }
} }
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* Send a timestamp and echo-reply if this is a SYN and our side * Send a timestamp and echo-reply if this is a SYN and our side
* wants to use timestamps (TF_REQ_TSTMP is set) or both our side * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
@ -379,9 +365,6 @@ send:
optlen += TCPOLEN_TSTAMP_APPA; optlen += TCPOLEN_TSTAMP_APPA;
} }
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* Send `CC-family' options if our side wants to use them (TF_REQ_CC), * Send `CC-family' options if our side wants to use them (TF_REQ_CC),
* options are allowed (!TF_NOOPT) and it's not a RST. * options are allowed (!TF_NOOPT) and it's not a RST.
@ -457,9 +440,6 @@ send:
hdrlen += optlen; hdrlen += optlen;
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* Adjust data length if insertion of options will * Adjust data length if insertion of options will
* bump the packet length beyond the t_maxopd length. * bump the packet length beyond the t_maxopd length.
@ -480,8 +460,6 @@ send:
panic("tcphdr too big"); panic("tcphdr too big");
/*#endif*/ /*#endif*/
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/* /*
* Grab a header mbuf, attaching a copy of data to * Grab a header mbuf, attaching a copy of data to
@ -607,21 +585,12 @@ send:
if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg) if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg)
win = 0; win = 0;
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
if (win > (long)TCP_MAXWIN << tp->rcv_scale) if (win > (long)TCP_MAXWIN << tp->rcv_scale)
win = (long)TCP_MAXWIN << tp->rcv_scale; win = (long)TCP_MAXWIN << tp->rcv_scale;
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
win = (long)(tp->rcv_adv - tp->rcv_nxt); win = (long)(tp->rcv_adv - tp->rcv_nxt);
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
ti->ti_win = htons((u_short) (win>>tp->rcv_scale)); ti->ti_win = htons((u_short) (win>>tp->rcv_scale));
if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
@ -640,9 +609,6 @@ send:
* checksum extended header and data. * checksum extended header and data.
*/ */
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
if (len + optlen) { if (len + optlen) {
ti->ti_src.s_addr = tp->t_inpcb->inp_laddr.s_addr; ti->ti_src.s_addr = tp->t_inpcb->inp_laddr.s_addr;
ti->ti_dst.s_addr = tp->t_inpcb->inp_faddr.s_addr; ti->ti_dst.s_addr = tp->t_inpcb->inp_faddr.s_addr;
@ -651,14 +617,8 @@ send:
optlen + len)); optlen + len));
} }
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
ti->ti_sum = in_cksum(m, (int)(hdrlen + len)); ti->ti_sum = in_cksum(m, (int)(hdrlen + len));
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
/* /*
* In transmit state, time the transmission and arrange for * In transmit state, time the transmission and arrange for
* the retransmit. In persist state, just set snd_max. * the retransmit. In persist state, just set snd_max.
@ -711,9 +671,6 @@ send:
if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
tp->snd_max = tp->snd_nxt + len; tp->snd_max = tp->snd_nxt + len;
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
#ifdef TCPDEBUG #ifdef TCPDEBUG
/* /*
* Trace. * Trace.
@ -756,9 +713,7 @@ send:
} }
#endif #endif
OS_DbgPrint(OSK_MID_TRACE, OS_DbgPrint(OSK_MID_TRACE,("Calling ip_output\n"));
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
error = ip_output(so, m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, error = ip_output(so, m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
so->so_options & SO_DONTROUTE, 0); so->so_options & SO_DONTROUTE, 0);
} }
@ -799,6 +754,8 @@ out:
tp->rcv_adv = tp->rcv_nxt + win; tp->rcv_adv = tp->rcv_nxt + win;
tp->last_ack_sent = tp->rcv_nxt; tp->last_ack_sent = tp->rcv_nxt;
tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
OS_DbgPrint(OSK_MID_TRACE,("sendalot: %d (flags %x)\n",
sendalot, tp->t_flags));
if (sendalot) if (sendalot)
goto again; goto again;
return (0); return (0);

View file

@ -427,7 +427,7 @@ tcp_notify(inp, error)
so->so_error = error; so->so_error = error;
else else
tp->t_softerror = error; tp->t_softerror = error;
wakeup((caddr_t) &so->so_timeo); wakeup(so, NULL, (caddr_t) &so->so_timeo);
sorwakeup(so); sorwakeup(so);
sowwakeup(so); sowwakeup(so);
} }

View file

@ -393,7 +393,7 @@ restart:
(atomic || space < so->so_snd.sb_lowat || space < clen)) { (atomic || space < so->so_snd.sb_lowat || space < clen)) {
if (so->so_state & SS_NBIO) if (so->so_state & SS_NBIO)
snderr(EWOULDBLOCK); snderr(EWOULDBLOCK);
sbunlock(&so->so_snd); sbunlock(so, &so->so_snd);
error = sbwait(&so->so_snd); error = sbwait(&so->so_snd);
splx(s); splx(s);
if (error) if (error)
@ -480,12 +480,14 @@ nopages:
} while (resid); } while (resid);
release: release:
sbunlock(&so->so_snd); sbunlock(so, &so->so_snd);
out: out:
#ifndef __REACTOS__
if (top) if (top)
m_freem(top); m_freem(top);
if (control) if (control)
m_freem(control); m_freem(control);
#endif /* The caller owns top and control */
return (error); return (error);
} }
@ -506,305 +508,87 @@ out:
* only for the count in uio_resid. * only for the count in uio_resid.
*/ */
int int
soreceive(so, paddr, uio, mp0, controlp, flagsp) soreceive(so, paddr, uio, _mp0, controlp, flagsp)
register struct socket *so; register struct socket *so;
struct mbuf **paddr; struct mbuf **paddr;
struct uio *uio; struct uio *uio;
struct mbuf **mp0; struct mbuf **_mp0;
struct mbuf **controlp; struct mbuf **controlp;
int *flagsp; int *flagsp;
{ {
register struct mbuf *m, **mp; struct mbuf dummy = { 0 };
register int flags, len, error, s, offset; struct mbuf *mb = &dummy, *mn, *mp0 = *_mp0;
struct protosw *pr = so->so_proto; int total = 0, copyamt;
struct mbuf *nextrecord;
int moff, type = 0;
int orig_resid = uio->uio_resid;
mp = mp0; dummy.m_nextpkt = so->so_rcv.sb_mb;
if (paddr) uio->uio_resid = 0;
*paddr = 0;
if (controlp)
*controlp = 0;
if (flagsp)
flags = *flagsp &~ MSG_EOR;
else
flags = 0;
if (flags & MSG_OOB) {
m = m_get(M_WAIT, MT_DATA);
error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0);
if (error)
goto bad;
do {
error = uiomove(mtod(m, caddr_t),
(int) min(uio->uio_resid, m->m_len), uio);
/*m = m_free(m);*/
} while (uio->uio_resid && error == 0 && m);
bad:
if (m)
/*m_freem(m);*/
return (error);
}
if (mp)
*mp = (struct mbuf *)0;
if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
(*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
(struct mbuf *)0, (struct mbuf *)0);
restart: if( mp0->m_len == 0 )
error = sblock(&so->so_rcv, SBLOCKWAIT(flags)); return 0;
if (error)
return (error);
s = splnet();
m = so->so_rcv.sb_mb; if( so->so_rcv.sb_cc == 0 && so->so_rcv.sb_sel.si_flags & SEL_FIN )
/* return OSK_ESHUTDOWN;
* If we have less data than requested, block awaiting more
* (subject to any timeout) if: while( mb->m_nextpkt && total < mp0->m_len ) {
* 1. the current count is less than the low water mark, or OS_DbgPrint(OSK_MID_TRACE, ("Looking at packet %x\n", mb));
* 2. MSG_WAITALL is set, and it is possible to do the entire
* receive operation at once if we block (resid <= hiwat). if( *flagsp & MSG_OOB ) {
* 3. MSG_DONTWAIT is not set OS_DbgPrint(OSK_MID_TRACE, ("Searching for oob: %x\n", mb));
* If MSG_WAITALL is set but resid is larger than the receive buffer, while( mb->m_nextpkt && mb->m_nextpkt->m_type != MT_OOBDATA )
* we have to do the receive in sections, and thus risk returning mb = mb->m_nextpkt;
* a short count if a timeout or signal occurs after we start. } else {
*/ while( mb->m_nextpkt && mb->m_nextpkt->m_type != MT_DATA ) {
if (m == 0 || (((flags & MSG_DONTWAIT) == 0 && OS_DbgPrint
so->so_rcv.sb_cc < uio->uio_resid) && (OSK_MID_TRACE,
(so->so_rcv.sb_cc < so->so_rcv.sb_lowat || ("Searching for data: %x (%x@%x)\n",
((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) && mb->m_nextpkt->m_type,
m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) { mb->m_nextpkt->m_len,
#ifdef DIAGNOSTIC mb->m_nextpkt->m_data));
if (m == 0 && so->so_rcv.sb_cc) mb = mb->m_nextpkt;
panic("receive 1"); }
#endif
if (so->so_error) {
if (m)
goto dontblock;
error = so->so_error;
if ((flags & MSG_PEEK) == 0)
so->so_error = 0;
goto release;
}
if (so->so_state & SS_CANTRCVMORE) {
if (m)
goto dontblock;
else
goto release;
}
for (; m; m = m->m_next)
if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
m = so->so_rcv.sb_mb;
goto dontblock;
}
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
(so->so_proto->pr_flags & PR_CONNREQUIRED)) {
error = ENOTCONN;
goto release;
}
if (uio->uio_resid == 0)
goto release;
if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
error = EWOULDBLOCK;
goto release;
}
sbunlock(&so->so_rcv);
error = sbwait(&so->so_rcv);
splx(s);
if (error)
return (error);
goto restart;
}
dontblock:
if (uio->uio_procp)
uio->uio_procp->p_stats->p_ru.ru_msgrcv++;
nextrecord = m->m_nextpkt;
if (pr->pr_flags & PR_ADDR) {
#ifdef DIAGNOSTIC
if (m->m_type != MT_SONAME)
panic("receive 1a");
#endif
orig_resid = 0;
if (flags & MSG_PEEK) {
if (paddr)
*paddr = m_copy(m, 0, m->m_len);
m = m->m_next;
} else {
sbfree(&so->so_rcv, m);
if (paddr) {
*paddr = m;
so->so_rcv.sb_mb = m->m_next;
m->m_next = 0;
m = so->so_rcv.sb_mb;
} else {
MFREE(m, so->so_rcv.sb_mb);
m = so->so_rcv.sb_mb;
}
}
}
while (m && m->m_type == MT_CONTROL && error == 0) {
if (flags & MSG_PEEK) {
if (controlp)
*controlp = m_copy(m, 0, m->m_len);
m = m->m_next;
} else {
sbfree(&so->so_rcv, m);
if (controlp) {
#ifndef __REACTOS__
if (pr->pr_domain->dom_externalize &&
mtod(m, struct cmsghdr *)->cmsg_type ==
SCM_RIGHTS)
error = (*pr->pr_domain->dom_externalize)(m);
*controlp = m;
so->so_rcv.sb_mb = m->m_next;
m->m_next = 0;
m = so->so_rcv.sb_mb;
#endif
} else {
/*MFREE(m, so->so_rcv.sb_mb);*/
m = so->so_rcv.sb_mb;
}
}
if (controlp) {
orig_resid = 0;
controlp = &(*controlp)->m_next;
}
}
if (m) {
if ((flags & MSG_PEEK) == 0)
m->m_nextpkt = nextrecord;
type = m->m_type;
if (type == MT_OOBDATA)
flags |= MSG_OOB;
}
moff = 0;
offset = 0;
while (m && uio->uio_resid > 0 && error == 0) {
if (m->m_type == MT_OOBDATA) {
if (type != MT_OOBDATA)
break;
} else if (type == MT_OOBDATA)
break;
#ifdef DIAGNOSTIC
else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
panic("receive 3");
#endif
so->so_state &= ~SS_RCVATMARK;
len = uio->uio_resid;
if (so->so_oobmark && len > so->so_oobmark - offset)
len = so->so_oobmark - offset;
if (len > m->m_len - moff)
len = m->m_len - moff;
/*
* If mp is set, just pass back the mbufs.
* Otherwise copy them out via the uio, then free.
* Sockbuf must be consistent here (points to current mbuf,
* it points to next record) when we drop priority;
* we must note any additions to the sockbuf when we
* block interrupts again.
*/
if (mp == 0) {
splx(s);
error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
s = splnet();
} else
uio->uio_resid -= len;
if (len == m->m_len - moff) {
if (m->m_flags & M_EOR)
flags |= MSG_EOR;
if (flags & MSG_PEEK) {
m = m->m_next;
moff = 0;
} else {
nextrecord = m->m_nextpkt;
sbfree(&so->so_rcv, m);
if (mp) {
*mp = m;
mp = &m->m_next;
so->so_rcv.sb_mb = m = m->m_next;
*mp = (struct mbuf *)0;
} else {
/*MFREE(m, so->so_rcv.sb_mb);*/
m = so->so_rcv.sb_mb;
}
if (m)
m->m_nextpkt = nextrecord;
}
} else {
if (flags & MSG_PEEK)
moff += len;
else {
if (mp)
*mp = m_copym(m, 0, len, M_WAIT);
m->m_data += len;
m->m_len -= len;
so->so_rcv.sb_cc -= len;
}
}
if (so->so_oobmark) {
if ((flags & MSG_PEEK) == 0) {
so->so_oobmark -= len;
if (so->so_oobmark == 0) {
so->so_state |= SS_RCVATMARK;
break;
}
} else {
offset += len;
if (offset == so->so_oobmark)
break;
}
}
if (flags & MSG_EOR)
break;
/*
* If the MSG_WAITALL flag is set (for non-atomic socket),
* we must not quit until "uio->uio_resid == 0" or an error
* termination. If a signal/timeout occurs, return
* with a short count but without error.
* Keep sockbuf locked against other readers.
*/
while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
!sosendallatonce(so) && !nextrecord) {
if (so->so_error || so->so_state & SS_CANTRCVMORE)
break;
error = sbwait(&so->so_rcv);
if (error) {
sbunlock(&so->so_rcv);
splx(s);
return (0);
}
m = so->so_rcv.sb_mb;
if (m)
nextrecord = m->m_nextpkt;
}
} }
if (m && pr->pr_flags & PR_ATOMIC) { if( !mb->m_nextpkt ) break;
flags |= MSG_TRUNC;
if ((flags & MSG_PEEK) == 0)
(void) sbdroprecord(&so->so_rcv);
}
if ((flags & MSG_PEEK) == 0) {
if (m == 0)
so->so_rcv.sb_mb = nextrecord;
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
(*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
(struct mbuf *)flags, (struct mbuf *)0);
}
if (orig_resid == uio->uio_resid && orig_resid &&
(flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
sbunlock(&so->so_rcv);
splx(s);
goto restart;
}
if (flagsp) mn = mb->m_nextpkt;
*flagsp |= flags;
release: if( !mn->m_next ) mn->m_next = mn->m_data;
sbunlock(&so->so_rcv); copyamt = min(mn->m_len, mp0->m_len);
splx(s); OS_DbgPrint(OSK_MID_TRACE,
return (error); ("Copying %d bytes (%d,%d) (total is %d so far)\n",
copyamt, mn->m_len, mp0->m_len, total + copyamt));
memcpy( mp0->m_data + total, mn->m_next, copyamt );
total += copyamt;
mp0->m_len -= copyamt;
if( copyamt < mn->m_len ) {
if( !(*flagsp & MSG_PEEK) )
((caddr_t)mn->m_next) += copyamt;
break;
}
mb->m_nextpkt = mn->m_nextpkt;
}
/* Free previous buffers if not peek */
if( !(*flagsp & MSG_PEEK) ) {
while( dummy.m_nextpkt && dummy.m_nextpkt != mn ) {
mb = dummy.m_nextpkt;
dummy.m_nextpkt = mb->m_nextpkt;
OS_DbgPrint
(OSK_MID_TRACE,
("Deleting buf %x", mb));
m_free(mb);
}
so->so_rcv.sb_cc -= total;
so->so_rcv.sb_mb = dummy.m_nextpkt;
}
uio->uio_resid = total;
OS_DbgPrint(OSK_MID_TRACE,("Leaving (success)\n"));
return 0;
} }
int int
@ -836,7 +620,7 @@ sorflush(so)
(void) sblock(sb, M_WAITOK); (void) sblock(sb, M_WAITOK);
s = splimp(); s = splimp();
socantrcvmore(so); socantrcvmore(so);
sbunlock(sb); sbunlock(so, sb);
asb = *sb; asb = *sb;
bzero((caddr_t)sb, sizeof (*sb)); bzero((caddr_t)sb, sizeof (*sb));
splx(s); splx(s);
@ -958,7 +742,7 @@ sosetopt(so, level, optname, m0)
} }
bad: bad:
if (m) if (m)
/*(void) m_free(m);*/ (void) m_free(m);
return (error); return (error);
} }
@ -1039,8 +823,8 @@ sogetopt(so, level, optname, mp)
} }
default: default:
(void)m_free(m); (void)m_free(m);
return (ENOPROTOOPT); return (ENOPROTOOPT);
} }
*mp = m; *mp = m;
return (0); return (0);
@ -1057,5 +841,5 @@ sohasoutofband(so)
gsignal(-so->so_pgid, SIGURG); gsignal(-so->so_pgid, SIGURG);
else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
psignal(p, SIGURG); psignal(p, SIGURG);
selwakeup(&so->so_rcv.sb_sel); wakeup(so, NULL, 0);
} }

View file

@ -111,20 +111,14 @@ soisconnected(so)
so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING); so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
so->so_state |= SS_ISCONNECTED; so->so_state |= SS_ISCONNECTED;
if (head && soqremque(so, 0)) { if (head && soqremque(so, 0)) {
soqinsque(head, so, 1); soqinsque(head, so, 1);
sorwakeup(head); sorwakeup(head);
wakeup((caddr_t)&head->so_timeo); wakeup(so, NULL, (caddr_t)&head->so_timeo);
} else { } else {
wakeup((caddr_t)&so->so_timeo); wakeup(so, NULL, (caddr_t)&so->so_timeo);
sorwakeup(so); sorwakeup(so);
sowwakeup(so); socwakeup(so);
} }
if( OtcpEvent.SocketConnectIndication )
OtcpEvent.SocketConnectIndication
( OtcpEvent.ClientData,
so,
so->so_connection );
} }
void void
@ -134,7 +128,7 @@ soisdisconnecting(so)
so->so_state &= ~SS_ISCONNECTING; so->so_state &= ~SS_ISCONNECTING;
so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE); so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
wakeup((caddr_t)&so->so_timeo); wakeup(so, NULL, (caddr_t)&so->so_timeo);
sowwakeup(so); sowwakeup(so);
sorwakeup(so); sorwakeup(so);
} }
@ -146,7 +140,7 @@ soisdisconnected(so)
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
wakeup((caddr_t)&so->so_timeo); wakeup(so, NULL, (caddr_t)&so->so_timeo);
sowwakeup(so); sowwakeup(so);
sorwakeup(so); sorwakeup(so);
} }
@ -194,7 +188,7 @@ sonewconn1(head, connstatus)
} }
if (connstatus) { if (connstatus) {
sorwakeup(head); sorwakeup(head);
wakeup((caddr_t)&head->so_timeo); wakeup(so, NULL, (caddr_t)&head->so_timeo);
so->so_state |= connstatus; so->so_state |= connstatus;
} }
return (so); return (so);
@ -327,23 +321,7 @@ sowakeup(so, sb)
{ {
struct proc *p; struct proc *p;
selwakeup(&sb->sb_sel); wakeup(so, &sb->sb_sel, (caddr_t)&sb->sb_cc);
#ifndef OSKIT
/*
* in the OS Kit, we do not want notifications to stop
*/
sb->sb_flags &= ~SB_SEL;
#endif
if (sb->sb_flags & SB_WAIT) {
sb->sb_flags &= ~SB_WAIT;
wakeup((caddr_t)&sb->sb_cc);
}
if (so->so_state & SS_ASYNC) {
if (so->so_pgid < 0)
gsignal(-so->so_pgid, SIGIO);
else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
psignal(p, SIGIO);
}
} }
/* /*
@ -383,7 +361,6 @@ soreserve(so, sndcc, rcvcc)
register struct socket *so; register struct socket *so;
u_long sndcc, rcvcc; u_long sndcc, rcvcc;
{ {
if (sbreserve(&so->so_snd, sndcc) == 0) if (sbreserve(&so->so_snd, sndcc) == 0)
goto bad; goto bad;
if (sbreserve(&so->so_rcv, rcvcc) == 0) if (sbreserve(&so->so_rcv, rcvcc) == 0)
@ -470,28 +447,47 @@ sbappend(so, sb, m)
struct sockbuf *sb; struct sockbuf *sb;
struct mbuf *m; struct mbuf *m;
{ {
register struct mbuf *n; register struct mbuf *n, *new_mbuf;
free( malloc( 2 ) );
if (m == 0) if (m == 0)
return; return;
n = sb->sb_mb; n = sb->sb_mb;
if (n) { OS_DbgPrint(OSK_MID_TRACE,("sbappendrecord: %x\n", n));
while (n->m_nextpkt)
n = n->m_nextpkt; while( n && n->m_nextpkt ) n = n->m_nextpkt;
do {
if (n->m_flags & M_EOR) { new_mbuf = malloc( sizeof( *m ) + m->m_len );
sbappendrecord(sb, m); /* XXXXXX!!!! */ memset( new_mbuf, 0, sizeof( *m ) );
return;
} free( malloc( 2 ) );
} while (n->m_next && (n = n->m_next));
new_mbuf->m_type = MT_DATA;
free( malloc( 2 ) );
new_mbuf->m_len = m->m_len;
free( malloc( 2 ) );
new_mbuf->m_data = ((caddr_t)new_mbuf) + sizeof(*new_mbuf);
free( malloc( 2 ) );
memcpy( new_mbuf->m_data, m->m_data, m->m_len );
free( malloc( 2 ) );
if( n ) {
n->m_nextpkt = new_mbuf;
OS_DbgPrint(OSK_MID_TRACE,("SK BUFF NEW: %x\n", n->m_nextpkt));
} else {
sb->sb_mb = new_mbuf;
OS_DbgPrint(OSK_MID_TRACE,
("SK BUFF HEAD: %x (new pkt %d bytes)\n",
sb->sb_mb, sb->sb_mb->m_len));
} }
OskitDumpBuffer( m->m_data, m->m_len );
if( OtcpEvent.SocketDataAvailable ) free( malloc( 2 ) );
OtcpEvent.SocketDataAvailable
( OtcpEvent.ClientData,
so,
so->so_connection,
m->m_data, m->m_len );
} }
#ifdef SOCKBUF_DEBUG #ifdef SOCKBUF_DEBUG
@ -539,6 +535,7 @@ sbappendrecord(sb, m0)
* Put the first mbuf on the queue. * Put the first mbuf on the queue.
* Note this permits zero length records. * Note this permits zero length records.
*/ */
sballoc(sb, m0); sballoc(sb, m0);
if (m) if (m)
m->m_nextpkt = m0; m->m_nextpkt = m0;
@ -615,7 +612,7 @@ sbappendaddr(sb, asa, m0, control)
int space = /*asa->sa_len;*/ sizeof(struct sockaddr); int space = /*asa->sa_len;*/ sizeof(struct sockaddr);
if (m0 && (m0->m_flags & M_PKTHDR) == 0) if (m0 && (m0->m_flags & M_PKTHDR) == 0)
panic("sbappendaddr"); panic("sbappendaddr");
if (m0) if (m0)
space += m0->m_pkthdr.len; space += m0->m_pkthdr.len;
for (n = control; n; n = n->m_next) { for (n = control; n; n = n->m_next) {
@ -709,6 +706,8 @@ sbcompress(sb, m, n)
(unsigned)m->m_len); (unsigned)m->m_len);
n->m_len += m->m_len; n->m_len += m->m_len;
sb->sb_cc += m->m_len; sb->sb_cc += m->m_len;
OS_DbgPrint(OSK_MID_TRACE,("SB->SB_CC = %d\n",
sb->sb_cc));
m = m_free(m); m = m_free(m);
continue; continue;
} }
@ -771,6 +770,8 @@ sbdrop(sb, len)
m->m_len -= len; m->m_len -= len;
m->m_data += len; m->m_data += len;
sb->sb_cc -= len; sb->sb_cc -= len;
OS_DbgPrint(OSK_MID_TRACE,("SB->SB_CC = %d\n",
sb->sb_cc));
break; break;
} }
len -= m->m_len; len -= m->m_len;

View file

@ -52,7 +52,6 @@ __inline ULONG SkipToOffset(
return Offset; return Offset;
} }
UINT CopyBufferToBufferChain( UINT CopyBufferToBufferChain(
PNDIS_BUFFER DstBuffer, PNDIS_BUFFER DstBuffer,
UINT DstOffset, UINT DstOffset,
@ -355,6 +354,18 @@ NdisAllocateBuffer(
"VirtualAddress (0x%X) Length (%d)\n", "VirtualAddress (0x%X) Length (%d)\n",
Status, Buffer, PoolHandle, VirtualAddress, Length)); Status, Buffer, PoolHandle, VirtualAddress, Length));
#if 0
Temp = Pool->FreeList;
while( Temp ) {
NDIS_DbgPrint(MID_TRACE,("Free buffer -> %x\n", Temp));
Temp = Temp->Next;
}
NDIS_DbgPrint(MID_TRACE,("|:. <- End free buffers"));
#endif
if(!VirtualAddress && !Length) return;
KeAcquireSpinLock(&Pool->SpinLock, &OldIrql); KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
if (Pool->FreeList) { if (Pool->FreeList) {
@ -370,13 +381,13 @@ NdisAllocateBuffer(
Temp->Mdl.MdlFlags |= (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE); Temp->Mdl.MdlFlags |= (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE);
Temp->Mdl.MappedSystemVa = VirtualAddress; Temp->Mdl.MappedSystemVa = VirtualAddress;
#else #else
Temp->Mdl.Next = (PMDL)NULL; Temp->Mdl.Next = (PMDL)NULL;
Temp->Mdl.Size = (CSHORT)(sizeof(MDL) + Temp->Mdl.Size = (CSHORT)(sizeof(MDL) +
(ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length) * sizeof(ULONG))); (ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length) * sizeof(ULONG)));
Temp->Mdl.MdlFlags = (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE); Temp->Mdl.MdlFlags = (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE);
; Temp->Mdl.StartVa = (PVOID)PAGE_ROUND_DOWN(VirtualAddress); ; Temp->Mdl.StartVa = (PVOID)PAGE_ROUND_DOWN(VirtualAddress);
Temp->Mdl.ByteOffset = (ULONG_PTR)(VirtualAddress - PAGE_ROUND_DOWN(VirtualAddress)); Temp->Mdl.ByteOffset = (ULONG_PTR)(VirtualAddress - PAGE_ROUND_DOWN(VirtualAddress));
Temp->Mdl.ByteCount = Length; Temp->Mdl.ByteCount = Length;
Temp->Mdl.MappedSystemVa = VirtualAddress; Temp->Mdl.MappedSystemVa = VirtualAddress;
#if 0 #if 0
//Temp->Mdl.Process = PsGetCurrentProcess(); //Temp->Mdl.Process = PsGetCurrentProcess();
@ -392,6 +403,8 @@ NdisAllocateBuffer(
} else { } else {
KeReleaseSpinLock(&Pool->SpinLock, OldIrql); KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
*Status = NDIS_STATUS_FAILURE; *Status = NDIS_STATUS_FAILURE;
NDIS_DbgPrint(MID_TRACE, ("Can't get another packet.\n"));
KeBugCheck(0);
} }
} }
@ -429,10 +442,12 @@ NdisAllocateBufferPool(
if (NumberOfDescriptors > 0) { if (NumberOfDescriptors > 0) {
Buffer = &Pool->Buffers[0]; Buffer = &Pool->Buffers[0];
DbgPrint("NDIS BUFFER ADDRESS << %x >>\n", Buffer);
Pool->FreeList = Buffer; Pool->FreeList = Buffer;
for (i = 1; i < NumberOfDescriptors; i++) { for (i = 1; i < NumberOfDescriptors; i++) {
Buffer->Next = &Pool->Buffers[i]; Buffer->Next = &Pool->Buffers[i];
Buffer = Buffer->Next; Buffer = Buffer->Next;
DbgPrint("NDIS BUFFER ADDRESS << %x >>\n", Buffer);
} }
Buffer->Next = NULL; Buffer->Next = NULL;
} else } else
@ -850,8 +865,8 @@ NdisFreeBuffer(
Pool = Temp->BufferPool; Pool = Temp->BufferPool;
KeAcquireSpinLock(&Pool->SpinLock, &OldIrql); KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
Buffer->Next = (PMDL)Pool->FreeList; Temp->Next = (PNETWORK_HEADER)Pool->FreeList;
Pool->FreeList = (PNETWORK_HEADER)Buffer; Pool->FreeList = (PNETWORK_HEADER)Temp;
KeReleaseSpinLock(&Pool->SpinLock, OldIrql); KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
} }

View file

@ -322,6 +322,8 @@ MiniEthReceiveComplete(
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n")); NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
if( !Filter ) return;
Adapter = (PLOGICAL_ADAPTER)Filter->Miniport; Adapter = (PLOGICAL_ADAPTER)Filter->Miniport;
NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n")); NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
@ -372,13 +374,15 @@ MiniEthReceiveIndication(
* PacketSize = Total size of received packet * PacketSize = Total size of received packet
*/ */
{ {
MiniIndicateData((PLOGICAL_ADAPTER)Filter->Miniport, if( Filter ) {
MacReceiveContext, MiniIndicateData((PLOGICAL_ADAPTER)Filter->Miniport,
HeaderBuffer, MacReceiveContext,
HeaderBufferSize, HeaderBuffer,
LookaheadBuffer, HeaderBufferSize,
LookaheadBufferSize, LookaheadBuffer,
PacketSize); LookaheadBufferSize,
PacketSize);
}
} }
@ -1555,6 +1559,7 @@ NdisIStartAdapter(
NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n")); NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
ExFreePool(Adapter); ExFreePool(Adapter);
ASSERT(FALSE); ASSERT(FALSE);
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
return; return;
} }

View file

@ -411,6 +411,7 @@ ProTransferData(
/* XXX sd - why is that true? */ /* XXX sd - why is that true? */
if (Packet == Adapter->LoopPacket) { if (Packet == Adapter->LoopPacket) {
NDIS_DbgPrint(MAX_TRACE, ("LoopPacket\n"));
/* NDIS is responsible for looping this packet */ /* NDIS is responsible for looping this packet */
NdisCopyFromPacketToPacket(Packet, NdisCopyFromPacketToPacket(Packet,
ByteOffset, ByteOffset,

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <arp.h> #include <arp.h>
#include <routines.h> #include <routines.h>
@ -43,42 +44,25 @@ PNDIS_PACKET PrepareARPPacket(
*/ */
{ {
PNDIS_PACKET NdisPacket; PNDIS_PACKET NdisPacket;
PNDIS_BUFFER NdisBuffer;
NDIS_STATUS NdisStatus; NDIS_STATUS NdisStatus;
PARP_HEADER Header; PARP_HEADER Header;
PVOID DataBuffer; PVOID DataBuffer;
ULONG Size; ULONG Size, Contig;
TI_DbgPrint(DEBUG_ARP, ("Called.\n")); TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
/* Prepare ARP packet */ /* Prepare ARP packet */
Size = MaxLLHeaderSize + sizeof(ARP_HEADER) + Size = MaxLLHeaderSize +
sizeof(ARP_HEADER) +
2 * LinkAddressLength + /* Hardware address length */ 2 * LinkAddressLength + /* Hardware address length */
2 * ProtoAddressLength; /* Protocol address length */ 2 * ProtoAddressLength; /* Protocol address length */
Size = MAX(Size, MinLLFrameSize); Size = MAX(Size, MinLLFrameSize);
DataBuffer = ExAllocatePool(NonPagedPool, Size); NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Size );
if (!DataBuffer) if( !NT_SUCCESS(NdisStatus) ) return NULL;
return NULL;
/* Allocate NDIS packet */ GetDataPtr( NdisPacket, 0, &DataBuffer, &Contig );
NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
ExFreePool(DataBuffer);
return NULL;
}
/* Allocate NDIS buffer for maximum link level header and ARP packet */
NdisAllocateBuffer(&NdisStatus, &NdisBuffer, GlobalBufferPool,
DataBuffer, Size);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
NdisFreePacket(NdisPacket);
ExFreePool(DataBuffer);
return NULL;
}
/* Link NDIS buffer into packet */
NdisChainBufferAtFront(NdisPacket, NdisBuffer);
RtlZeroMemory(DataBuffer, Size); RtlZeroMemory(DataBuffer, Size);
Header = (PARP_HEADER)((ULONG_PTR)DataBuffer + MaxLLHeaderSize); Header = (PARP_HEADER)((ULONG_PTR)DataBuffer + MaxLLHeaderSize);
Header->HWType = HardwareType; Header->HWType = HardwareType;
@ -126,7 +110,6 @@ VOID ARPTransmitComplete(
*/ */
{ {
TI_DbgPrint(DEBUG_ARP, ("Called.\n")); TI_DbgPrint(DEBUG_ARP, ("Called.\n"));
FreeNdisPacket(NdisPacket); FreeNdisPacket(NdisPacket);
} }

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <lan.h> #include <lan.h>
#include <address.h> #include <address.h>
@ -20,7 +21,6 @@ BOOLEAN ProtocolRegistered = FALSE;
LIST_ENTRY AdapterListHead; LIST_ENTRY AdapterListHead;
KSPIN_LOCK AdapterListLock; KSPIN_LOCK AdapterListLock;
NDIS_STATUS NDISCall( NDIS_STATUS NDISCall(
PLAN_ADAPTER Adapter, PLAN_ADAPTER Adapter,
NDIS_REQUEST_TYPE Type, NDIS_REQUEST_TYPE Type,
@ -73,72 +73,6 @@ NDIS_STATUS NDISCall(
} }
PNDIS_PACKET AllocateTDPacket(
PLAN_ADAPTER Adapter)
/*
* FUNCTION: Allocates an NDIS packet for NdisTransferData
* ARGUMENTS:
* Adapter = Pointer to LAN_ADAPTER structure
* RETURNS:
* Pointer to NDIS packet or NULL if there was not enough free
* non-paged memory
*/
{
NDIS_STATUS NdisStatus;
PNDIS_PACKET NdisPacket;
PNDIS_BUFFER Buffer;
PVOID Data;
NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool);
if (NdisStatus != NDIS_STATUS_SUCCESS)
return NULL;
Data = ExAllocatePool(NonPagedPool, Adapter->MTU);
if (!Data) {
NdisFreePacket(NdisPacket);
return NULL;
}
NdisAllocateBuffer(&NdisStatus,
&Buffer,
GlobalBufferPool,
Data,
Adapter->MTU);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
NdisFreePacket(NdisPacket);
ExFreePool(Data);
return NULL;
}
NdisChainBufferAtFront(NdisPacket, Buffer);
PC(NdisPacket)->Context = NULL; /* End of list */
return NdisPacket;
}
VOID FreeTDPackets(
PLAN_ADAPTER Adapter)
/*
* FUNCTION: Frees transfer data packets
* ARGUMENTS:
* Adapter = Pointer to LAN_ADAPTER structure
*/
{
PNDIS_PACKET NdisPacket, Next;
/* Release transfer data packets */
NdisPacket = Adapter->TDPackets;
while (NdisPacket) {
Next = PC(NdisPacket)->Context;
FreeNdisPacket(NdisPacket);
NdisPacket = Next;
}
Adapter->TDPackets = NULL;
}
VOID FreeAdapter( VOID FreeAdapter(
PLAN_ADAPTER Adapter) PLAN_ADAPTER Adapter)
/* /*
@ -147,8 +81,7 @@ VOID FreeAdapter(
* Adapter = Pointer to LAN_ADAPTER structure to free * Adapter = Pointer to LAN_ADAPTER structure to free
*/ */
{ {
FreeTDPackets(Adapter); exFreePool(Adapter);
ExFreePool(Adapter);
} }
@ -241,12 +174,11 @@ VOID STDCALL ProtocolSendComplete(
* Status = Status of the operation * Status = Status of the operation
*/ */
{ {
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
AdjustPacket(Packet, Adapter->HeaderSize, PC(Packet)->DLOffset); AdjustPacket(Packet, Adapter->HeaderSize, PC(Packet)->DLOffset);
(*PC(Packet)->DLComplete)(Adapter->Context, Packet, Status); (*PC(Packet)->DLComplete)(Adapter->Context, Packet, Status);
} }
@ -285,28 +217,35 @@ VOID STDCALL ProtocolTransferDataComplete(
&IPPacket.ContigSize, &IPPacket.ContigSize,
&IPPacket.TotalSize); &IPPacket.TotalSize);
IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred;
/* Determine which upper layer protocol that should receive /* Determine which upper layer protocol that should receive
this packet and pass it to the correct receive handler */ this packet and pass it to the correct receive handler */
OskitDumpBuffer( IPPacket.Header, BytesTransferred );
PacketType = ((PETH_HEADER)IPPacket.Header)->EType; PacketType = ((PETH_HEADER)IPPacket.Header)->EType;
IPPacket.Header += MaxLLHeaderSize;
TI_DbgPrint
(DEBUG_DATALINK,
("Ether Type = %x ContigSize = %d Total = %d\n",
PacketType, IPPacket.ContigSize, IPPacket.TotalSize));
switch (PacketType) { switch (PacketType) {
case ETYPE_IPv4: case ETYPE_IPv4:
case ETYPE_IPv6: case ETYPE_IPv6:
TI_DbgPrint(MID_TRACE,("Received IP Packet\n"));
IPReceive(Adapter->Context, &IPPacket); IPReceive(Adapter->Context, &IPPacket);
break; break;
case ETYPE_ARP: case ETYPE_ARP:
TI_DbgPrint(MID_TRACE,("Received ARP Packet\n"));
ARPReceive(Adapter->Context, &IPPacket); ARPReceive(Adapter->Context, &IPPacket);
default: default:
break; break;
} }
} }
/* Release the packet descriptor */ FreeNdisPacket( Packet );
KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
PC(Packet)->Context = Adapter->TDPackets;
Adapter->TDPackets = Packet;
KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
} }
@ -333,8 +272,10 @@ NDIS_STATUS STDCALL ProtocolReceive(
*/ */
{ {
USHORT EType; USHORT EType;
UINT PacketType; UINT PacketType, BytesTransferred;
IP_PACKET IPPacket; IP_PACKET IPPacket;
PCHAR BufferData;
NDIS_STATUS NdisStatus;
PNDIS_PACKET NdisPacket; PNDIS_PACKET NdisPacket;
PNDIS_BUFFER NdisBuffer; PNDIS_BUFFER NdisBuffer;
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
@ -374,22 +315,13 @@ NDIS_STATUS STDCALL ProtocolReceive(
/* Get a transfer data packet */ /* Get a transfer data packet */
KeAcquireSpinLockAtDpcLevel(&Adapter->Lock); KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Adapter->MTU );
if( NdisStatus != NDIS_STATUS_SUCCESS ) return NDIS_STATUS_NOT_ACCEPTED;
GetDataPtr( NdisPacket, 0, &BufferData, &PacketSize );
NdisPacket = Adapter->TDPackets; IPPacket.NdisPacket = NdisPacket;
if (NdisPacket == (PNDIS_PACKET)NULL) {
TI_DbgPrint(DEBUG_DATALINK, ("No available packet descriptors.\n"));
/* We don't have a free packet descriptor. Drop the packet */
KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
return NDIS_STATUS_SUCCESS;
}
Adapter->TDPackets = PC(NdisPacket)->Context;
KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
if (LookaheadBufferSize < PacketSize) { if (LookaheadBufferSize < PacketSize) {
NDIS_STATUS NdisStatus;
UINT BytesTransferred;
/* Get the data */ /* Get the data */
NdisTransferData(&NdisStatus, NdisTransferData(&NdisStatus,
Adapter->NdisHandle, Adapter->NdisHandle,
@ -398,45 +330,23 @@ NDIS_STATUS STDCALL ProtocolReceive(
PacketSize, PacketSize,
NdisPacket, NdisPacket,
&BytesTransferred); &BytesTransferred);
if (NdisStatus != NDIS_STATUS_PENDING) } else {
ProtocolTransferDataComplete(BindingContext, NdisStatus = NDIS_STATUS_SUCCESS;
NdisPacket, BytesTransferred = PacketSize;
NdisStatus, RtlCopyMemory(BufferData,
BytesTransferred); HeaderBuffer,
HeaderBufferSize);
return NDIS_STATUS_SUCCESS; RtlCopyMemory(BufferData + HeaderBufferSize,
LookaheadBuffer, LookaheadBufferSize);
} }
/* We got all the data in the lookahead buffer */ if (NdisStatus != NDIS_STATUS_PENDING)
ProtocolTransferDataComplete(BindingContext,
IPPacket.NdisPacket = NdisPacket; NdisPacket,
NdisStatus,
NdisGetFirstBufferFromPacket(NdisPacket, BytesTransferred);
&NdisBuffer,
&IPPacket.Header,
&IPPacket.ContigSize,
&IPPacket.TotalSize);
RtlCopyMemory(IPPacket.Header, LookaheadBuffer, PacketSize);
switch (PacketType) {
case ETYPE_IPv4:
case ETYPE_IPv6:
IPReceive(Adapter->Context, &IPPacket);
break;
case ETYPE_ARP:
ARPReceive(Adapter->Context, &IPPacket);
break;
default:
break;
}
/* Release the packet descriptor */ /* Release the packet descriptor */
KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
PC(NdisPacket)->Context = Adapter->TDPackets;
Adapter->TDPackets = NdisPacket;
KeReleaseSpinLockFromDpcLevel(&Adapter->Lock); KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
return NDIS_STATUS_SUCCESS; return NDIS_STATUS_SUCCESS;
@ -537,7 +447,7 @@ VOID LANTransmit(
area so it can be undone before we release the packet */ area so it can be undone before we release the packet */
Data = AdjustPacket(NdisPacket, Offset, Adapter->HeaderSize); Data = AdjustPacket(NdisPacket, Offset, Adapter->HeaderSize);
PC(NdisPacket)->DLOffset = Offset; PC(NdisPacket)->DLOffset = Offset;
if (Adapter->State == LAN_STATE_STARTED) { if (Adapter->State == LAN_STATE_STARTED) {
switch (Adapter->Media) { switch (Adapter->Media) {
case NdisMedium802_3: case NdisMedium802_3:
@ -633,7 +543,7 @@ static NTSTATUS ReadIPAddressFromRegistry( HANDLE RegHandle,
if(!AnsiLen) if(!AnsiLen)
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
AnsiAddress.Buffer = ExAllocatePoolWithTag(PagedPool, AnsiLen, 0x01020304); AnsiAddress.Buffer = exAllocatePoolWithTag(PagedPool, AnsiLen, 0x01020304);
if(!AnsiAddress.Buffer) if(!AnsiAddress.Buffer)
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
@ -642,14 +552,14 @@ static NTSTATUS ReadIPAddressFromRegistry( HANDLE RegHandle,
Status = RtlUnicodeStringToAnsiString(&AnsiAddress, &UnicodeAddress, FALSE); Status = RtlUnicodeStringToAnsiString(&AnsiAddress, &UnicodeAddress, FALSE);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
ExFreePool(AnsiAddress.Buffer); exFreePool(AnsiAddress.Buffer);
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
AnsiAddress.Buffer[AnsiAddress.Length] = 0; AnsiAddress.Buffer[AnsiAddress.Length] = 0;
*Address = AddrBuildIPv4(inet_addr(AnsiAddress.Buffer)); *Address = AddrBuildIPv4(inet_addr(AnsiAddress.Buffer));
if (!Address) { if (!Address) {
ExFreePool(AnsiAddress.Buffer); exFreePool(AnsiAddress.Buffer);
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
@ -693,20 +603,6 @@ VOID BindAdapter(
return; return;
} }
/* Allocate packets for NdisTransferData */
/* FIXME: How many should we allocate? */
Adapter->TDPackets = NULL;
for (i = 0; i < 2; i++) {
Packet = AllocateTDPacket(Adapter);
if (!Packet) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
FreeTDPackets(Adapter);
return;
}
PC(Packet)->Context = Adapter->TDPackets;
Adapter->TDPackets = Packet;
}
/* Bind the adapter to IP layer */ /* Bind the adapter to IP layer */
BindInfo.Context = Adapter; BindInfo.Context = Adapter;
BindInfo.HeaderSize = Adapter->HeaderSize; BindInfo.HeaderSize = Adapter->HeaderSize;
@ -717,9 +613,9 @@ VOID BindAdapter(
BindInfo.Transmit = LANTransmit; BindInfo.Transmit = LANTransmit;
IF = IPCreateInterface(&BindInfo); IF = IPCreateInterface(&BindInfo);
if (!IF) { if (!IF) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
FreeTDPackets(Adapter);
return; return;
} }
@ -750,7 +646,6 @@ VOID BindAdapter(
ZwClose(RegHandle); ZwClose(RegHandle);
if(Address) Address->Free(Address); if(Address) Address->Free(Address);
if(Netmask) Netmask->Free(Netmask); if(Netmask) Netmask->Free(Netmask);
FreeTDPackets(Adapter);
IPDestroyInterface(IF); IPDestroyInterface(IF);
return; return;
} }
@ -769,7 +664,6 @@ VOID BindAdapter(
if (!IPCreateNTE(IF, Address, AddrCountPrefixBits(Netmask))) { if (!IPCreateNTE(IF, Address, AddrCountPrefixBits(Netmask))) {
Netmask->Free(Netmask); Netmask->Free(Netmask);
TI_DbgPrint(MIN_TRACE, ("IPCreateNTE() failed.\n")); TI_DbgPrint(MIN_TRACE, ("IPCreateNTE() failed.\n"));
FreeTDPackets(Adapter);
IPDestroyInterface(IF); IPDestroyInterface(IF);
return; return;
} }
@ -791,13 +685,11 @@ VOID BindAdapter(
sizeof(UINT)); sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MID_TRACE, ("Could not set packet filter (0x%X).\n", NdisStatus)); TI_DbgPrint(MID_TRACE, ("Could not set packet filter (0x%X).\n", NdisStatus));
FreeTDPackets(Adapter);
IPDestroyInterface(IF); IPDestroyInterface(IF);
return; return;
} }
Adapter->Context = IF; Adapter->Context = IF;
Adapter->State = LAN_STATE_STARTED; Adapter->State = LAN_STATE_STARTED;
} }
@ -818,9 +710,6 @@ VOID UnbindAdapter(
IPUnregisterInterface(IF); IPUnregisterInterface(IF);
IPDestroyInterface(IF); IPDestroyInterface(IF);
/* Free transfer data packets */
FreeTDPackets(Adapter);
} }
} }
@ -848,7 +737,7 @@ NDIS_STATUS LANRegisterAdapter(
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
IF = ExAllocatePool(NonPagedPool, sizeof(LAN_ADAPTER)); IF = exAllocatePool(NonPagedPool, sizeof(LAN_ADAPTER));
if (!IF) { if (!IF) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NDIS_STATUS_RESOURCES; return NDIS_STATUS_RESOURCES;
@ -885,7 +774,7 @@ NDIS_STATUS LANRegisterAdapter(
if (NdisStatus == NDIS_STATUS_PENDING) if (NdisStatus == NDIS_STATUS_PENDING)
KeWaitForSingleObject(&IF->Event, UserRequest, KernelMode, FALSE, NULL); KeWaitForSingleObject(&IF->Event, UserRequest, KernelMode, FALSE, NULL);
else if (NdisStatus != NDIS_STATUS_SUCCESS) { else if (NdisStatus != NDIS_STATUS_SUCCESS) {
ExFreePool(IF); exFreePool(IF);
return NdisStatus; return NdisStatus;
} }
@ -910,7 +799,7 @@ NDIS_STATUS LANRegisterAdapter(
default: default:
/* Unsupported media */ /* Unsupported media */
TI_DbgPrint(MIN_TRACE, ("Unsupported media.\n")); TI_DbgPrint(MIN_TRACE, ("Unsupported media.\n"));
ExFreePool(IF); exFreePool(IF);
return NDIS_STATUS_NOT_SUPPORTED; return NDIS_STATUS_NOT_SUPPORTED;
} }
@ -921,7 +810,7 @@ NDIS_STATUS LANRegisterAdapter(
&IF->MTU, &IF->MTU,
sizeof(UINT)); sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
ExFreePool(IF); exFreePool(IF);
return NdisStatus; return NdisStatus;
} }
@ -933,7 +822,7 @@ NDIS_STATUS LANRegisterAdapter(
sizeof(UINT)); sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Query for maximum packet size failed.\n")); TI_DbgPrint(MIN_TRACE, ("Query for maximum packet size failed.\n"));
ExFreePool(IF); exFreePool(IF);
return NdisStatus; return NdisStatus;
} }
@ -956,7 +845,7 @@ NDIS_STATUS LANRegisterAdapter(
IF->HWAddressLength); IF->HWAddressLength);
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Query for current hardware address failed.\n")); TI_DbgPrint(MIN_TRACE, ("Query for current hardware address failed.\n"));
ExFreePool(IF); exFreePool(IF);
return NdisStatus; return NdisStatus;
} }
@ -968,7 +857,7 @@ NDIS_STATUS LANRegisterAdapter(
sizeof(UINT)); sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Query for maximum link speed failed.\n")); TI_DbgPrint(MIN_TRACE, ("Query for maximum link speed failed.\n"));
ExFreePool(IF); exFreePool(IF);
return NdisStatus; return NdisStatus;
} }

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <loopback.h> #include <loopback.h>
#include <ip.h> #include <ip.h>
@ -169,6 +170,7 @@ NDIS_STATUS LoopRegisterAdapter(
BindInfo.Transmit = LoopTransmit; BindInfo.Transmit = LoopTransmit;
Loopback = IPCreateInterface(&BindInfo); Loopback = IPCreateInterface(&BindInfo);
if ((Loopback != NULL) && (IPCreateNTE(Loopback, Address, 8))) if ((Loopback != NULL) && (IPCreateNTE(Loopback, Address, 8)))
{ {
/* Reference the interface for the NTE. The reference for /* Reference the interface for the NTE. The reference for

View file

@ -35,9 +35,7 @@ NTSTATUS DGTransmit(
NTSTATUS DGSendDatagram( NTSTATUS DGSendDatagram(
PTDI_REQUEST Request, PTDI_REQUEST Request,
PTDI_CONNECTION_INFORMATION ConnInfo, PTDI_CONNECTION_INFORMATION ConnInfo,
PNDIS_BUFFER Buffer, PIP_PACKET Packet);
ULONG DataSize,
DATAGRAM_BUILD_ROUTINE Build);
NTSTATUS DGReceiveDatagram( NTSTATUS DGReceiveDatagram(
PTDI_REQUEST Request, PTDI_REQUEST Request,

View file

@ -57,6 +57,7 @@ extern DWORD DebugTraceLevel;
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#if 0
#ifdef ASSERT #ifdef ASSERT
#undef ASSERT #undef ASSERT
#endif #endif
@ -66,6 +67,7 @@ extern DWORD DebugTraceLevel;
#else /* NASSERT */ #else /* NASSERT */
#define ASSERT(x) if (!(x)) { TI_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); } #define ASSERT(x) if (!(x)) { TI_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); }
#endif /* NASSERT */ #endif /* NASSERT */
#endif
#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x)) #define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x))
@ -73,8 +75,10 @@ extern DWORD DebugTraceLevel;
#define TI_DbgPrint(_t_, _x_) #define TI_DbgPrint(_t_, _x_)
#if 0
#define ASSERT_IRQL(x) #define ASSERT_IRQL(x)
#define ASSERT(x) #define ASSERT(x)
#endif
#endif /* DBG */ #endif /* DBG */
@ -103,6 +107,8 @@ extern DWORD DebugTraceLevel;
#define CP CHECKPOINT #define CP CHECKPOINT
#include <memtrack.h>
#endif /* __DEBUG_H */ #endif /* __DEBUG_H */
/* EOF */ /* EOF */

View file

@ -48,7 +48,7 @@ typedef struct IPADDR_ENTRY {
typedef struct IPROUTE_ENTRY { typedef struct IPROUTE_ENTRY {
ULONG Dest; ULONG Dest;
ULONG Index; //matches if_index in IFEntry and iae_index in IPAddrEntry ULONG Index; //matches if_index in IFEntry and iae_index in IPAddrEntry
ULONG Metric1; ULONG Metric1;
ULONG Metric2; ULONG Metric2;
ULONG Metric3; ULONG Metric3;
@ -87,13 +87,13 @@ typedef struct IFENTRY {
#define IP_MIB_STATS_ID 1 #define IP_MIB_STATS_ID 1
#define IF_MIB_STATS_ID 1 #define IF_MIB_STATS_ID 1
#ifndef IP_MIB_ROUTETABLE_ENTRY_ID
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101
#endif
#ifndef IP_MIB_ADDRTABLE_ENTRY_ID #ifndef IP_MIB_ADDRTABLE_ENTRY_ID
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 #define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
#endif #endif
#ifndef IP_MIB_ROUTETABLE_ENTRY_ID
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x103
#endif
#ifndef MAX_PHYSADDR_SIZE #ifndef MAX_PHYSADDR_SIZE
#define MAX_PHYSADDR_SIZE 8 #define MAX_PHYSADDR_SIZE 8
#endif #endif
@ -137,6 +137,59 @@ TDI_STATUS InfoTdiSetInformationEx(
PVOID Buffer, PVOID Buffer,
UINT BufferSize); UINT BufferSize);
/* Network layer info functions */
TDI_STATUS InfoNetworkLayerTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoNetworkLayerTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize );
TDI_STATUS InfoTransportLayerTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoTransportLayerTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize );
TDI_STATUS InfoInterfaceTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
TDI_STATUS InfoInterfaceTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize );
/* Insert and remove interface entities */
VOID InsertTDIInterfaceEntity( PIP_INTERFACE Interface );
VOID RemoveTDIInterfaceEntity( PIP_INTERFACE Interface );
#endif /* __INFO_H */ #endif /* __INFO_H */
/* EOF */ /* EOF */

View file

@ -0,0 +1,16 @@
#ifndef _TCPIP_INTERFACE_H
#define _TCPIP_INTERFACE_H
#include <ip.h>
NTSTATUS GetInterfaceIPv4Address( PIP_INTERFACE Interface,
ULONG Type,
PULONG Address );
UINT CountInterfaces();
NTSTATUS GetInterfaceSpeed( PIP_INTERFACE Interface, PUINT Speed );
NTSTATUS GetInterfaceName( PIP_INTERFACE Interface, PCHAR NameBuffer,
UINT NameMaxLen );
#endif//_TCPIP_INTERFACE_H

View file

@ -9,6 +9,7 @@
typedef VOID (*OBJECT_FREE_ROUTINE)(PVOID Object); typedef VOID (*OBJECT_FREE_ROUTINE)(PVOID Object);
#define FOURCC(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
/* Raw IPv4 style address */ /* Raw IPv4 style address */
typedef ULONG IPv4_RAW_ADDRESS; typedef ULONG IPv4_RAW_ADDRESS;
@ -93,7 +94,6 @@ typedef struct _PACKET_CONTEXT {
/* The ProtocolReserved field is structured as a PACKET_CONTEXT */ /* The ProtocolReserved field is structured as a PACKET_CONTEXT */
#define PC(Packet) ((PPACKET_CONTEXT)(&Packet->ProtocolReserved)) #define PC(Packet) ((PPACKET_CONTEXT)(&Packet->ProtocolReserved))
/* Address information a.k.a ADE */ /* Address information a.k.a ADE */
typedef struct _ADDRESS_ENTRY { typedef struct _ADDRESS_ENTRY {
DEFINE_TAG DEFINE_TAG
@ -105,10 +105,12 @@ typedef struct _ADDRESS_ENTRY {
PIP_ADDRESS Address; /* Pointer to address identifying this entry */ PIP_ADDRESS Address; /* Pointer to address identifying this entry */
} ADDRESS_ENTRY, *PADDRESS_ENTRY; } ADDRESS_ENTRY, *PADDRESS_ENTRY;
/* Values for address type */ /* Values for address type -- also the interface flags */
#define ADE_UNICAST 0x01 /* These values are mean to overlap meaningfully with the BSD ones */
#define ADE_MULTICAST 0x02 #define ADE_UNICAST 0x01
#define ADE_ADDRMASK 0x03 #define ADE_MULTICAST 0x02
#define ADE_ADDRMASK 0x04
#define ADE_POINTOPOINT 0x10
/* There is one NTE for each source (unicast) address assigned to an interface */ /* There is one NTE for each source (unicast) address assigned to an interface */
typedef struct _NET_TABLE_ENTRY { typedef struct _NET_TABLE_ENTRY {
@ -162,17 +164,6 @@ typedef struct _IP_INTERFACE {
} IP_INTERFACE, *PIP_INTERFACE; } IP_INTERFACE, *PIP_INTERFACE;
/* Prefix List Entry */
typedef struct _PREFIX_LIST_ENTRY {
DEFINE_TAG
LIST_ENTRY ListEntry; /* Entry on list */
ULONG RefCount; /* Reference count */
PIP_INTERFACE Interface; /* Pointer to interface */
PIP_ADDRESS Prefix; /* Pointer to prefix */
UINT PrefixLength; /* Length of prefix */
} PREFIX_LIST_ENTRY, *PPREFIX_LIST_ENTRY;
#define IP_PROTOCOL_TABLE_SIZE 0x100 #define IP_PROTOCOL_TABLE_SIZE 0x100
typedef VOID (*IP_PROTOCOL_HANDLER)( typedef VOID (*IP_PROTOCOL_HANDLER)(
@ -202,8 +193,6 @@ extern LIST_ENTRY InterfaceListHead;
extern KSPIN_LOCK InterfaceListLock; extern KSPIN_LOCK InterfaceListLock;
extern LIST_ENTRY NetTableListHead; extern LIST_ENTRY NetTableListHead;
extern KSPIN_LOCK NetTableListLock; extern KSPIN_LOCK NetTableListLock;
extern LIST_ENTRY PrefixListHead;
extern KSPIN_LOCK PrefixListLock;
extern UINT MaxLLHeaderSize; extern UINT MaxLLHeaderSize;
extern UINT MinLLFrameSize; extern UINT MinLLFrameSize;

View file

@ -56,7 +56,6 @@ typedef struct LAN_ADAPTER {
UINT MacOptions; /* MAC options for NIC driver/adapter */ UINT MacOptions; /* MAC options for NIC driver/adapter */
UINT Speed; /* Link speed */ UINT Speed; /* Link speed */
UINT PacketFilter; /* Packet filter for this adapter */ UINT PacketFilter; /* Packet filter for this adapter */
PNDIS_PACKET TDPackets; /* Transfer Data packets */
} LAN_ADAPTER, *PLAN_ADAPTER; } LAN_ADAPTER, *PLAN_ADAPTER;
/* LAN adapter state constants */ /* LAN adapter state constants */

View file

@ -0,0 +1,74 @@
#ifndef MEMTRACK_H
#define MEMTRACK_H
#ifndef FOURCC
#define FOURCC(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
#endif
#define FBSD_MALLOC FOURCC('d','s','b','f')
#define EXALLOC_TAG FOURCC('E','x','A','l')
#define AllocatePacketWithBuffer(x,y,z) AllocatePacketWithBufferX(x,y,z,__FILE__,__LINE__)
#define FreeNdisPacket(x) FreeNdisPacketX(x,__FILE__,__LINE__)
#ifdef MEMTRACK
#define MTMARK() TrackDumpFL(__FILE__, __LINE__)
#define NdisAllocateBuffer(x,y,z,a,b) { \
NdisAllocateBuffer(x,y,z,a,b); \
if( *x == NDIS_STATUS_SUCCESS ) { \
Track(NDIS_BUFFER_TAG, *y); \
} \
}
#define NdisAllocatePacket(x,y,z) { \
NdisAllocatePacket(x,y,z); \
if( *x == NDIS_STATUS_SUCCESS ) { \
Track(NDIS_PACKET_TAG, *y); \
} \
}
#define NdisFreePacket(x) { Untrack(x); NdisFreePacket(x); }
#define NdisFreeBuffer(x) { Untrack(x); NdisFreeBuffer(x); }
#define exAllocatePool(x,y) ExAllocatePoolX(x,y,__FILE__,__LINE__)
#define exAllocatePoolWithTag(x,y,z) ExAllocatePoolX(x,y,__FILE__,__LINE__)
#define exFreePool(x) ExFreePoolX(x,__FILE__,__LINE__)
extern LIST_ENTRY AllocatedObjectsHead;
extern KSPIN_LOCK AllocatedObjectsLock;
typedef struct _ALLOCATION_TRACKER {
LIST_ENTRY Entry;
DWORD Tag;
PVOID Thing;
PCHAR FileName;
DWORD LineNo;
} ALLOCATION_TRACKER, *PALLOCATION_TRACKER;
VOID TrackingInit();
VOID TrackWithTag( DWORD Tag, PVOID Thing, PCHAR File, DWORD Line );
#define Track(Tag,Thing) TrackWithTag(Tag,Thing,__FILE__,__LINE__)
VOID UntrackFL( PCHAR File, DWORD Line, PVOID Thing );
#define Untrack(Thing) UntrackFL(__FILE__,__LINE__,Thing)
VOID TrackDumpFL( PCHAR File, DWORD Line );
#define TrackDump() TrackDumpFL(__FILE__,__LINE__)
VOID TrackTag( DWORD Tag );
static inline PVOID ExAllocatePoolX( POOL_TYPE type, SIZE_T size, PCHAR File, ULONG Line ) {
PVOID Out = ExAllocatePool( type, size );
if( Out ) TrackWithTag( EXALLOC_TAG, Out, File, Line );
return Out;
}
static inline VOID ExFreePoolX( PVOID Data, PCHAR File, ULONG Line ) {
UntrackFL(File, Line, Data);
ExFreePool(Data);
}
#define MEMTRACK_MAX_TAGS_TO_TRACK 64
#else
#define MTMARK()
#define Track(x,y)
#define TrackingInit()
#define TrackDump()
#define Untrack(x)
#define TrackTag(x)
#endif
#endif/*MEMMTRAC_H*/

View file

@ -0,0 +1,28 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: include/info.h
* PURPOSE: TdiQueryInformation definitions
*/
#ifndef __PREFIX_H
#define __PREFIX_H
/* Prefix List Entry */
typedef struct _PREFIX_LIST_ENTRY {
DEFINE_TAG
LIST_ENTRY ListEntry; /* Entry on list */
ULONG RefCount; /* Reference count */
PIP_INTERFACE Interface; /* Pointer to interface */
PIP_ADDRESS Prefix; /* Pointer to prefix */
UINT PrefixLength; /* Length of prefix */
} PREFIX_LIST_ENTRY, *PPREFIX_LIST_ENTRY;
extern LIST_ENTRY PrefixListHead;
extern KSPIN_LOCK PrefixListLock;
VOID InitPLE();
PPREFIX_LIST_ENTRY CreatePLE(PIP_INTERFACE IF, PIP_ADDRESS Prefix, UINT Len);
VOID DestroyPLE(PPREFIX_LIST_ENTRY PLE);
VOID DestroyPLEs();
#endif/*__PREFIX_H*/

View file

@ -17,7 +17,6 @@ typedef struct _FIB_ENTRY {
OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */ OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */
PIP_ADDRESS NetworkAddress; /* Address of network */ PIP_ADDRESS NetworkAddress; /* Address of network */
PIP_ADDRESS Netmask; /* Netmask of network */ PIP_ADDRESS Netmask; /* Netmask of network */
PNET_TABLE_ENTRY NTE; /* Pointer to NTE to use */
PNEIGHBOR_CACHE_ENTRY Router; /* Pointer to NCE of router to use */ PNEIGHBOR_CACHE_ENTRY Router; /* Pointer to NCE of router to use */
UINT Metric; /* Cost of this route */ UINT Metric; /* Cost of this route */
} FIB_ENTRY, *PFIB_ENTRY; } FIB_ENTRY, *PFIB_ENTRY;
@ -34,7 +33,6 @@ PIP_INTERFACE RouterFindOnLinkInterface(
PFIB_ENTRY RouterAddRoute( PFIB_ENTRY RouterAddRoute(
PIP_ADDRESS NetworkAddress, PIP_ADDRESS NetworkAddress,
PIP_ADDRESS Netmask, PIP_ADDRESS Netmask,
PNET_TABLE_ENTRY NTE,
PNEIGHBOR_CACHE_ENTRY Router, PNEIGHBOR_CACHE_ENTRY Router,
UINT Metric); UINT Metric);
@ -58,6 +56,10 @@ NTSTATUS RouterStartup(
NTSTATUS RouterShutdown( NTSTATUS RouterShutdown(
VOID); VOID);
UINT CountFIBs();
UINT CopyFIBs( PFIB_ENTRY Target );
#endif /* __ROUTER_H */ #endif /* __ROUTER_H */
/* EOF */ /* EOF */

View file

@ -8,25 +8,7 @@
#define __ROUTINES_H #define __ROUTINES_H
inline NTSTATUS BuildDatagramSendRequest( UINT Random(VOID);
PDATAGRAM_SEND_REQUEST *SendRequest,
PIP_ADDRESS RemoteAddress,
USHORT RemotePort,
PNDIS_BUFFER Buffer,
DWORD BufferSize,
DATAGRAM_COMPLETION_ROUTINE Complete,
PVOID Context,
DATAGRAM_BUILD_ROUTINE Build,
ULONG Flags);
inline NTSTATUS BuildTCPSendRequest(
PTCP_SEND_REQUEST *SendRequest,
DATAGRAM_COMPLETION_ROUTINE Complete,
PVOID Context,
PVOID ProtocolContext);
UINT Random(
VOID);
UINT CopyBufferToBufferChain( UINT CopyBufferToBufferChain(
PNDIS_BUFFER DstBuffer, PNDIS_BUFFER DstBuffer,
@ -53,8 +35,10 @@ UINT CopyPacketToBufferChain(
UINT SrcOffset, UINT SrcOffset,
UINT Length); UINT Length);
VOID FreeNdisPacket( VOID FreeNdisPacketX(
PNDIS_PACKET Packet); PNDIS_PACKET Packet,
PCHAR File,
UINT Line);
PVOID AdjustPacket( PVOID AdjustPacket(
PNDIS_PACKET Packet, PNDIS_PACKET Packet,

View file

@ -35,6 +35,9 @@ typedef struct TCPv4_HEADER {
#define TCPOPTLEN_MAX_SEG_SIZE 0x4 #define TCPOPTLEN_MAX_SEG_SIZE 0x4
/* Data offset; 32-bit words (leftmost 4 bits); convert to bytes */
#define TCP_DATA_OFFSET(DataOffset)(((DataOffset) & 0xF0) >> (4-2))
/* TCPv4 pseudo header */ /* TCPv4 pseudo header */
typedef struct TCPv4_PSEUDO_HEADER { typedef struct TCPv4_PSEUDO_HEADER {
@ -70,10 +73,9 @@ typedef struct TCPv4_PSEUDO_HEADER {
#define SRF_SYN TCP_SYN #define SRF_SYN TCP_SYN
#define SRF_FIN TCP_FIN #define SRF_FIN TCP_FIN
PTCP_SEGMENT TCPCreateSegment( PTCP_SEGMENT TCPCreateSegment(
PIP_PACKET IPPacket, PIP_PACKET IPPacket,
ULONG SequenceNumber, PTCPv4_HEADER TCPHeader,
ULONG SegmentLength); ULONG SegmentLength);
VOID TCPFreeSegment( VOID TCPFreeSegment(
@ -81,25 +83,8 @@ VOID TCPFreeSegment(
VOID TCPAddSegment( VOID TCPAddSegment(
PCONNECTION_ENDPOINT Connection, PCONNECTION_ENDPOINT Connection,
PTCP_SEGMENT Segment); PTCP_SEGMENT Segment,
PULONG Acknowledged);
inline NTSTATUS TCPBuildSendRequest(
PTCP_SEND_REQUEST *SendRequest,
PDATAGRAM_SEND_REQUEST *DGSendRequest,
PCONNECTION_ENDPOINT Connection,
DATAGRAM_COMPLETION_ROUTINE Complete,
PVOID Context,
PNDIS_BUFFER Buffer,
DWORD BufferSize,
ULONG Flags);
inline NTSTATUS TCPBuildAndTransmitSendRequest(
PCONNECTION_ENDPOINT Connection,
DATAGRAM_COMPLETION_ROUTINE Complete,
PVOID Context,
PNDIS_BUFFER Buffer,
DWORD BufferSize,
ULONG Flags);
NTSTATUS TCPConnect( NTSTATUS TCPConnect(
PTDI_REQUEST Request, PTDI_REQUEST Request,
@ -108,10 +93,16 @@ NTSTATUS TCPConnect(
NTSTATUS TCPListen( NTSTATUS TCPListen(
PTDI_REQUEST Request, PTDI_REQUEST Request,
PTDI_CONNECTION_INFORMATION ConnInfo, UINT Backlog );
PTDI_CONNECTION_INFORMATION ReturnInfo);
NTSTATUS TCPSendDatagram( NTSTATUS TCPReceiveData(
PTDI_REQUEST Request,
PNDIS_BUFFER Buffer,
ULONG ReceiveLength,
ULONG ReceiveFlags,
PULONG BytesReceived);
NTSTATUS TCPSendData(
PTDI_REQUEST Request, PTDI_REQUEST Request,
PTDI_CONNECTION_INFORMATION ConnInfo, PTDI_CONNECTION_INFORMATION ConnInfo,
PNDIS_BUFFER Buffer, PNDIS_BUFFER Buffer,

View file

@ -63,6 +63,8 @@
#define MAX(value1, value2) \ #define MAX(value1, value2) \
((value1 > value2)? value1 : value2) ((value1 > value2)? value1 : value2)
#define NDIS_BUFFER_TAG FOURCC('n','b','u','f')
#define NDIS_PACKET_TAG FOURCC('n','p','k','t')
#ifdef i386 #ifdef i386
@ -110,6 +112,34 @@
#endif /* i386 */ #endif /* i386 */
typedef TDI_STATUS (*InfoRequest_f)( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize );
typedef TDI_STATUS (*InfoSet_f)( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize );
/* Sufficient information to manage the entity list */
typedef struct {
UINT tei_entity;
UINT tei_instance;
PVOID context;
InfoRequest_f info_req;
InfoSet_f info_set;
} TDIEntityInfo;
#ifndef htons
#define htons(x) (((x) << 16) | (((x) >> 8) & 0xff))
#endif
/* Global variable */ /* Global variable */
extern PDEVICE_OBJECT TCPDeviceObject; extern PDEVICE_OBJECT TCPDeviceObject;
@ -123,7 +153,7 @@ extern KSPIN_LOCK AddressFileListLock;
extern NDIS_HANDLE GlobalPacketPool; extern NDIS_HANDLE GlobalPacketPool;
extern NDIS_HANDLE GlobalBufferPool; extern NDIS_HANDLE GlobalBufferPool;
extern KSPIN_LOCK EntityListLock; extern KSPIN_LOCK EntityListLock;
extern TDIEntityID *EntityList; extern TDIEntityInfo *EntityList;
extern ULONG EntityCount; extern ULONG EntityCount;
extern ULONG EntityMax; extern ULONG EntityMax;
extern UDP_STATISTICS UDPStats; extern UDP_STATISTICS UDPStats;

View file

@ -65,7 +65,7 @@
#else /* DBG */ #else /* DBG */
#define DEFINE_TAG #define DEFINE_TAG
#define INIT_TAG (Object, Tag) #define INIT_TAG(Object, Tag)
/* /*
* VOID ReferenceObject( * VOID ReferenceObject(
@ -127,17 +127,18 @@ typedef NTSTATUS (*DATAGRAM_BUILD_ROUTINE)(
PIP_PACKET *IPPacket); PIP_PACKET *IPPacket);
typedef struct _DATAGRAM_SEND_REQUEST { typedef struct _DATAGRAM_SEND_REQUEST {
LIST_ENTRY ListEntry; /* Entry on list */ LIST_ENTRY ListEntry;
PIP_ADDRESS RemoteAddress; /* Pointer to remote IP address */ PNDIS_PACKET PacketToSend;
USHORT RemotePort; /* Remote port number */
PNDIS_BUFFER Buffer; /* Pointer to NDIS buffer to send */
DWORD BufferSize; /* Size of Buffer */
DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */ DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */
PVOID Context; /* Pointer to context information */ PVOID Context; /* Pointer to context information */
DATAGRAM_BUILD_ROUTINE Build; /* Datagram build routine */ IP_PACKET Packet;
UINT BufferSize;
IP_ADDRESS RemoteAddress;
USHORT RemotePort;
ULONG Flags; /* Protocol specific flags */ ULONG Flags; /* Protocol specific flags */
} DATAGRAM_SEND_REQUEST, *PDATAGRAM_SEND_REQUEST; } DATAGRAM_SEND_REQUEST, *PDATAGRAM_SEND_REQUEST;
#if 0
#define InitializeDatagramSendRequest( \ #define InitializeDatagramSendRequest( \
_SendRequest, \ _SendRequest, \
_RemoteAddress, \ _RemoteAddress, \
@ -157,6 +158,7 @@ typedef struct _DATAGRAM_SEND_REQUEST {
(_SendRequest)->Build = (_Build); \ (_SendRequest)->Build = (_Build); \
(_SendRequest)->Flags = (_Flags); \ (_SendRequest)->Flags = (_Flags); \
} }
#endif /* These things bug me... They hide the member names. */
/* Transport address file context structure. The FileObject->FsContext2 /* Transport address file context structure. The FileObject->FsContext2
field holds a pointer to this structure */ field holds a pointer to this structure */
@ -254,32 +256,17 @@ typedef struct _AF_SEARCH {
USHORT Protocol; /* Protocol number */ USHORT Protocol; /* Protocol number */
} AF_SEARCH, *PAF_SEARCH; } AF_SEARCH, *PAF_SEARCH;
/******************************************************* /*******************************************************
* Connection-oriented communication support structures * * Connection-oriented communication support structures *
*******************************************************/ *******************************************************/
typedef struct _TCP_SEND_REQUEST { typedef struct _TCP_RECEIVE_REQUEST {
LIST_ENTRY ListEntry; /* Entry on list */ LIST_ENTRY ListEntry; /* Entry on list */
PNDIS_BUFFER Buffer; /* Pointer to receive buffer */
ULONG BufferSize; /* Size of Buffer */
DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */ DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */
PVOID Context; /* Pointer to context information */ PVOID Context; /* Pointer to context information */
PVOID ProtocolContext; /* Protocol specific context */ } TCP_RECEIVE_REQUEST, *PTCP_RECEIVE_REQUEST;
ULONG Flags; /* Protocol specific flags */
ULONG SequenceNumber; /* Sequence number (network byte order) */
ULONG AckNumber; /* Acknowledgement number (network byte order) */
} TCP_SEND_REQUEST, *PTCP_SEND_REQUEST;
#define InitializeTCPSendRequest( \
_SendRequest, \
_Complete, \
_Context, \
_ProtocolContext) { \
(_SendRequest)->Complete = (_Complete); \
(_SendRequest)->Context = (_Context); \
(_SendRequest)->ProtocolContext = (_ProtocolContext); \
}
/* Connection states */ /* Connection states */
typedef enum { typedef enum {
@ -302,8 +289,10 @@ typedef enum {
typedef struct _TCP_SEGMENT { typedef struct _TCP_SEGMENT {
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
PIP_PACKET IPPacket; /* Pointer to IP packet */ PIP_PACKET IPPacket; /* Pointer to IP packet */
PVOID SegmentData; /* Pointer to segment data */
ULONG SequenceNumber; /* Sequence number of first byte in segment */ ULONG SequenceNumber; /* Sequence number of first byte in segment */
ULONG Length; /* Number of bytes in segment */ ULONG Length; /* Number of bytes in segment */
ULONG BytesDelivered; /* Number of bytes already delivered to the client */
} TCP_SEGMENT, *PTCP_SEGMENT; } TCP_SEGMENT, *PTCP_SEGMENT;
@ -316,15 +305,16 @@ typedef struct _CONNECTION_ENDPOINT {
ULONG RefCount; /* Number of references to this object */ ULONG RefCount; /* Number of references to this object */
PVOID ClientContext; /* Pointer to client context information */ PVOID ClientContext; /* Pointer to client context information */
PADDRESS_FILE AddressFile; /* Associated address file object (NULL if none) */ PADDRESS_FILE AddressFile; /* Associated address file object (NULL if none) */
PVOID SocketContext; /* Context for lower layer */
CONNECTION_STATE State; /* Connection state */ #if 0
PIP_ADDRESS LocalAddress; /* Pointer to local IP address */ PIP_ADDRESS LocalAddress; /* Pointer to local IP address */
USHORT LocalPort; /* Local port number (network byte order) */ USHORT LocalPort; /* Local port number (network byte order) */
PIP_ADDRESS RemoteAddress; /* Pointer to remote IP address */ PIP_ADDRESS RemoteAddress; /* Pointer to remote IP address */
USHORT RemotePort; /* Remote port number (network byte order) */ USHORT RemotePort; /* Remote port number (network byte order) */
CONNECTION_STATE State; /* Connection state */
/* Send sequence variables */ /* Send sequence variables */
ULONG SendUnacknowledged; /* Highest sequence number that is acknowledged */ ULONG SendUnacknowledged; /* Highest sequence number that is acknowledged */
ULONG SendNext; /* Sequence number of last data block sent */ ULONG SendNext; /* Sequence number of last data block sent */
@ -335,20 +325,23 @@ typedef struct _CONNECTION_ENDPOINT {
ULONG SendISS; /* Initial send sequence number */ ULONG SendISS; /* Initial send sequence number */
/* Receive sequence variables */ /* Receive sequence variables */
ULONG ReceiveNext; /* Sequence number of last data block received */ ULONG ReceiveNext; /* Next sequence number expected and start of receive window */
ULONG ReceiveWindow; /* Maximum allowed number of octets in a segment */ ULONG ReceiveWindow; /* Maximum allowed number of octets in a segment */
ULONG ReceiveUrgentPointer; /* Sequence number of start of urgent data */ ULONG ReceiveUrgentPointer; /* Sequence number of start of urgent data */
ULONG ReceiveIRS; /* Initial receive sequence number */ ULONG ReceiveIRS; /* Initial receive sequence number */
ULONG ReceiveDelivered; /* Next sequence number to be delivered to the client */
/* Statistics for computing the retransmission timeout */ /* Statistics for computing the retransmission timeout */
ULONG TimestampSend; /* Timestamp when sending a segment */ ULONG TimestampSend; /* Timestamp when sending a segment */
ULONG TimestampAck; /* Timestamp when receiving acknowledgment */ ULONG TimestampAck; /* Timestamp when receiving acknowledgment */
#endif
/* Requests */ /* Requests */
PTDI_REQUEST ListenRequest; /* Queued listen request */ PTDI_REQUEST ListenRequest; /* Queued listen request */
LIST_ENTRY ReceiveRequests; /* Queued receive requests */
/* Queues */ /* Queues */
LIST_ENTRY ReceivedSegments; LIST_ENTRY ReceivedSegments;/* Segments that are received */
} CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT; } CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.16 2004/03/04 20:45:38 chorns Exp $ # $Id: makefile,v 1.17 2004/06/09 18:11:37 arty Exp $
PATH_TO_TOP = ../../.. PATH_TO_TOP = ../../..
@ -8,9 +8,16 @@ TARGET_TYPE = export_driver
TARGET_NAME = tcpip TARGET_NAME = tcpip
TARGET_CFLAGS = -I./include -DDBG=1 -DNDIS40 -D__USE_W32API TARGET_CFLAGS = \
-D__USE_W32API \
-DNDIS40 \
-DMEMTRACK \
-I./include \
-I$(PATH_TO_TOP)/drivers/lib/oskittcp/include \
-I$(PATH_TO_TOP)/w32api/include \
-I$(PATH_TO_TOP)/include
TARGET_DDKLIBS = ndis.a TARGET_DDKLIBS = ndis.a $(PATH_TO_TOP)/dk/w32/lib/oskittcp.a
TARGET_CLEAN = \ TARGET_CLEAN = \
tcpip/*.o \ tcpip/*.o \
@ -19,32 +26,35 @@ TARGET_CLEAN = \
transport/datagram/*.o \ transport/datagram/*.o \
transport/rawip/*.o \ transport/rawip/*.o \
transport/tcp/*.o \ transport/tcp/*.o \
transport/udp/*.o transport/udp/*.o
TCPIP_OBJECTS = tcpip/main.o tcpip/address.o tcpip/checksum.o \ TCPIP_OBJECTS = tcpip/main.o tcpip/address.o tcpip/checksum.o \
tcpip/dispatch.o tcpip/fileobjs.o tcpip/info.o \ tcpip/dispatch.o tcpip/fileobjs.o \
tcpip/pool.o tcpip/routines.o tcpip/pool.o tcpip/routines.o tcpip/interface.o \
tcpip/memtrack.o tcpip/irp.o
INFO_OBJECTS = tcpip/info.o tcpip/ninfo.o tcpip/tinfo.o tcpip/iinfo.o
DATALINK_OBJECTS = datalink/arp.o datalink/lan.o datalink/loopback.o DATALINK_OBJECTS = datalink/arp.o datalink/lan.o datalink/loopback.o
NETWORK_OBJECTS = network/icmp.o network/ip.o network/neighbor.o \ NETWORK_OBJECTS = network/icmp.o network/ip.o network/neighbor.o \
network/receive.o network/route.o network/router.o \ network/receive.o network/route.o network/router.o \
network/transmit.o network/transmit.o network/prefix.o
DATAGRAM_OBJECTS = transport/datagram/datagram.o DATAGRAM_OBJECTS = transport/datagram/datagram.o
RAWIP_OBJECTS = transport/rawip/rawip.o RAWIP_OBJECTS = transport/rawip/rawip.o
TCP_OBJECTS = transport/tcp/tcp.o transport/tcp/tcpcore.o \ TCP_OBJECTS = transport/tcp/tcp.o transport/tcp/event.o transport/tcp/if.o
transport/tcp/tcp_input.o transport/tcp/tcp_ipv4.o \
transport/tcp/tcp_output.o transport/tcp/tcp_timer.o
UDP_OBJECTS = transport/udp/udp.o UDP_OBJECTS = transport/udp/udp.o
ARCH_OBJECTS = tcpip/i386/checksum.o ARCH_OBJECTS = tcpip/i386/checksum.o
TARGET_OBJECTS = \ TARGET_OBJECTS = \
$(TCPIP_OBJECTS) \ $(TCPIP_OBJECTS) \
$(INFO_OBJECTS) \
$(DATALINK_OBJECTS) \ $(DATALINK_OBJECTS) \
$(NETWORK_OBJECTS) \ $(NETWORK_OBJECTS) \
$(DATAGRAM_OBJECTS) \ $(DATAGRAM_OBJECTS) \
$(RAWIP_OBJECTS) \ $(RAWIP_OBJECTS) \
$(TCP_OBJECTS) \ $(TCP_OBJECTS) \
$(FREEBSD_OBJECTS) \
$(REACTOS_OBJECTS) \
$(UDP_OBJECTS) \ $(UDP_OBJECTS) \
$(ARCH_OBJECTS) $(ARCH_OBJECTS) \
include $(PATH_TO_TOP)/rules.mak include $(PATH_TO_TOP)/rules.mak

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <icmp.h> #include <icmp.h>
#include <rawip.h> #include <rawip.h>
@ -38,8 +39,6 @@ VOID SendICMPComplete(
FreeNdisPacket(Packet); FreeNdisPacket(Packet);
TI_DbgPrint(DEBUG_ICMP, ("Freeing IP packet at %X.\n", IPPacket)); TI_DbgPrint(DEBUG_ICMP, ("Freeing IP packet at %X.\n", IPPacket));
(*IPPacket->Free)(IPPacket);
} }
@ -79,9 +78,8 @@ PIP_PACKET PrepareICMPPacket(
Size = MaxLLHeaderSize + sizeof(IPv4_HEADER) + Size = MaxLLHeaderSize + sizeof(IPv4_HEADER) +
sizeof(ICMP_HEADER) + DataSize; sizeof(ICMP_HEADER) + DataSize;
DataBuffer = ExAllocatePool(NonPagedPool, Size); DataBuffer = exAllocatePool(NonPagedPool, Size);
if (!DataBuffer) { if (!DataBuffer) {
(*IPPacket->Free)(IPPacket);
return NULL; return NULL;
} }
@ -90,10 +88,10 @@ PIP_PACKET PrepareICMPPacket(
/* Allocate NDIS packet */ /* Allocate NDIS packet */
NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool); NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool);
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
(*IPPacket->Free)(IPPacket); exFreePool(DataBuffer);
ExFreePool(DataBuffer);
return NULL; return NULL;
} }
Track(NDIS_PACKET_TAG,NdisPacket);
TI_DbgPrint(MAX_TRACE, ("NdisPacket at (0x%X).\n", NdisPacket)); TI_DbgPrint(MAX_TRACE, ("NdisPacket at (0x%X).\n", NdisPacket));
@ -101,12 +99,12 @@ PIP_PACKET PrepareICMPPacket(
NdisAllocateBuffer(&NdisStatus, &NdisBuffer, GlobalBufferPool, NdisAllocateBuffer(&NdisStatus, &NdisBuffer, GlobalBufferPool,
DataBuffer, Size); DataBuffer, Size);
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
(*IPPacket->Free)(IPPacket); FreeNdisPacket(NdisPacket);
NdisFreePacket(NdisPacket); exFreePool(DataBuffer);
ExFreePool(DataBuffer);
return NULL; return NULL;
} }
Track(NDIS_BUFFER_TAG,NdisBuffer);
TI_DbgPrint(MAX_TRACE, ("NdisBuffer at (0x%X).\n", NdisBuffer)); TI_DbgPrint(MAX_TRACE, ("NdisBuffer at (0x%X).\n", NdisBuffer));
/* Link NDIS buffer into packet */ /* Link NDIS buffer into packet */
@ -202,9 +200,10 @@ VOID ICMPReceive(
((PICMP_HEADER)NewPacket->Data)->Code = 0; ((PICMP_HEADER)NewPacket->Data)->Code = 0;
((PICMP_HEADER)NewPacket->Data)->Checksum = 0; ((PICMP_HEADER)NewPacket->Data)->Checksum = 0;
#ifdef DBG
DisplayIPPacket(IPPacket); DisplayIPPacket(IPPacket);
DisplayIPPacket(NewPacket); DisplayIPPacket(NewPacket);
#endif
ICMPTransmit(NTE, NewPacket); ICMPTransmit(NTE, NewPacket);
@ -245,11 +244,11 @@ VOID ICMPTransmit(
IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0); IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0);
/* Get a route to the destination address */ /* Get a route to the destination address */
PNEIGHBOR_CACHE_ENTRY *NCE = RouterGetRoute( &IPPacket->DstAddr, NULL );
if (RouteGetRouteToDestination(&IPPacket->DstAddr, NTE, &RCN) == IP_SUCCESS) { if (RouteGetRouteToDestination(&IPPacket->DstAddr, NTE, &RCN) == IP_SUCCESS) {
/* Send the packet */ /* Send the packet */
if (IPSendDatagram(IPPacket, RCN) != STATUS_SUCCESS) { if (IPSendDatagram(IPPacket, RCN) != STATUS_SUCCESS) {
FreeNdisPacket(IPPacket->NdisPacket); FreeNdisPacket(IPPacket->NdisPacket);
(*IPPacket->Free)(IPPacket);
} }
/* We're done with the RCN */ /* We're done with the RCN */
DereferenceObject(RCN); DereferenceObject(RCN);
@ -261,7 +260,6 @@ VOID ICMPTransmit(
IPPacket->DstAddr.Address.IPv4Address)); IPPacket->DstAddr.Address.IPv4Address));
/* Discard packet */ /* Discard packet */
FreeNdisPacket(IPPacket->NdisPacket); FreeNdisPacket(IPPacket->NdisPacket);
(*IPPacket->Free)(IPPacket);
} }
} }

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <ip.h> #include <ip.h>
#include <tcp.h> #include <tcp.h>
@ -14,6 +15,7 @@
#include <neighbor.h> #include <neighbor.h>
#include <receive.h> #include <receive.h>
#include <address.h> #include <address.h>
#include <prefix.h>
#include <route.h> #include <route.h>
#include <icmp.h> #include <icmp.h>
#include <pool.h> #include <pool.h>
@ -25,8 +27,6 @@ LIST_ENTRY InterfaceListHead;
KSPIN_LOCK InterfaceListLock; KSPIN_LOCK InterfaceListLock;
LIST_ENTRY NetTableListHead; LIST_ENTRY NetTableListHead;
KSPIN_LOCK NetTableListLock; KSPIN_LOCK NetTableListLock;
LIST_ENTRY PrefixListHead;
KSPIN_LOCK PrefixListLock;
UINT MaxLLHeaderSize; /* Largest maximum header size */ UINT MaxLLHeaderSize; /* Largest maximum header size */
UINT MinLLFrameSize; /* Largest minimum frame size */ UINT MinLLFrameSize; /* Largest minimum frame size */
BOOLEAN IPInitialized = FALSE; BOOLEAN IPInitialized = FALSE;
@ -47,6 +47,17 @@ VOID FreePacket(
} }
VOID DontFreePacket(
PVOID Object)
/*
* FUNCTION: Do nothing for when the IPPacket struct is part of another
* ARGUMENTS:
* Object = Pointer to an IP packet structure
*/
{
}
VOID FreeADE( VOID FreeADE(
PVOID Object) PVOID Object)
/* /*
@ -55,7 +66,7 @@ VOID FreeADE(
* Object = Pointer to an address entry structure * Object = Pointer to an address entry structure
*/ */
{ {
ExFreePool(Object); exFreePool(Object);
} }
@ -67,7 +78,7 @@ VOID FreeNTE(
* Object = Pointer to an net table entry structure * Object = Pointer to an net table entry structure
*/ */
{ {
ExFreePool(Object); exFreePool(Object);
} }
@ -79,7 +90,7 @@ VOID FreeIF(
* Object = Pointer to an interface structure * Object = Pointer to an interface structure
*/ */
{ {
ExFreePool(Object); exFreePool(Object);
} }
@ -114,7 +125,7 @@ PADDRESS_ENTRY CreateADE(
A2S(Address), A2S(NTE->Address))); A2S(Address), A2S(NTE->Address)));
/* Allocate space for an ADE and set it up */ /* Allocate space for an ADE and set it up */
ADE = ExAllocatePool(NonPagedPool, sizeof(ADDRESS_ENTRY)); ADE = exAllocatePool(NonPagedPool, sizeof(ADDRESS_ENTRY));
if (!ADE) { if (!ADE) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NULL; return NULL;
@ -221,119 +232,35 @@ PIP_PACKET IPCreatePacket(
INIT_TAG(IPPacket, TAG('I','P','K','T')); INIT_TAG(IPPacket, TAG('I','P','K','T'));
IPPacket->Free = FreePacket; IPPacket->Free = FreePacket;
IPPacket->RefCount = 1; IPPacket->RefCount = 1;
IPPacket->Type = Type; IPPacket->Type = Type;
IPPacket->HeaderSize = 20;
return IPPacket; return IPPacket;
} }
PIP_PACKET IPInitializePacket(
PPREFIX_LIST_ENTRY CreatePLE( PIP_PACKET IPPacket,
PIP_INTERFACE IF, ULONG Type)
PIP_ADDRESS Prefix,
UINT Length)
/* /*
* FUNCTION: Creates a prefix list entry and binds it to an interface * FUNCTION: Creates an IP packet object
* ARGUMENTS: * ARGUMENTS:
* IF = Pointer to interface * Type = Type of IP packet
* Prefix = Pointer to prefix
* Length = Length of prefix
* RETURNS: * RETURNS:
* Pointer to PLE, NULL if there was not enough free resources * Pointer to the created IP packet. NULL if there was not enough free resources.
* NOTES:
* The prefix list entry retains a reference to the interface and
* the provided address. The caller is responsible for providing
* these references
*/ */
{ {
PPREFIX_LIST_ENTRY PLE; /* FIXME: Is this needed? */
RtlZeroMemory(IPPacket, sizeof(IP_PACKET));
TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X) Prefix (0x%X) Length (%d).\n", IF, Prefix, Length));
INIT_TAG(IPPacket, TAG('I','P','K','T'));
TI_DbgPrint(DEBUG_IP, ("Prefix (%s).\n", A2S(Prefix)));
IPPacket->Free = DontFreePacket;
/* Allocate space for an PLE and set it up */ IPPacket->RefCount = 1;
PLE = ExAllocatePool(NonPagedPool, sizeof(PREFIX_LIST_ENTRY)); IPPacket->Type = Type;
if (!PLE) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); return IPPacket;
return NULL;
}
INIT_TAG(PLE, TAG('P','L','E',' '));
PLE->RefCount = 1;
PLE->Interface = IF;
PLE->Prefix = Prefix;
PLE->PrefixLength = Length;
/* Add PLE to the global prefix list */
ExInterlockedInsertTailList(&PrefixListHead, &PLE->ListEntry, &PrefixListLock);
return PLE;
}
VOID DestroyPLE(
PPREFIX_LIST_ENTRY PLE)
/*
* FUNCTION: Destroys an prefix list entry
* ARGUMENTS:
* PLE = Pointer to prefix list entry
* NOTES:
* The prefix list lock must be held when called
*/
{
TI_DbgPrint(DEBUG_IP, ("Called. PLE (0x%X).\n", PLE));
TI_DbgPrint(DEBUG_IP, ("PLE (%s).\n", PLE->Prefix));
/* Unlink the prefix list entry from the list */
RemoveEntryList(&PLE->ListEntry);
/* Dereference the address */
DereferenceObject(PLE->Prefix);
/* Dereference the interface */
DereferenceObject(PLE->Interface);
#ifdef DBG
PLE->RefCount--;
if (PLE->RefCount != 0) {
TI_DbgPrint(MIN_TRACE, ("Prefix list entry at (0x%X) has (%d) references (should be 0).\n", PLE, PLE->RefCount));
}
#endif
/* And free the PLE */
ExFreePool(PLE);
}
VOID DestroyPLEs(
VOID)
/*
* FUNCTION: Destroys all prefix list entries
*/
{
KIRQL OldIrql;
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
PPREFIX_LIST_ENTRY Current;
TI_DbgPrint(DEBUG_IP, ("Called.\n"));
KeAcquireSpinLock(&PrefixListLock, &OldIrql);
/* Search the list and remove every PLE we find */
CurrentEntry = PrefixListHead.Flink;
while (CurrentEntry != &PrefixListHead) {
NextEntry = CurrentEntry->Flink;
Current = CONTAINING_RECORD(CurrentEntry, PREFIX_LIST_ENTRY, ListEntry);
/* Destroy the PLE */
DestroyPLE(Current);
CurrentEntry = NextEntry;
}
KeReleaseSpinLock(&PrefixListLock, OldIrql);
} }
@ -364,7 +291,7 @@ PNET_TABLE_ENTRY IPCreateNTE(
TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address))); TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address)));
/* Allocate room for an NTE */ /* Allocate room for an NTE */
NTE = ExAllocatePool(NonPagedPool, sizeof(NET_TABLE_ENTRY)); NTE = exAllocatePool(NonPagedPool, sizeof(NET_TABLE_ENTRY));
if (!NTE) { if (!NTE) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NULL; return NULL;
@ -392,7 +319,7 @@ PNET_TABLE_ENTRY IPCreateNTE(
ADE = CreateADE(IF, NTE->Address, ADE_UNICAST, NTE); ADE = CreateADE(IF, NTE->Address, ADE_UNICAST, NTE);
if (!ADE) { if (!ADE) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
ExFreePool(NTE); exFreePool(NTE);
return NULL; return NULL;
} }
@ -400,7 +327,7 @@ PNET_TABLE_ENTRY IPCreateNTE(
NTE->PLE = CreatePLE(IF, NTE->Address, PrefixLength); NTE->PLE = CreatePLE(IF, NTE->Address, PrefixLength);
if (!NTE->PLE) { if (!NTE->PLE) {
DestroyADE(IF, ADE); DestroyADE(IF, ADE);
ExFreePool(NTE); exFreePool(NTE);
return NULL; return NULL;
} }
@ -462,7 +389,7 @@ VOID DestroyNTE(
} }
#endif #endif
/* And free the NTE */ /* And free the NTE */
ExFreePool(NTE); exFreePool(NTE);
} }
@ -792,7 +719,7 @@ PIP_INTERFACE IPCreateInterface(
} }
#endif #endif
IF = ExAllocatePool(NonPagedPool, sizeof(IP_INTERFACE)); IF = exAllocatePool(NonPagedPool, sizeof(IP_INTERFACE));
if (!IF) { if (!IF) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NULL; return NULL;
@ -821,6 +748,8 @@ PIP_INTERFACE IPCreateInterface(
KeInitializeSpinLock(&IF->Lock); KeInitializeSpinLock(&IF->Lock);
InsertTDIInterfaceEntity( IF );
return IF; return IF;
} }
@ -838,6 +767,8 @@ VOID IPDestroyInterface(
TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF)); TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF));
RemoveTDIInterfaceEntity( IF );
KeAcquireSpinLock(&NetTableListLock, &OldIrql1); KeAcquireSpinLock(&NetTableListLock, &OldIrql1);
KeAcquireSpinLock(&IF->Lock, &OldIrql2); KeAcquireSpinLock(&IF->Lock, &OldIrql2);
DestroyADEs(IF); DestroyADEs(IF);
@ -852,7 +783,8 @@ VOID IPDestroyInterface(
TI_DbgPrint(MIN_TRACE, ("Interface at (0x%X) has (%d) references (should be 0).\n", IF, IF->RefCount)); TI_DbgPrint(MIN_TRACE, ("Interface at (0x%X) has (%d) references (should be 0).\n", IF, IF->RefCount));
} }
#endif #endif
ExFreePool(IF);
exFreePool(IF);
} }
@ -891,30 +823,29 @@ BOOLEAN IPRegisterInterface(
KeReleaseSpinLock(&IF->Lock, OldIrql); KeReleaseSpinLock(&IF->Lock, OldIrql);
return FALSE; return FALSE;
} }
#if 1
/* Reference objects for forward information base */ /* Reference objects for forward information base */
ReferenceObject(Current->Address); ReferenceObject(Current->Address);
ReferenceObject(Current->PLE->Prefix); ReferenceObject(Current->PLE->Prefix);
ReferenceObject(Current); ReferenceObject(NCE);
/* NCE is already referenced */ /* NCE is already referenced */
if (!RouterAddRoute(Current->Address, Current->PLE->Prefix, Current, NCE, 1)) { if (!RouterAddRoute(Current->Address, Current->PLE->Prefix, NCE, 1)) {
TI_DbgPrint(MIN_TRACE, ("Could not add route due to insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Could not add route due to insufficient resources.\n"));
DereferenceObject(Current->Address); DereferenceObject(Current->Address);
DereferenceObject(Current->PLE->Prefix); DereferenceObject(Current->PLE->Prefix);
DereferenceObject(Current);
DereferenceObject(NCE); DereferenceObject(NCE);
} }
#else
RCN = RouteAddRouteToDestination(Current->Address, Current, IF, NCE); RCN = RouteAddRouteToDestination(Current->Address, Current, IF, NCE);
if (!RCN) { if (!RCN) {
TI_DbgPrint(MIN_TRACE, ("Could not create RCN.\n")); TI_DbgPrint(MIN_TRACE, ("Could not create RCN.\n"));
DereferenceObject(Current->Address); DereferenceObject(Current->Address);
KeReleaseSpinLock(&IF->Lock, OldIrql); KeReleaseSpinLock(&IF->Lock, OldIrql);
return FALSE;
} }
/* Don't need this any more since the route cache references the NCE */ /* Don't need this any more since the route cache references the NCE */
DereferenceObject(NCE); DereferenceObject(NCE);
#endif
CurrentEntry = CurrentEntry->Flink; CurrentEntry = CurrentEntry->Flink;
} }
@ -1096,9 +1027,7 @@ NTSTATUS IPStartup(
InitializeListHead(&ReassemblyListHead); InitializeListHead(&ReassemblyListHead);
KeInitializeSpinLock(&ReassemblyListLock); KeInitializeSpinLock(&ReassemblyListLock);
/* Initialize the prefix list and protecting lock */ InitPLE();
InitializeListHead(&PrefixListHead);
KeInitializeSpinLock(&PrefixListLock);
/* Initialize our periodic timer and its associated DPC object. When the /* Initialize our periodic timer and its associated DPC object. When the
timer expires, the IPTimeout deferred procedure call (DPC) is queued */ timer expires, the IPTimeout deferred procedure call (DPC) is queued */

View file

@ -7,10 +7,10 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <neighbor.h> #include <neighbor.h>
#include <routines.h> #include <routines.h>
#include <neighbor.h>
#include <transmit.h> #include <transmit.h>
#include <address.h> #include <address.h>
#include <route.h> #include <route.h>
@ -186,7 +186,7 @@ VOID NBShutdown(
NdisPacket = NextNdisPacket; NdisPacket = NextNdisPacket;
} }
#if DBG #ifdef DBG
if (CurNCE->RefCount != 1) if (CurNCE->RefCount != 1)
{ {
TI_DbgPrint(DEBUG_REFCOUNT, ("NCE at (0x%X) has (%d) references (should be 1).\n", CurNCE, CurNCE->RefCount)); TI_DbgPrint(DEBUG_REFCOUNT, ("NCE at (0x%X) has (%d) references (should be 1).\n", CurNCE, CurNCE->RefCount));
@ -293,7 +293,7 @@ PNEIGHBOR_CACHE_ENTRY NBAddNeighbor(
NCE->Interface = Interface; NCE->Interface = Interface;
NCE->Address = Address; NCE->Address = Address;
NCE->LinkAddressLength = LinkAddressLength; NCE->LinkAddressLength = LinkAddressLength;
NCE->LinkAddress = (PVOID)((ULONG_PTR)NCE + sizeof(NEIGHBOR_CACHE_ENTRY)); NCE->LinkAddress = (PVOID)&NCE[1];
if (LinkAddress != NULL) if (LinkAddress != NULL)
{ {
RtlCopyMemory(NCE->LinkAddress, LinkAddress, LinkAddressLength); RtlCopyMemory(NCE->LinkAddress, LinkAddress, LinkAddressLength);
@ -524,7 +524,7 @@ VOID NBRemoveNeighbor(
/* Remove reference to the address */ /* Remove reference to the address */
DereferenceObject(CurNCE->Address); DereferenceObject(CurNCE->Address);
#if DBG #ifdef DBG
CurNCE->RefCount--; CurNCE->RefCount--;
if (CurNCE->RefCount != 0) if (CurNCE->RefCount != 0)

View file

@ -0,0 +1,139 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: network/ip.c
* PURPOSE: Internet Protocol module
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Art Yerkes (arty@users.sourceforge.net)
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <ip.h>
#include <tcp.h>
#include <loopback.h>
#include <neighbor.h>
#include <receive.h>
#include <address.h>
#include <route.h>
#include <icmp.h>
#include <prefix.h>
#include <pool.h>
LIST_ENTRY PrefixListHead;
KSPIN_LOCK PrefixListLock;
/* --------- The Prefix List ---------- */
VOID InitPLE() {
/* Initialize the prefix list and protecting lock */
InitializeListHead(&PrefixListHead);
KeInitializeSpinLock(&PrefixListLock);
}
PPREFIX_LIST_ENTRY CreatePLE(PIP_INTERFACE IF, PIP_ADDRESS Prefix, UINT Length)
/*
* FUNCTION: Creates a prefix list entry and binds it to an interface
* ARGUMENTS:
* IF = Pointer to interface
* Prefix = Pointer to prefix
* Length = Length of prefix
* RETURNS:
* Pointer to PLE, NULL if there was not enough free resources
* NOTES:
* The prefix list entry retains a reference to the interface and
* the provided address. The caller is responsible for providing
* these references
*/
{
PPREFIX_LIST_ENTRY PLE;
TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X) Prefix (0x%X) Length (%d).\n", IF, Prefix, Length));
TI_DbgPrint(DEBUG_IP, ("Prefix (%s).\n", A2S(Prefix)));
/* Allocate space for an PLE and set it up */
PLE = ExAllocatePool(NonPagedPool, sizeof(PREFIX_LIST_ENTRY));
if (!PLE) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NULL;
}
INIT_TAG(PLE, TAG('P','L','E',' '));
PLE->RefCount = 1;
PLE->Interface = IF;
PLE->Prefix = Prefix;
PLE->PrefixLength = Length;
/* Add PLE to the global prefix list */
ExInterlockedInsertTailList(&PrefixListHead, &PLE->ListEntry, &PrefixListLock);
return PLE;
}
VOID DestroyPLE(
PPREFIX_LIST_ENTRY PLE)
/*
* FUNCTION: Destroys an prefix list entry
* ARGUMENTS:
* PLE = Pointer to prefix list entry
* NOTES:
* The prefix list lock must be held when called
*/
{
TI_DbgPrint(DEBUG_IP, ("Called. PLE (0x%X).\n", PLE));
TI_DbgPrint(DEBUG_IP, ("PLE (%s).\n", PLE->Prefix));
/* Unlink the prefix list entry from the list */
RemoveEntryList(&PLE->ListEntry);
/* Dereference the address */
DereferenceObject(PLE->Prefix);
/* Dereference the interface */
DereferenceObject(PLE->Interface);
#ifdef DBG
PLE->RefCount--;
if (PLE->RefCount != 0) {
TI_DbgPrint(MIN_TRACE, ("Prefix list entry at (0x%X) has (%d) references (should be 0).\n", PLE, PLE->RefCount));
}
#endif
/* And free the PLE */
ExFreePool(PLE);
}
VOID DestroyPLEs(
VOID)
/*
* FUNCTION: Destroys all prefix list entries
*/
{
KIRQL OldIrql;
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
PPREFIX_LIST_ENTRY Current;
TI_DbgPrint(DEBUG_IP, ("Called.\n"));
KeAcquireSpinLock(&PrefixListLock, &OldIrql);
/* Search the list and remove every PLE we find */
CurrentEntry = PrefixListHead.Flink;
while (CurrentEntry != &PrefixListHead) {
NextEntry = CurrentEntry->Flink;
Current = CONTAINING_RECORD(CurrentEntry, PREFIX_LIST_ENTRY, ListEntry);
/* Destroy the PLE */
DestroyPLE(Current);
CurrentEntry = NextEntry;
}
KeReleaseSpinLock(&PrefixListLock, OldIrql);
}

View file

@ -9,6 +9,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <receive.h> #include <receive.h>
#include <routines.h> #include <routines.h>
@ -100,7 +101,7 @@ VOID FreeIPDR(
TI_DbgPrint(DEBUG_IP, ("Freeing fragment data at (0x%X).\n", CurrentF->Data)); TI_DbgPrint(DEBUG_IP, ("Freeing fragment data at (0x%X).\n", CurrentF->Data));
/* Free the fragment data buffer */ /* Free the fragment data buffer */
ExFreePool(CurrentF->Data); exFreePool(CurrentF->Data);
TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF)); TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF));
@ -112,7 +113,7 @@ VOID FreeIPDR(
/* Free resources for the header, if it exists */ /* Free resources for the header, if it exists */
if (IPDR->IPv4Header) { if (IPDR->IPv4Header) {
TI_DbgPrint(DEBUG_IP, ("Freeing IPv4 header data at (0x%X).\n", IPDR->IPv4Header)); TI_DbgPrint(DEBUG_IP, ("Freeing IPv4 header data at (0x%X).\n", IPDR->IPv4Header));
ExFreePool(IPDR->IPv4Header); exFreePool(IPDR->IPv4Header);
} }
TI_DbgPrint(DEBUG_IP, ("Freeing IPDR data at (0x%X).\n", IPDR)); TI_DbgPrint(DEBUG_IP, ("Freeing IPDR data at (0x%X).\n", IPDR));
@ -201,6 +202,11 @@ PIP_PACKET ReassembleDatagram(
PVOID Data; PVOID Data;
TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR)); TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR));
TI_DbgPrint(DEBUG_IP, ("IPDR->HeaderSize = %d\n", IPDR->HeaderSize));
TI_DbgPrint(DEBUG_IP, ("IPDR->DataSize = %d\n", IPDR->DataSize));
TI_DbgPrint(DEBUG_IP, ("Fragment header:\n"));
OskitDumpBuffer(IPDR->IPv4Header, IPDR->HeaderSize);
/* FIXME: Assume IPv4 */ /* FIXME: Assume IPv4 */
IPPacket = IPCreatePacket(IP_ADDRESS_V4); IPPacket = IPCreatePacket(IP_ADDRESS_V4);
@ -216,7 +222,7 @@ PIP_PACKET ReassembleDatagram(
RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS)); RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS));
/* Allocate space for full IP datagram */ /* Allocate space for full IP datagram */
IPPacket->Header = ExAllocatePool(NonPagedPool, IPPacket->TotalSize); IPPacket->Header = exAllocatePool(NonPagedPool, IPPacket->TotalSize);
if (!IPPacket->Header) { if (!IPPacket->Header) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
(*IPPacket->Free)(IPPacket); (*IPPacket->Free)(IPPacket);
@ -226,7 +232,7 @@ PIP_PACKET ReassembleDatagram(
/* Copy the header into the buffer */ /* Copy the header into the buffer */
RtlCopyMemory(IPPacket->Header, IPDR->IPv4Header, IPDR->HeaderSize); RtlCopyMemory(IPPacket->Header, IPDR->IPv4Header, IPDR->HeaderSize);
Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPDR->HeaderSize); Data = IPPacket->Header + IPDR->HeaderSize;
IPPacket->Data = Data; IPPacket->Data = Data;
/* Copy data from all fragments into buffer */ /* Copy data from all fragments into buffer */
@ -237,11 +243,10 @@ PIP_PACKET ReassembleDatagram(
TI_DbgPrint(DEBUG_IP, ("Copying (%d) bytes of fragment data from (0x%X) to offset (%d).\n", TI_DbgPrint(DEBUG_IP, ("Copying (%d) bytes of fragment data from (0x%X) to offset (%d).\n",
Current->Size, Data, Current->Offset)); Current->Size, Data, Current->Offset));
/* Copy fragment data to the destination buffer at the correct offset */ /* Copy fragment data to the destination buffer at the correct offset */
RtlCopyMemory( RtlCopyMemory((PVOID)((ULONG_PTR)Data + Current->Offset),
(PVOID)((ULONG_PTR)Data + Current->Offset), Current->Data,
Current->Data, Current->Size);
Current->Size); OskitDumpBuffer( Data, Current->Offset + Current->Size );
CurrentEntry = CurrentEntry->Flink; CurrentEntry = CurrentEntry->Flink;
} }
@ -269,7 +274,7 @@ __inline VOID Cleanup(
RemoveIPDR(IPDR); RemoveIPDR(IPDR);
FreeIPDR(IPDR); FreeIPDR(IPDR);
if (Buffer) if (Buffer)
ExFreePool(Buffer); exFreePool(Buffer);
} }
@ -399,7 +404,7 @@ VOID ProcessFragment(
/* If this is the first fragment, save the IP header */ /* If this is the first fragment, save the IP header */
if (FragFirst == 0) { if (FragFirst == 0) {
IPDR->IPv4Header = ExAllocatePool(NonPagedPool, IPPacket->HeaderSize); IPDR->IPv4Header = exAllocatePool(NonPagedPool, IPPacket->HeaderSize);
if (!IPDR->IPv4Header) { if (!IPDR->IPv4Header) {
/* We don't have the resources to process this packet, discard it */ /* We don't have the resources to process this packet, discard it */
Cleanup(&IPDR->Lock, OldIrql, IPDR, NULL); Cleanup(&IPDR->Lock, OldIrql, IPDR, NULL);
@ -426,7 +431,7 @@ VOID ProcessFragment(
TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment)); TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));
Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize; Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize;
Fragment->Data = ExAllocatePool(NonPagedPool, Fragment->Size); Fragment->Data = exAllocatePool(NonPagedPool, Fragment->Size);
if (!Fragment->Data) { if (!Fragment->Data) {
/* We don't have the resources to process this packet, discard it */ /* We don't have the resources to process this packet, discard it */
Cleanup(&IPDR->Lock, OldIrql, IPDR, Fragment); Cleanup(&IPDR->Lock, OldIrql, IPDR, Fragment);
@ -437,13 +442,12 @@ VOID ProcessFragment(
Fragment->Data, Fragment->Size)); Fragment->Data, Fragment->Size));
/* Copy datagram data into fragment buffer */ /* Copy datagram data into fragment buffer */
CopyPacketToBuffer( CopyPacketToBuffer(Fragment->Data,
Fragment->Data, IPPacket->NdisPacket,
IPPacket->NdisPacket, IPPacket->Position + MaxLLHeaderSize,
IPPacket->Position, Fragment->Size);
Fragment->Size); Fragment->Offset = FragFirst;
Fragment->Offset = FragFirst;
/* If this is the last fragment, compute and save the datagram data size */ /* If this is the last fragment, compute and save the datagram data size */
if (!MoreFragments) if (!MoreFragments)
IPDR->DataSize = FragFirst + Fragment->Size; IPDR->DataSize = FragFirst + Fragment->Size;
@ -463,7 +467,7 @@ VOID ProcessFragment(
Datagram = ReassembleDatagram(IPDR); Datagram = ReassembleDatagram(IPDR);
KeReleaseSpinLock(&IPDR->Lock, OldIrql); KeReleaseSpinLock(&IPDR->Lock, OldIrql);
RemoveIPDR(IPDR); RemoveIPDR(IPDR);
FreeIPDR(IPDR); FreeIPDR(IPDR);
@ -478,7 +482,7 @@ VOID ProcessFragment(
IPDispatchProtocol(NTE, Datagram); IPDispatchProtocol(NTE, Datagram);
/* We're done with this datagram */ /* We're done with this datagram */
ExFreePool(Datagram->Header); exFreePool(Datagram->Header);
TI_DbgPrint(MAX_TRACE, ("Freeing datagram at (0x%X).\n", Datagram)); TI_DbgPrint(MAX_TRACE, ("Freeing datagram at (0x%X).\n", Datagram));
(*Datagram->Free)(Datagram); (*Datagram->Free)(Datagram);
} else } else
@ -525,7 +529,6 @@ VOID IPDatagramReassemblyTimeout(
{ {
} }
VOID IPv4Receive( VOID IPv4Receive(
PVOID Context, PVOID Context,
PIP_PACKET IPPacket) PIP_PACKET IPPacket)
@ -536,81 +539,77 @@ VOID IPv4Receive(
* IPPacket = Pointer to IP packet * IPPacket = Pointer to IP packet
*/ */
{ {
PNEIGHBOR_CACHE_ENTRY NCE; PNEIGHBOR_CACHE_ENTRY NCE;
PNET_TABLE_ENTRY NTE; PNET_TABLE_ENTRY NTE;
UINT AddressType; UINT AddressType;
TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n"));
IPPacket->HeaderSize = (((PIPv4_HEADER)IPPacket->Header)->VerIHL & 0x0F) << 2;
TI_DbgPrint(DEBUG_IP, ("IPPacket->HeaderSize = %d\n", IPPacket->HeaderSize));
TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n")); if (IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE) {
TI_DbgPrint
IPPacket->HeaderSize = (((PIPv4_HEADER)IPPacket->Header)->VerIHL & 0x0F) << 2; (MIN_TRACE,
("Datagram received with incorrect header size (%d).\n",
if (IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE) { IPPacket->HeaderSize));
TI_DbgPrint(MIN_TRACE, ("Datagram received with incorrect header size (%d).\n", /* Discard packet */
IPPacket->HeaderSize)); return;
/* Discard packet */ }
return;
} /* Checksum IPv4 header */
if (!IPv4CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
/* Checksum IPv4 header */ TI_DbgPrint
if (!IPv4CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) { (MIN_TRACE,
TI_DbgPrint(MIN_TRACE, ("Datagram received with bad checksum. Checksum field (0x%X)\n", ("Datagram received with bad checksum. Checksum field (0x%X)\n",
WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum))); WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum)));
/* Discard packet */ /* Discard packet */
return; return;
} }
// TI_DbgPrint(DEBUG_IP, ("TotalSize (datalink) is (%d).\n", IPPacket->TotalSize)); IPPacket->TotalSize = WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength);
IPPacket->TotalSize = WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength); AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr);
AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
// TI_DbgPrint(DEBUG_IP, ("TotalSize (IPv4) is (%d).\n", IPPacket->TotalSize));
IPPacket->Position = IPPacket->HeaderSize;
AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr); IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPPacket->HeaderSize) + 14; /* XXX 14 */
AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
OskitDumpBuffer(IPPacket->Data - IPPacket->HeaderSize, IPPacket->TotalSize);
IPPacket->Position = IPPacket->HeaderSize;
IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPPacket->HeaderSize); /* FIXME: Possibly forward packets with multicast addresses */
/* FIXME: Possibly forward packets with multicast addresses */ /* FIXME: Should we allow packets to be received on the wrong interface? */
NTE = IPLocateNTEOnInterface((PIP_INTERFACE)Context, &IPPacket->DstAddr, &AddressType);
/* FIXME: Should we allow packets to be received on the wrong interface? */
#if 0 if (NTE) {
NTE = IPLocateNTE(&IPPacket->DstAddr, &AddressType); /* This packet is destined for us */
#else ProcessFragment((PIP_INTERFACE)Context, IPPacket, NTE);
NTE = IPLocateNTEOnInterface((PIP_INTERFACE)Context, &IPPacket->DstAddr, &AddressType);
#endif /* Done with this NTE */
if (NTE) { DereferenceObject(NTE);
/* This packet is destined for us */ } else {
ProcessFragment((PIP_INTERFACE)Context, IPPacket, NTE); /* This packet is not destined for us. If we are a router,
try to find a route and forward the packet */
/* Done with this NTE */
DereferenceObject(NTE); /* FIXME: Check if acting as a router */
} else { NCE = NULL;
/* This packet is not destined for us. If we are a router, if (NCE) {
try to find a route and forward the packet */ /* FIXME: Possibly fragment datagram */
/* Forward the packet */
/* FIXME: Check if acting as a router */ IPSendFragment(IPPacket, NCE);
#if 1 } else {
//NCE = RouteFindRouter(&IPPacket->DstAddr, NULL); TI_DbgPrint(MIN_TRACE, ("No route to destination (0x%X).\n",
NCE = NULL; IPPacket->DstAddr.Address.IPv4Address));
if (NCE) {
/* FIXME: Possibly fragment datagram */ /* FIXME: Send ICMP error code */
/* Forward the packet */ }
IPSendFragment(IPPacket, NCE);
} else {
TI_DbgPrint(MIN_TRACE, ("No route to destination (0x%X).\n",
IPPacket->DstAddr.Address.IPv4Address));
/* FIXME: Send ICMP error code */
} }
#endif
}
} }
VOID IPReceive( VOID IPReceive( PVOID Context,
PVOID Context, PIP_PACKET IPPacket )
PIP_PACKET IPPacket)
/* /*
* FUNCTION: Receives an IP datagram (or fragment) * FUNCTION: Receives an IP datagram (or fragment)
* ARGUMENTS: * ARGUMENTS:

View file

@ -6,9 +6,15 @@
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* NOTES: The route cache is implemented as a binary search * NOTES: The route cache is implemented as a binary search
* tree to obtain fast searches * tree to obtain fast searches
*
* This data is not authoritative. It is a searchable cache that allows
* quick access to route information to selected hosts. This information
* should always defer to the FIB.
*
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <route.h> #include <route.h>
#include <router.h> #include <router.h>
@ -23,7 +29,7 @@ KSPIN_LOCK RouteCacheLock;
NPAGED_LOOKASIDE_LIST IPRCNList; NPAGED_LOOKASIDE_LIST IPRCNList;
#if DBG #ifdef DBG
VOID PrintTree( VOID PrintTree(
PROUTE_CACHE_NODE Node) PROUTE_CACHE_NODE Node)
/* /*
@ -50,6 +56,17 @@ VOID PrintTree(
} }
#endif #endif
UINT CountRouteNodes( PROUTE_CACHE_NODE Node ) {
if( !Node ) Node = RouteCache;
if( IsInternalRCN(Node) )
return
/* Traverse left subtree */
CountRouteNodes(Node->Left) +
/* Traverse right subtree */
CountRouteNodes(Node->Right) + 1;
else
return 0;
}
VOID FreeRCN( VOID FreeRCN(
PVOID Object) PVOID Object)
@ -168,6 +185,8 @@ PROUTE_CACHE_NODE ExpandExternalRCN(VOID)
{ {
PROUTE_CACHE_NODE RCN; PROUTE_CACHE_NODE RCN;
MTMARK();
TI_DbgPrint(DEBUG_RCACHE, ("Called.\n")); TI_DbgPrint(DEBUG_RCACHE, ("Called.\n"));
RCN = ExAllocateFromNPagedLookasideList(&IPRCNList); RCN = ExAllocateFromNPagedLookasideList(&IPRCNList);
@ -176,6 +195,8 @@ PROUTE_CACHE_NODE ExpandExternalRCN(VOID)
return NULL; return NULL;
} }
MTMARK();
RCN->Free = FreeRCN; RCN->Free = FreeRCN;
if (ExternalRCN->Left) if (ExternalRCN->Left)
@ -186,6 +207,8 @@ PROUTE_CACHE_NODE ExpandExternalRCN(VOID)
RCN->Left = ExternalRCN; RCN->Left = ExternalRCN;
RCN->Right = ExternalRCN; RCN->Right = ExternalRCN;
MTMARK();
return RCN; return RCN;
} }
@ -364,7 +387,7 @@ VOID RemoveSubtree(
DereferenceObject(Node->NTE); DereferenceObject(Node->NTE);
DereferenceObject(Node->NCE); DereferenceObject(Node->NCE);
#if DBG #ifdef DBG
if (Node->RefCount != 1) if (Node->RefCount != 1)
TI_DbgPrint(MIN_TRACE, ("RCN at (0x%X) has (%d) references (should be 1).\n", Node, Node->RefCount)); TI_DbgPrint(MIN_TRACE, ("RCN at (0x%X) has (%d) references (should be 1).\n", Node, Node->RefCount));
#endif #endif

View file

@ -4,12 +4,18 @@
* FILE: network/router.c * FILE: network/router.c
* PURPOSE: IP routing subsystem * PURPOSE: IP routing subsystem
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* NOTES:
* This file holds authoritative routing information.
* Information queries on the route table should be handled here.
* This information should always override the route cache info.
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <address.h> #include <address.h>
#include <router.h> #include <router.h>
#include <prefix.h>
#include <pool.h> #include <pool.h>
@ -48,7 +54,6 @@ VOID DestroyFIBE(
DereferenceObject(FIBE->NetworkAddress); DereferenceObject(FIBE->NetworkAddress);
DereferenceObject(FIBE->Netmask); DereferenceObject(FIBE->Netmask);
DereferenceObject(FIBE->Router); DereferenceObject(FIBE->Router);
DereferenceObject(FIBE->NTE);
#ifdef DBG #ifdef DBG
FIBE->RefCount--; FIBE->RefCount--;
@ -79,7 +84,7 @@ VOID DestroyFIBEs(
CurrentEntry = FIBListHead.Flink; CurrentEntry = FIBListHead.Flink;
while (CurrentEntry != &FIBListHead) { while (CurrentEntry != &FIBListHead) {
NextEntry = CurrentEntry->Flink; NextEntry = CurrentEntry->Flink;
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry); Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
/* Destroy the FIB entry */ /* Destroy the FIB entry */
DestroyFIBE(Current); DestroyFIBE(Current);
CurrentEntry = NextEntry; CurrentEntry = NextEntry;
@ -87,6 +92,43 @@ VOID DestroyFIBEs(
} }
UINT CountFIBs() {
UINT FibCount = 0;
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
/* Search the list and remove every FIB entry we find */
CurrentEntry = FIBListHead.Flink;
while (CurrentEntry != &FIBListHead) {
NextEntry = CurrentEntry->Flink;
CurrentEntry = NextEntry;
FibCount++;
}
return FibCount;
}
UINT CopyFIBs( PFIB_ENTRY Target ) {
UINT FibCount = 0;
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
PFIB_ENTRY Current;
/* Search the list and remove every FIB entry we find */
CurrentEntry = FIBListHead.Flink;
while (CurrentEntry != &FIBListHead) {
NextEntry = CurrentEntry->Flink;
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
Target[FibCount] = *Current;
CurrentEntry = NextEntry;
FibCount++;
}
return FibCount;
}
UINT CommonPrefixLength( UINT CommonPrefixLength(
PIP_ADDRESS Address1, PIP_ADDRESS Address1,
PIP_ADDRESS Address2) PIP_ADDRESS Address2)
@ -108,33 +150,25 @@ UINT CommonPrefixLength(
TI_DbgPrint(DEBUG_ROUTER, ("Called. Address1 (0x%X) Address2 (0x%X).\n", Address1, Address2)); TI_DbgPrint(DEBUG_ROUTER, ("Called. Address1 (0x%X) Address2 (0x%X).\n", Address1, Address2));
TI_DbgPrint(DEBUG_ROUTER, ("Address1 (%s) Address2 (%s).\n", /*TI_DbgPrint(DEBUG_ROUTER, ("Target (%s) \n", A2S(Address1)));*/
A2S(Address1), A2S(Address2))); /*TI_DbgPrint(DEBUG_ROUTER, ("Adapter (%s).\n", A2S(Address2)));*/
if (Address1->Type == IP_ADDRESS_V4) if (Address1->Type == IP_ADDRESS_V4)
Size = sizeof(IPv4_RAW_ADDRESS); Size = sizeof(IPv4_RAW_ADDRESS);
else else
Size = sizeof(IPv6_RAW_ADDRESS); Size = sizeof(IPv6_RAW_ADDRESS);
Addr1 = (PUCHAR)&Address1->Address; Addr1 = (PUCHAR)&Address1->Address.IPv4Address;
Addr2 = (PUCHAR)&Address2->Address; Addr2 = (PUCHAR)&Address2->Address.IPv4Address;
/* Find first non-matching byte */ /* Find first non-matching byte */
for (i = 0; ; i++) { for (i = 0; i < Size && Addr1[i] == Addr2[i]; i++);
if (i == Size) if( i == Size ) return 8 * i;
return 8 * i; /* The two addresses are equal */
if (Addr1[i] != Addr2[i])
break;
}
/* Find first non-matching bit */ /* Find first non-matching bit */
Bitmask = 0x80; Bitmask = 0x80;
for (j = 0; ; j++) { for (j = 0; (Addr1[i] & Bitmask) != (Addr2[i] & Bitmask); j++)
if ((Addr1[i] & Bitmask) != (Addr2[i] & Bitmask))
break;
Bitmask >>= 1; Bitmask >>= 1;
}
return 8 * i + j; return 8 * i + j;
} }
@ -161,8 +195,10 @@ BOOLEAN HasPrefix(
TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X) Prefix (0x%X) Length (%d).\n", Address, Prefix, Length)); TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X) Prefix (0x%X) Length (%d).\n", Address, Prefix, Length));
#if 0
TI_DbgPrint(DEBUG_ROUTER, ("Address (%s) Prefix (%s).\n", TI_DbgPrint(DEBUG_ROUTER, ("Address (%s) Prefix (%s).\n",
A2S(Address), A2S(Prefix))); A2S(Address), A2S(Prefix)));
#endif
/* Check that initial integral bytes match */ /* Check that initial integral bytes match */
while (Length > 8) { while (Length > 8) {
@ -207,7 +243,8 @@ PNET_TABLE_ENTRY RouterFindBestNTE(
CurrentEntry = Interface->NTEListHead.Flink; CurrentEntry = Interface->NTEListHead.Flink;
while (CurrentEntry != &Interface->NTEListHead) { while (CurrentEntry != &Interface->NTEListHead) {
Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry); Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry);
TI_DbgPrint(DEBUG_ROUTER, ("Looking at NTE %s\n", A2S(Current->Address)));
Length = CommonPrefixLength(Destination, Current->Address); Length = CommonPrefixLength(Destination, Current->Address);
if (BestNTE) { if (BestNTE) {
@ -271,7 +308,6 @@ PIP_INTERFACE RouterFindOnLinkInterface(
PFIB_ENTRY RouterAddRoute( PFIB_ENTRY RouterAddRoute(
PIP_ADDRESS NetworkAddress, PIP_ADDRESS NetworkAddress,
PIP_ADDRESS Netmask, PIP_ADDRESS Netmask,
PNET_TABLE_ENTRY NTE,
PNEIGHBOR_CACHE_ENTRY Router, PNEIGHBOR_CACHE_ENTRY Router,
UINT Metric) UINT Metric)
/* /*
@ -279,24 +315,23 @@ PFIB_ENTRY RouterAddRoute(
* ARGUMENTS: * ARGUMENTS:
* NetworkAddress = Pointer to address of network * NetworkAddress = Pointer to address of network
* Netmask = Pointer to netmask of network * Netmask = Pointer to netmask of network
* NTE = Pointer to NTE to use
* Router = Pointer to NCE of router to use * Router = Pointer to NCE of router to use
* Metric = Cost of this route * Metric = Cost of this route
* RETURNS: * RETURNS:
* Pointer to FIB entry if the route was added, NULL if not * Pointer to FIB entry if the route was added, NULL if not
* NOTES: * NOTES:
* The FIB entry references the NetworkAddress, Netmask, NTE and * The FIB entry references the NetworkAddress, Netmask and
* the NCE of the router. The caller is responsible for providing * the NCE of the router. The caller is responsible for providing
* these references * these references
*/ */
{ {
PFIB_ENTRY FIBE; PFIB_ENTRY FIBE;
TI_DbgPrint(DEBUG_ROUTER, ("Called. NetworkAddress (0x%X) Netmask (0x%X) NTE (0x%X) " TI_DbgPrint(DEBUG_ROUTER, ("Called. NetworkAddress (0x%X) Netmask (0x%X) "
"Router (0x%X) Metric (%d).\n", NetworkAddress, Netmask, NTE, Router, Metric)); "Router (0x%X) Metric (%d).\n", NetworkAddress, Netmask, Router, Metric));
TI_DbgPrint(DEBUG_ROUTER, ("NetworkAddress (%s) Netmask (%s) NTE (%s) Router (%s).\n", TI_DbgPrint(DEBUG_ROUTER, ("NetworkAddress (%s) Netmask (%s) Router (%s).\n",
A2S(NetworkAddress), A2S(Netmask), A2S(NTE->Address), A2S(Router->Address))); A2S(NetworkAddress), A2S(Netmask), A2S(Router->Address)));
FIBE = ExAllocatePool(NonPagedPool, sizeof(FIB_ENTRY)); FIBE = ExAllocatePool(NonPagedPool, sizeof(FIB_ENTRY));
if (!FIBE) { if (!FIBE) {
@ -304,13 +339,11 @@ PFIB_ENTRY RouterAddRoute(
return NULL; return NULL;
} }
INIT_TAG(NTE, TAG('N','T','E',' '));
INIT_TAG(Router, TAG('R','O','U','T')); INIT_TAG(Router, TAG('R','O','U','T'));
FIBE->Free = FreeFIB; FIBE->Free = FreeFIB;
FIBE->NetworkAddress = NetworkAddress; FIBE->NetworkAddress = NetworkAddress;
FIBE->Netmask = Netmask; FIBE->Netmask = Netmask;
FIBE->NTE = NTE;
FIBE->Router = Router; FIBE->Router = Router;
FIBE->Metric = Metric; FIBE->Metric = Metric;
@ -346,8 +379,9 @@ PNEIGHBOR_CACHE_ENTRY RouterGetRoute(
TI_DbgPrint(DEBUG_ROUTER, ("Called. Destination (0x%X) NTE (0x%X).\n", Destination, NTE)); TI_DbgPrint(DEBUG_ROUTER, ("Called. Destination (0x%X) NTE (0x%X).\n", Destination, NTE));
TI_DbgPrint(DEBUG_ROUTER, ("Destination (%s) NTE (%s).\n", TI_DbgPrint(DEBUG_ROUTER, ("Destination (%s)\n", A2S(Destination)));
A2S(Destination), A2S(NTE->Address))); if( NTE )
TI_DbgPrint(DEBUG_ROUTER, ("NTE (%s).\n", A2S(NTE->Address)));
KeAcquireSpinLock(&FIBLock, &OldIrql); KeAcquireSpinLock(&FIBLock, &OldIrql);
@ -476,7 +510,7 @@ PFIB_ENTRY RouterCreateRouteIPv4(
ReferenceObject(pNetworkAddress); ReferenceObject(pNetworkAddress);
ReferenceObject(pNetmask); ReferenceObject(pNetmask);
FIBE = RouterAddRoute(pNetworkAddress, pNetmask, NTE, NCE, 1); FIBE = RouterAddRoute(pNetworkAddress, pNetmask, NCE, 1);
if (!FIBE) { if (!FIBE) {
/* Not enough free resources */ /* Not enough free resources */
NBRemoveNeighbor(NCE); NBRemoveNeighbor(NCE);

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <transmit.h> #include <transmit.h>
#include <routines.h> #include <routines.h>
@ -66,6 +67,7 @@ BOOLEAN PrepareNextFragment(
/* Calculate checksum of IP header */ /* Calculate checksum of IP header */
Header->Checksum = 0; Header->Checksum = 0;
Header->Checksum = (USHORT)IPv4Checksum(Header, IFC->HeaderSize, 0); Header->Checksum = (USHORT)IPv4Checksum(Header, IFC->HeaderSize, 0);
TI_DbgPrint(MID_TRACE,("IP Check: %x\n", Header->Checksum));
/* Update pointers */ /* Update pointers */
IFC->DatagramData = (PVOID)((ULONG_PTR)IFC->DatagramData + DataSize); IFC->DatagramData = (PVOID)((ULONG_PTR)IFC->DatagramData + DataSize);
@ -103,23 +105,23 @@ NTSTATUS SendFragments(
TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X) PathMTU (%d).\n", TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X) PathMTU (%d).\n",
IPPacket, NCE, PathMTU)); IPPacket, NCE, PathMTU));
IFC = ExAllocatePool(NonPagedPool, sizeof(IPFRAGMENT_CONTEXT)); IFC = exAllocatePool(NonPagedPool, sizeof(IPFRAGMENT_CONTEXT));
if (IFC == NULL) if (IFC == NULL)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
/* We allocate a buffer for a PathMTU sized packet and reuse /* We allocate a buffer for a PathMTU sized packet and reuse
it for all fragments */ it for all fragments */
Data = ExAllocatePool(NonPagedPool, MaxLLHeaderSize + PathMTU); Data = exAllocatePool(NonPagedPool, MaxLLHeaderSize + PathMTU);
if (Data == NULL) { if (Data == NULL) {
ExFreePool(IFC); exFreePool(IFC);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
/* Allocate NDIS packet */ /* Allocate NDIS packet */
NdisAllocatePacket(&NdisStatus, &IFC->NdisPacket, GlobalPacketPool); NdisAllocatePacket(&NdisStatus, &IFC->NdisPacket, GlobalPacketPool);
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
ExFreePool(Data); exFreePool(Data);
ExFreePool(IFC); exFreePool(IFC);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
@ -127,9 +129,9 @@ NTSTATUS SendFragments(
NdisAllocateBuffer(&NdisStatus, &IFC->NdisBuffer, NdisAllocateBuffer(&NdisStatus, &IFC->NdisBuffer,
GlobalBufferPool, Data, MaxLLHeaderSize + PathMTU); GlobalBufferPool, Data, MaxLLHeaderSize + PathMTU);
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
NdisFreePacket(IFC->NdisPacket); FreeNdisPacket(IFC->NdisPacket);
ExFreePool(Data); exFreePool(Data);
ExFreePool(IFC); exFreePool(IFC);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
@ -206,8 +208,11 @@ VOID IPSendComplete(
/* There are no more fragments to transmit, so call completion handler */ /* There are no more fragments to transmit, so call completion handler */
NdisPacket = IFC->Datagram; NdisPacket = IFC->Datagram;
FreeNdisPacket(IFC->NdisPacket); FreeNdisPacket(IFC->NdisPacket);
ExFreePool(IFC); exFreePool(IFC);
(*PC(NdisPacket)->Complete)(PC(NdisPacket)->Context, NdisPacket, NdisStatus); (*PC(NdisPacket)->Complete)
(PC(NdisPacket)->Context,
NdisPacket,
NdisStatus);
} }
} }
} }
@ -304,10 +309,11 @@ NTSTATUS IPSendDatagram(
TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) RCN (0x%X)\n", IPPacket, RCN)); TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) RCN (0x%X)\n", IPPacket, RCN));
DISPLAY_IP_PACKET(IPPacket); DISPLAY_IP_PACKET(IPPacket);
OskitDumpBuffer( IPPacket->Header, IPPacket->TotalSize );
NCE = RCN->NCE; NCE = RCN->NCE;
#if DBG #ifdef DBG
if (!NCE) { if (!NCE) {
TI_DbgPrint(MIN_TRACE, ("No NCE to use.\n")); TI_DbgPrint(MIN_TRACE, ("No NCE to use.\n"));
FreeNdisPacket(IPPacket->NdisPacket); FreeNdisPacket(IPPacket->NdisPacket);
@ -317,16 +323,20 @@ NTSTATUS IPSendDatagram(
/* Fetch path MTU now, because it may change */ /* Fetch path MTU now, because it may change */
PathMTU = RCN->PathMTU; PathMTU = RCN->PathMTU;
TI_DbgPrint(MID_TRACE,("PathMTU: %d\n", PathMTU));
if (IPPacket->TotalSize > PathMTU) { if (IPPacket->TotalSize > PathMTU) {
TI_DbgPrint(MID_TRACE,("Doing SendFragments\n"));
return SendFragments(IPPacket, NCE, PathMTU); return SendFragments(IPPacket, NCE, PathMTU);
} else { } else {
if ((IPPacket->Flags & IP_PACKET_FLAG_RAW) == 0) { if ((IPPacket->Flags & IP_PACKET_FLAG_RAW) == 0) {
/* Calculate checksum of IP header */ /* Calculate checksum of IP header */
TI_DbgPrint(MID_TRACE,("-> not IP_PACKET_FLAG_RAW\n"));
((PIPv4_HEADER)IPPacket->Header)->Checksum = 0; ((PIPv4_HEADER)IPPacket->Header)->Checksum = 0;
((PIPv4_HEADER)IPPacket->Header)->Checksum = (USHORT) ((PIPv4_HEADER)IPPacket->Header)->Checksum = (USHORT)
IPv4Checksum(IPPacket->Header, IPPacket->HeaderSize, 0); IPv4Checksum(IPPacket->Header, IPPacket->HeaderSize, 0);
TI_DbgPrint(MID_TRACE,("IP Check: %x\n", ((PIPv4_HEADER)IPPacket->Header)->Checksum));
TI_DbgPrint(MAX_TRACE, ("Sending packet (length is %d).\n", TI_DbgPrint(MAX_TRACE, ("Sending packet (length is %d).\n",
WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength))); WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength)));

View file

@ -1,4 +1,12 @@
Ideas for optimizations:
* transmit.c (SendFragments, IPSendComplete):
Keep IPFRAGMENT_CONTEXT objects and PathMTU buffers in a pool
References:
RFC 791 - Internet Protocol RFC 791 - Internet Protocol
http://www.faqs.org/rfcs/rfc791.html http://www.faqs.org/rfcs/rfc791.html

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <address.h> #include <address.h>
#include <pool.h> #include <pool.h>
@ -164,7 +165,9 @@ NTSTATUS AddrGetAddress(
} }
} }
IPAddress = ExAllocatePool(NonPagedPool, sizeof(IP_ADDRESS)); IPAddress = ExAllocatePoolWithTag(NonPagedPool,
sizeof(IP_ADDRESS),
FOURCC('I','P','v','4'));
if (IPAddress) { if (IPAddress) {
AddrInitIPv4(IPAddress, ValidAddr->in_addr); AddrInitIPv4(IPAddress, ValidAddr->in_addr);
*Address = IPAddress; *Address = IPAddress;

View file

@ -8,6 +8,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <checksum.h> #include <checksum.h>

View file

@ -8,6 +8,7 @@
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
* TODO: Validate device object in all dispatch routines * TODO: Validate device object in all dispatch routines
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <dispatch.h> #include <dispatch.h>
#include <routines.h> #include <routines.h>
@ -53,13 +54,9 @@ NTSTATUS DispPrepareIrpForCancel(
Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n")); TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n"));
return STATUS_CANCELLED; return IRPFinish(Irp, STATUS_CANCELLED);
} }
@ -223,7 +220,7 @@ VOID DispDataRequestComplete(
TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); IRPFinish(Irp, STATUS_SUCCESS);
} }
@ -239,7 +236,7 @@ NTSTATUS DispTdiAccept(
{ {
TI_DbgPrint(DEBUG_IRP, ("Called.\n")); TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
@ -378,11 +375,14 @@ NTSTATUS DispTdiConnect(
Request.RequestNotifyObject = DispDataRequestComplete; Request.RequestNotifyObject = DispDataRequestComplete;
Request.RequestContext = Irp; Request.RequestContext = Irp;
/* XXX Handle connected UDP, etc... */
Status = TCPConnect( Status = TCPConnect(
&Request, &Request,
Parameters->RequestConnectionInformation, Parameters->RequestConnectionInformation,
Parameters->ReturnConnectionInformation); Parameters->ReturnConnectionInformation);
TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
return Status; return Status;
} }
@ -555,36 +555,7 @@ NTSTATUS DispTdiListen(
Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters; Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
/* Initialize a listen request */ Status = TCPListen( Request, 1024 /* BACKLOG */ );
Request = (PTDI_REQUEST) ExAllocatePool(NonPagedPool, sizeof(TDI_REQUEST));
if (Request == NULL)
{
return STATUS_NO_MEMORY;
}
Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
if (NT_SUCCESS(Status))
{
Request->Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
Request->RequestNotifyObject = DispDataRequestComplete;
Request->RequestContext = Irp;
Status = TCPListen(
Request,
Parameters->RequestConnectionInformation,
Parameters->ReturnConnectionInformation);
if (Status != STATUS_PENDING)
{
IoAcquireCancelSpinLock(&OldIrql);
IoSetCancelRoutine(Irp, NULL);
IoReleaseCancelSpinLock(OldIrql);
}
}
if (Status != STATUS_PENDING)
{
ExFreePool(Request);
}
return Status; return Status;
} }
@ -683,9 +654,61 @@ NTSTATUS DispTdiReceive(
* Status of operation * Status of operation
*/ */
{ {
PIO_STACK_LOCATION IrpSp;
PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
PTRANSPORT_CONTEXT TranContext;
TDI_REQUEST Request;
NTSTATUS Status;
ULONG BytesReceived;
TI_DbgPrint(DEBUG_IRP, ("Called.\n")); TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
return STATUS_NOT_IMPLEMENTED; IrpSp = IoGetCurrentIrpStackLocation(Irp);
ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters);
TranContext = IrpSp->FileObject->FsContext;
if (TranContext == NULL)
{
TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
return STATUS_INVALID_CONNECTION;
}
if (TranContext->Handle.ConnectionContext == NULL)
{
TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
return STATUS_INVALID_CONNECTION;
}
/* Initialize a receive request */
Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
Request.RequestNotifyObject = DispDataRequestComplete;
Request.RequestContext = Irp;
Status = DispPrepareIrpForCancel(
IrpSp->FileObject->FsContext,
Irp,
(PDRIVER_CANCEL)DispCancelRequest);
if (NT_SUCCESS(Status))
{
Status = TCPReceiveData(
&Request,
(PNDIS_BUFFER)Irp->MdlAddress,
ReceiveInfo->ReceiveLength,
ReceiveInfo->ReceiveFlags,
&BytesReceived);
if (Status != STATUS_PENDING)
{
DispDataRequestComplete(Irp, Status, BytesReceived);
}
}
if (Status != STATUS_PENDING)
{
IrpSp->Control &= ~SL_PENDING_RETURNED;
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
return Status;
} }
@ -712,6 +735,12 @@ NTSTATUS DispTdiReceiveDatagram(
DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters); DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters);
TranContext = IrpSp->FileObject->FsContext; TranContext = IrpSp->FileObject->FsContext;
if (TranContext == NULL)
{
TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
return STATUS_INVALID_ADDRESS;
}
/* Initialize a receive request */ /* Initialize a receive request */
Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
Request.RequestNotifyObject = DispDataRequestComplete; Request.RequestNotifyObject = DispDataRequestComplete;
@ -720,22 +749,26 @@ NTSTATUS DispTdiReceiveDatagram(
IrpSp->FileObject->FsContext, IrpSp->FileObject->FsContext,
Irp, Irp,
(PDRIVER_CANCEL)DispCancelRequest); (PDRIVER_CANCEL)DispCancelRequest);
if (NT_SUCCESS(Status)) { if (NT_SUCCESS(Status))
Status = UDPReceiveDatagram( {
&Request, Status = UDPReceiveDatagram(
DgramInfo->ReceiveDatagramInformation, &Request,
(PNDIS_BUFFER)Irp->MdlAddress, DgramInfo->ReceiveDatagramInformation,
DgramInfo->ReceiveLength, (PNDIS_BUFFER)Irp->MdlAddress,
DgramInfo->ReceiveFlags, DgramInfo->ReceiveLength,
DgramInfo->ReturnDatagramInformation, DgramInfo->ReceiveFlags,
&BytesReceived); DgramInfo->ReturnDatagramInformation,
if (Status != STATUS_PENDING) { &BytesReceived);
DispDataRequestComplete(Irp, Status, BytesReceived); if (Status != STATUS_PENDING)
/* Return STATUS_PENDING because DispPrepareIrpForCancel marks {
the Irp as pending */ DispDataRequestComplete(Irp, Status, BytesReceived);
Status = STATUS_PENDING; }
}
if (Status != STATUS_PENDING)
{
IrpSp->Control &= ~SL_PENDING_RETURNED;
} }
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
@ -753,9 +786,46 @@ NTSTATUS DispTdiSend(
* Status of operation * Status of operation
*/ */
{ {
PIO_STACK_LOCATION IrpSp;
TDI_REQUEST Request;
PTDI_REQUEST_KERNEL_SEND SendInfo;
PTRANSPORT_CONTEXT TranContext;
NTSTATUS Status;
TI_DbgPrint(DEBUG_IRP, ("Called.\n")); TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
return STATUS_NOT_IMPLEMENTED; IrpSp = IoGetCurrentIrpStackLocation(Irp);
SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters);
TranContext = IrpSp->FileObject->FsContext;
/* Initialize a send request */
Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
Request.RequestNotifyObject = DispDataRequestComplete;
Request.RequestContext = Irp;
Status = DispPrepareIrpForCancel(
IrpSp->FileObject->FsContext,
Irp,
(PDRIVER_CANCEL)DispCancelRequest);
if (NT_SUCCESS(Status)) {
/* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
must be of type PTDI_ADDRESS_IP */
Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
&Request, NULL,
(PNDIS_BUFFER)Irp->MdlAddress, SendInfo->SendLength);
if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, 0);
/* Return STATUS_PENDING because DispPrepareIrpForCancel
marks Irp as pending */
Status = STATUS_PENDING;
}
}
TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
return Status;
} }
@ -1209,9 +1279,7 @@ NTSTATUS DispTdiSetInformationEx(
TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); return IRPFinish(Irp, STATUS_INVALID_PARAMETER);
return STATUS_INVALID_PARAMETER;
} }
Status = DispPrepareIrpForCancel(TranContext, Irp, NULL); Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <datagram.h> #include <datagram.h>
#include <address.h> #include <address.h>
@ -16,6 +17,7 @@
#include <udp.h> #include <udp.h>
#include <ip.h> #include <ip.h>
#include <fileobjs.h> #include <fileobjs.h>
#include <oskittcp.h>
/* List of all address file objects managed by this driver */ /* List of all address file objects managed by this driver */
LIST_ENTRY AddressFileListHead; LIST_ENTRY AddressFileListHead;
@ -98,7 +100,8 @@ VOID DeleteAddress(
CurrentEntry = AddrFile->TransmitQueue.Flink; CurrentEntry = AddrFile->TransmitQueue.Flink;
while (CurrentEntry != &AddrFile->TransmitQueue) { while (CurrentEntry != &AddrFile->TransmitQueue) {
NextEntry = CurrentEntry->Flink; NextEntry = CurrentEntry->Flink;
SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry); SendRequest = CONTAINING_RECORD(CurrentEntry,
DATAGRAM_SEND_REQUEST, ListEntry);
/* Abort the request and free its resources */ /* Abort the request and free its resources */
KeReleaseSpinLock(&AddrFile->Lock, OldIrql); KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
(*SendRequest->Complete)(SendRequest->Context, STATUS_ADDRESS_CLOSED, 0); (*SendRequest->Complete)(SendRequest->Context, STATUS_ADDRESS_CLOSED, 0);
@ -309,7 +312,7 @@ NTSTATUS FileOpenAddress(
case IPPROTO_TCP: case IPPROTO_TCP:
/* FIXME: If specified port is 0, a port is chosen dynamically */ /* FIXME: If specified port is 0, a port is chosen dynamically */
AddrFile->Port = Address->Address[0].Address[0].sin_port; AddrFile->Port = Address->Address[0].Address[0].sin_port;
AddrFile->Send = TCPSendDatagram; AddrFile->Send = TCPSendData;
break; break;
case IPPROTO_UDP: case IPPROTO_UDP:
@ -437,7 +440,9 @@ NTSTATUS FileOpenConnection(
PTDI_REQUEST Request, PTDI_REQUEST Request,
PVOID ClientContext) PVOID ClientContext)
{ {
NTSTATUS Status;
PCONNECTION_ENDPOINT Connection; PCONNECTION_ENDPOINT Connection;
PADDRESS_FILE AddrFile;
TI_DbgPrint(MID_TRACE, ("Called.\n")); TI_DbgPrint(MID_TRACE, ("Called.\n"));
@ -455,15 +460,26 @@ NTSTATUS FileOpenConnection(
/* Reference the object */ /* Reference the object */
Connection->RefCount = 1; Connection->RefCount = 1;
/* Put connection in the closed state */
Connection->State = ctClosed;
/* Save client context pointer */ /* Save client context pointer */
Connection->ClientContext = ClientContext; Connection->ClientContext = ClientContext;
Status = OskitTCPSocket( Connection,
&Connection->SocketContext,
AF_INET,
SOCK_STREAM,
IPPROTO_TCP );
DbgPrint("STATUS from OSKITTCP was %08x\n", Status);
/* Initialize receive requests queue */
InitializeListHead(&Connection->ReceiveRequests);
/* Initialize receive queue */ /* Initialize received segments queue */
InitializeListHead(&Connection->ReceivedSegments); InitializeListHead(&Connection->ReceivedSegments);
TI_DbgPrint(MIN_TRACE, ("X1 cur 0x%x\n", &Connection->ReceivedSegments));
TI_DbgPrint(MIN_TRACE, ("X1 Flink 0x%x\n", Connection->ReceivedSegments.Flink));
TI_DbgPrint(MIN_TRACE, ("X1 Blink 0x%x\n", Connection->ReceivedSegments.Blink));
/* Return connection endpoint file object */ /* Return connection endpoint file object */
Request->Handle.ConnectionContext = Connection; Request->Handle.ConnectionContext = Connection;
@ -497,43 +513,9 @@ NTSTATUS FileCloseConnection(
Connection = Request->Handle.ConnectionContext; Connection = Request->Handle.ConnectionContext;
#if 0 TCPClose(Request);
KeAcquireSpinLock(&Connection->Lock, &OldIrql); DeleteConnectionEndpoint(Connection);
if ((!AF_IS_BUSY(Connection)) && (Connection->RefCount == 1)) {
/* Set connection endpoint file object exclusive to us */
AF_SET_BUSY(Connection);
AF_CLR_VALID(Connection);
KeReleaseSpinLock(&Connection->Lock, OldIrql);
#endif
DeleteConnectionEndpoint(Connection);
#if 0
} else {
if (!AF_IS_PENDING(Connection, AFF_DELETE)) {
Connection->Complete = Request->RequestNotifyObject;
Connection->Context = Request->RequestContext;
/* Shedule connection endpoint for deletion */
AF_SET_PENDING(Connection, AFF_DELETE);
AF_CLR_VALID(Connection);
if (!AF_IS_BUSY(Connection)) {
/* Worker function is not running, so shedule it to run */
AF_SET_BUSY(Connection);
KeReleaseSpinLock(&Connection->Lock, OldIrql);
ExQueueWorkItem(&Connection->WorkItem, CriticalWorkQueue);
} else
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n"));
return STATUS_PENDING;
} else
Status = STATUS_ADDRESS_CLOSED;
KeReleaseSpinLock(&Connection->Lock, OldIrql);
}
#endif
TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return Status; return Status;

View file

@ -0,0 +1,108 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/iinfo.c
* PURPOSE: Per-interface information.
* PROGRAMMERS: Art Yerkes
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <lan.h>
#include <address.h>
#include <info.h>
#include <pool.h>
#include <ip.h>
TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIEntityID *ID,
PIP_INTERFACE Interface,
PNDIS_BUFFER Buffer,
PUINT BufferSize) {
TDI_STATUS Status = TDI_INVALID_REQUEST;
PIFENTRY OutData;
PLAN_ADAPTER IF = (PLAN_ADAPTER)Interface->Context;
PCHAR IFDescr;
KIRQL OldIrql;
ULONG Size;
UINT DescrLenMax = MAX_IFDESCR_LEN - 1;
TI_DbgPrint(MAX_TRACE,
("Getting IFEntry MIB (IF %08x LA %08x) (%04x:%d)\n",
Interface, IF, ID->tei_entity, ID->tei_instance));
OutData =
(PIFENTRY)ExAllocatePool( NonPagedPool,
sizeof(IFENTRY) + MAX_IFDESCR_LEN );
if( !OutData ) return TDI_INVALID_REQUEST; /* Out of memory */
RtlZeroMemory( OutData, sizeof(IFENTRY) + MAX_IFDESCR_LEN );
OutData->Index = ID->tei_instance + 1;
/* viz: tcpip keeps those indices */
OutData->Type = IF ? 1 : 0; /* XXX other -- for now ... */
OutData->Mtu = Interface->MTU;
TI_DbgPrint(MAX_TRACE,
("Getting interface speed\n"));
OutData->PhysAddrLen = Interface->AddressLength;
OutData->AdminStatus = 1; /* XXX Up -- How do I know? */
OutData->OperStatus = 1; /* XXX Up -- How do I know? */
IFDescr = (PCHAR)&OutData[1];
if( IF ) {
GetInterfaceSpeed( Interface, &OutData->Speed );
TI_DbgPrint(MAX_TRACE,
("IF Speed = %d * 100bps\n", OutData->Speed));
memcpy(OutData->PhysAddr,Interface->Address,Interface->AddressLength);
TI_DbgPrint(MAX_TRACE, ("Got HWAddr\n"));
GetInterfaceName( Interface, IFDescr, MAX_IFDESCR_LEN - 1 );
DescrLenMax = strlen( IFDescr ) + 1;
}
IFDescr[DescrLenMax] = 0; /* Terminate ifdescr string */
TI_DbgPrint(MAX_TRACE, ("Copied in name %s\n", IFDescr));
OutData->DescrLen = DescrLenMax;
IFDescr += DescrLenMax;
Size = IFDescr - (PCHAR)OutData + 1;
TI_DbgPrint(MAX_TRACE, ("Finished IFEntry MIB (%04x:%d) size %d\n",
ID->tei_entity, ID->tei_instance, Size));
Status = InfoCopyOut( OutData, Size, Buffer, BufferSize );
ExFreePool( OutData );
return Status;
}
TDI_STATUS InfoInterfaceTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize ) {
if( InfoClass == INFO_CLASS_GENERIC &&
InfoType == INFO_TYPE_PROVIDER &&
InfoId == ENTITY_TYPE_ID ) {
ULONG Temp = IF_MIB;
return InfoCopyOut( &Temp, sizeof(Temp), Buffer, BufferSize );
} else if( InfoClass == INFO_CLASS_PROTOCOL &&
InfoType == INFO_TYPE_PROVIDER &&
InfoId == IF_MIB_STATS_ID ) {
return InfoTdiQueryGetInterfaceMIB( id, Context, Buffer, BufferSize );
} else
return TDI_INVALID_REQUEST;
}
TDI_STATUS InfoInterfaceTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize ) {
return TDI_INVALID_REQUEST;
}

View file

@ -7,321 +7,110 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <info.h> #include <info.h>
#include <routines.h> #include <routines.h>
#include <debug.h>
TDI_STATUS InfoCopyOut( PCHAR DataOut, UINT SizeOut,
PNDIS_BUFFER ClientBuf, PUINT ClientBufSize ) {
UINT RememberedCBSize = *ClientBufSize;
*ClientBufSize = SizeOut;
if( RememberedCBSize < SizeOut )
return TDI_BUFFER_TOO_SMALL;
else {
CopyBufferToBufferChain( ClientBuf, 0, (PUCHAR)DataOut, SizeOut );
return TDI_SUCCESS;
}
}
TDI_STATUS IPTdiQueryInformationEx( VOID InsertTDIInterfaceEntity( PIP_INTERFACE Interface ) {
PTDI_REQUEST Request, KIRQL OldIrql;
TDIObjectID *ID, UINT Count = 0, i;
PNDIS_BUFFER Buffer,
PUINT BufferSize,
PVOID Context)
/*
* FUNCTION: Returns extended information about network layer
* ARGUMENTS:
* Request = Pointer to TDI request structure for the request
* ID = TDI object ID
* Buffer = Pointer to buffer with data to use.
* BufferSize = Pointer to buffer with size of Buffer. On return
* this is filled with number of bytes returned
* Context = Pointer to context buffer
* RETURNS:
* Status of operation
*/
{
PLIST_ENTRY CurrentIFEntry;
PLIST_ENTRY CurrentADEEntry;
PADDRESS_ENTRY CurrentADE;
PIP_INTERFACE CurrentIF;
IPADDR_ENTRY IpAddress;
IPSNMP_INFO SnmpInfo;
KIRQL OldIrql;
ULONG Entity;
ULONG Temp;
UINT Count;
UINT BufSize;
BufSize = *BufferSize; TI_DbgPrint(MAX_TRACE,
("Inserting interface %08x (%d entities already)\n",
Interface, EntityCount));
/* Make return parameters consistent every time */ KeAcquireSpinLock( &EntityListLock, &OldIrql );
*BufferSize = 0;
Entity = ID->toi_entity.tei_entity; /* Count IP Entities */
if (Entity != CL_NL_ENTITY) for( i = 0; i < EntityCount; i++ )
{ if( EntityList[i].tei_entity == IF_ENTITY ) {
/* We can't handle this entity */ Count++;
return TDI_INVALID_PARAMETER; TI_DbgPrint(MAX_TRACE, ("Entity %d is an IF. Found %d\n",
i, Count));
}
EntityList[EntityCount].tei_entity = IF_ENTITY;
EntityList[EntityCount].tei_instance = Count;
EntityList[EntityCount].context = Interface;
EntityList[EntityCount].info_req = InfoInterfaceTdiQueryEx;
EntityList[EntityCount].info_set = InfoInterfaceTdiSetEx;
EntityCount++;
KeReleaseSpinLock( &EntityListLock, OldIrql );
}
VOID RemoveTDIInterfaceEntity( PIP_INTERFACE Interface ) {
KIRQL OldIrql;
UINT Count = 0, i;
KeAcquireSpinLock( &EntityListLock, &OldIrql );
/* Remove entities that have this interface as context
* In the future, this might include AT_ENTITY types, too
*/
for( i = 0; i < EntityCount; i++ ) {
if( EntityList[i].context == Interface ) {
if( i != EntityCount-1 )
memcpy( &EntityList[i],
&EntityList[--EntityCount],
sizeof(EntityList[i]) );
}
} }
if (ID->toi_entity.tei_instance != TL_INSTANCE) KeReleaseSpinLock( &EntityListLock, OldIrql );
{
/* Only a single instance is supported */
return TDI_INVALID_REQUEST;
}
if (ID->toi_class == INFO_CLASS_GENERIC)
{
if ((ID->toi_type == INFO_TYPE_PROVIDER) &&
(ID->toi_id == ENTITY_TYPE_ID))
{
if (BufSize < sizeof(ULONG))
{
return TDI_BUFFER_TOO_SMALL;
}
Temp = CL_NL_IP;
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&Temp, sizeof(ULONG));
return TDI_SUCCESS;
}
return TDI_INVALID_PARAMETER;
}
if (ID->toi_class == INFO_CLASS_PROTOCOL)
{
if (ID->toi_type != INFO_TYPE_PROVIDER)
{
return TDI_INVALID_PARAMETER;
}
switch (ID->toi_id)
{
case IP_MIB_ADDRTABLE_ENTRY_ID:
Temp = 0;
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
while (CurrentIFEntry != &InterfaceListHead)
{
CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
if (Temp + sizeof(IPADDR_ENTRY) > BufSize)
{
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
return TDI_BUFFER_TOO_SMALL;
}
IpAddress.Addr = 0;
IpAddress.BcastAddr = 0;
IpAddress.Mask = 0;
/* Locate the diffrent addresses and put them the right place */
CurrentADEEntry = CurrentIF->ADEListHead.Flink;
while (CurrentADEEntry != &CurrentIF->ADEListHead)
{
CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry);
switch (CurrentADE->Type)
{
case ADE_UNICAST:
IpAddress.Addr = CurrentADE->Address->Address.IPv4Address;
break;
case ADE_MULTICAST:
IpAddress.BcastAddr = CurrentADE->Address->Address.IPv4Address;
break;
case ADE_ADDRMASK:
IpAddress.Mask = CurrentADE->Address->Address.IPv4Address;
break;
default:
/* Should not happen */
TI_DbgPrint(MIN_TRACE, ("Unknown address entry type (0x%X)\n", CurrentADE->Type));
break;
}
CurrentADEEntry = CurrentADEEntry->Flink;
}
/* Pack the address information into IPADDR_ENTRY structure */
IpAddress.Index = 0;
IpAddress.ReasmSize = 0;
IpAddress.Context = 0;
IpAddress.Pad = 0;
Count = CopyBufferToBufferChain(Buffer, Temp, (PUCHAR)&IpAddress, sizeof(IPADDR_ENTRY));
Temp += sizeof(IPADDR_ENTRY);
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
return TDI_SUCCESS;
case IP_MIB_STATS_ID:
if (BufSize < sizeof(IPSNMP_INFO))
{
return TDI_BUFFER_TOO_SMALL;
}
RtlZeroMemory(&SnmpInfo, sizeof(IPSNMP_INFO));
/* Count number of interfaces */
Count = 0;
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
while (CurrentIFEntry != &InterfaceListHead)
{
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
SnmpInfo.NumIf = Count;
/* Count number of addresses */
Count = 0;
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
while (CurrentIFEntry != &InterfaceListHead)
{
CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
SnmpInfo.NumAddr = Count;
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&SnmpInfo, sizeof(IPSNMP_INFO));
return TDI_SUCCESS;
default:
/* We can't handle this ID */
return TDI_INVALID_PARAMETER;
}
}
return TDI_INVALID_PARAMETER;
} }
TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer, TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer,
UINT BufSize,
PUINT BufferSize) PUINT BufferSize)
{ {
UINT Count, Size, Temp; UINT Count, Size, BufSize = *BufferSize;
KIRQL OldIrql; KIRQL OldIrql;
TDIEntityID *EntityOutList;
PLIST_ENTRY CurrentIFEntry; PLIST_ENTRY CurrentIFEntry;
/* Count Adapters */ TI_DbgPrint(MAX_TRACE,("About to copy %d TDIEntityIDs to user\n",
KeAcquireSpinLock(&InterfaceListLock, &OldIrql); EntityCount));
CurrentIFEntry = InterfaceListHead.Flink; KeAcquireSpinLock(&EntityListLock, &OldIrql);
Count = EntityCount;
Size = EntityCount * sizeof(TDIEntityID);
while( CurrentIFEntry != &InterfaceListHead ) {
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
Size = Count * sizeof(TDIEntityID);
*BufferSize = Size; *BufferSize = Size;
if (BufSize < Size) if (BufSize < Size)
{ {
KeReleaseSpinLock( &EntityListLock, OldIrql );
/* The buffer is too small to contain requested data */ /* The buffer is too small to contain requested data */
return TDI_BUFFER_TOO_SMALL; return TDI_BUFFER_TOO_SMALL;
} }
DbgPrint("About to copy %d TDIEntityIDs (%d bytes) to user\n", /* Return entity list -- Copy only the TDIEntityID parts. */
Count, Size); for( Count = 0; Count < EntityCount; Count++ ) {
CopyBufferToBufferChain(Buffer,
KeAcquireSpinLock(&EntityListLock, &OldIrql); Count * sizeof(TDIEntityID),
(PUCHAR)&EntityList[Count],
/* Update entity list */ sizeof(TDIEntityID));
for( Temp = EntityCount; Temp < Count; Temp++ ) {
EntityList[Temp].tei_entity = IF_ENTITY;
EntityList[Temp].tei_instance = Temp - EntityCount;
} }
EntityMax = Count;
/* Return entity list */
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size);
KeReleaseSpinLock(&EntityListLock, OldIrql); KeReleaseSpinLock(&EntityListLock, OldIrql);
*BufferSize = Size;
return TDI_SUCCESS; return TDI_SUCCESS;
} }
TDI_STATUS InfoTdiQueryGetInterfaceMIB(TDIObjectID *ID,
PNDIS_BUFFER Buffer,
UINT BufSize,
PUINT BufferSize) {
PIFENTRY OutData;
UINT ListedIfIndex, Count, Size;
PLIST_ENTRY CurrentADEEntry;
PADDRESS_ENTRY CurrentADE;
PLIST_ENTRY CurrentIFEntry;
PIP_INTERFACE CurrentIF;
PCHAR IFDescr;
KIRQL OldIrql;
OutData = ExAllocatePool( NonPagedPool,
sizeof(IFENTRY) + MAX_IFDESCR_LEN );
if( !OutData ) return STATUS_NO_MEMORY;
RtlZeroMemory( OutData,sizeof(IFENTRY) + MAX_IFDESCR_LEN );
KeAcquireSpinLock(&EntityListLock, &OldIrql);
ListedIfIndex = ID->toi_entity.tei_instance - EntityCount;
if( ListedIfIndex > EntityMax ) {
KeReleaseSpinLock(&EntityListLock,OldIrql);
return TDI_INVALID_REQUEST;
}
CurrentIFEntry = InterfaceListHead.Flink;
for( Count = 0; Count < ListedIfIndex; Count++ )
CurrentIFEntry = CurrentIFEntry->Flink;
CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
CurrentADEEntry = CurrentIF->ADEListHead.Flink;
if( CurrentADEEntry == &CurrentIF->ADEListHead ) {
KeReleaseSpinLock( &EntityListLock, OldIrql );
return TDI_INVALID_REQUEST;
}
CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry);
OutData->Index = Count + 1; /* XXX - arty What goes here?? */
OutData->Type = CurrentADE->Type;
OutData->Mtu = CurrentIF->MTU;
OutData->Speed = 10000000; /* XXX - arty Not sure */
memcpy(OutData->PhysAddr,
CurrentIF->Address,CurrentIF->AddressLength);
OutData->PhysAddrLen = CurrentIF->AddressLength;
OutData->AdminStatus = TRUE;
OutData->OperStatus = TRUE;
IFDescr = (PCHAR)&OutData[1];
strcpy(IFDescr,"ethernet adapter");
OutData->DescrLen = strlen(IFDescr);
IFDescr = IFDescr + strlen(IFDescr);
Size = IFDescr - (PCHAR)OutData;
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
*BufferSize = Size;
if( BufSize < Size ) {
return TDI_BUFFER_TOO_SMALL;
} else {
CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&OutData, Size);
return TDI_SUCCESS;
}
}
TDI_STATUS InfoTdiQueryInformationEx( TDI_STATUS InfoTdiQueryInformationEx(
PTDI_REQUEST Request, PTDI_REQUEST Request,
TDIObjectID *ID, TDIObjectID *ID,
@ -341,170 +130,72 @@ TDI_STATUS InfoTdiQueryInformationEx(
* Status of operation * Status of operation
*/ */
{ {
PLIST_ENTRY CurrentIFEntry; KIRQL OldIrql;
PLIST_ENTRY CurrentADEEntry; UINT i;
PLIST_ENTRY CurrentADFEntry; PVOID context;
PADDRESS_FILE CurrentADF; NTSTATUS Status = STATUS_SUCCESS;
PADDRESS_ENTRY CurrentADE; TDIEntityID EntityId;
PIP_INTERFACE CurrentIF; BOOL FoundEntity = FALSE;
ADDRESS_INFO Info; InfoRequest_f InfoRequest;
KIRQL OldIrql;
UINT BufSize;
UINT Entity;
UINT Offset;
ULONG Temp;
UINT Count;
UINT Size;
TDIEntityID EntityId;
Offset = 0; TI_DbgPrint(MAX_TRACE,
BufSize = *BufferSize; ("InfoEx Req: %x %x %x!%04x:%d\n",
ID->toi_class,
ID->toi_type,
ID->toi_id,
ID->toi_entity.tei_entity,
ID->toi_entity.tei_instance));
/* Check wether it is a query for a list of entities */ /* Check wether it is a query for a list of entities */
Entity = ID->toi_entity.tei_entity; if (ID->toi_entity.tei_entity == GENERIC_ENTITY)
if (Entity == GENERIC_ENTITY)
{ {
if ((ID->toi_class != INFO_CLASS_GENERIC) || if ((ID->toi_class != INFO_CLASS_GENERIC) ||
(ID->toi_type != INFO_TYPE_PROVIDER) || (ID->toi_type != INFO_TYPE_PROVIDER) ||
(ID->toi_id != ENTITY_LIST_ID)) (ID->toi_id != ENTITY_LIST_ID))
{ Status = TDI_INVALID_PARAMETER;
return TDI_INVALID_PARAMETER;
}
return InfoTdiQueryListEntities(Buffer, BufSize, BufferSize);
}
/* Get an IFENTRY */
if (ID->toi_class == INFO_CLASS_PROTOCOL &&
ID->toi_type == INFO_TYPE_PROVIDER &&
ID->toi_id == IF_MIB_STATS_ID)
{
if(ID->toi_entity.tei_entity != IF_ENTITY)
return TDI_INVALID_REQUEST;
return InfoTdiQueryGetInterfaceMIB(ID, Buffer, BufSize, BufferSize);
}
if ((Entity != CL_TL_ENTITY) && (Entity != CO_TL_ENTITY))
{
/* We can't handle this entity, pass it on */
return IPTdiQueryInformationEx(
Request, ID, Buffer, BufferSize, Context);
}
/* Make return parameters consistent every time */
*BufferSize = 0;
if (ID->toi_entity.tei_instance != TL_INSTANCE)
{
/* We only support a single instance */
return TDI_INVALID_REQUEST;
}
if (ID->toi_class == INFO_CLASS_GENERIC)
{
if ((ID->toi_type != INFO_TYPE_PROVIDER) ||
(ID->toi_id != ENTITY_TYPE_ID))
return TDI_INVALID_PARAMETER;
if (BufSize < sizeof(ULONG))
{
return TDI_BUFFER_TOO_SMALL;
}
if (Entity == CL_TL_ENTITY)
{
Temp = CL_TL_UDP;
}
else if (Entity == CO_TL_ENTITY)
{
Temp = CO_TL_TCP;
}
else else
{ Status = InfoTdiQueryListEntities(Buffer, BufferSize);
return TDI_INVALID_PARAMETER; } else {
} KeAcquireSpinLock( &EntityListLock, &OldIrql );
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&Temp, sizeof(ULONG)); for( i = 0; i < EntityCount; i++ ) {
if( EntityList[i].tei_entity == ID->toi_entity.tei_entity &&
return TDI_SUCCESS; EntityList[i].tei_instance == ID->toi_entity.tei_instance ) {
InfoRequest = EntityList[i].info_req;
context = EntityList[i].context;
FoundEntity = TRUE;
break;
}
}
KeReleaseSpinLock( &EntityListLock, OldIrql );
if( FoundEntity ) {
TI_DbgPrint(MAX_TRACE,
("Calling Entity %d (%04x:%d) InfoEx (%x,%x,%x)\n",
i, ID->toi_entity.tei_entity,
ID->toi_entity.tei_instance,
ID->toi_class, ID->toi_type, ID->toi_id));
Status = InfoRequest( ID->toi_class,
ID->toi_type,
ID->toi_id,
context,
&ID->toi_entity,
Buffer,
BufferSize );
}
} }
if (ID->toi_class == INFO_CLASS_PROTOCOL) TI_DbgPrint(MAX_TRACE,("Status: %08x\n", Status));
{
if (ID->toi_type != INFO_TYPE_PROVIDER)
{
return TDI_INVALID_PARAMETER;
}
switch (ID->toi_id) return Status;
{
case UDP_MIB_STAT_ID:
if (Entity != CL_TL_ENTITY)
{
return TDI_INVALID_PARAMETER;
}
if (BufSize < sizeof(UDPStats))
{
return TDI_BUFFER_TOO_SMALL;
}
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&UDPStats, sizeof(UDP_STATISTICS));
return TDI_SUCCESS;
case UDP_MIB_TABLE_ID:
if (Entity != CL_TL_ENTITY)
{
return TDI_INVALID_PARAMETER;
}
Offset = 0;
KeAcquireSpinLock(&AddressFileListLock, &OldIrql);
CurrentADFEntry = AddressFileListHead.Flink;
while (CurrentADFEntry != &AddressFileListHead)
{
CurrentADF = CONTAINING_RECORD(CurrentADFEntry, ADDRESS_FILE, ListEntry);
if (Offset + sizeof(ADDRESS_INFO) > BufSize)
{
KeReleaseSpinLock(&AddressFileListLock, OldIrql);
*BufferSize = Offset;
return TDI_BUFFER_OVERFLOW;
}
Info.LocalAddress = CurrentADF->ADE->Address->Address.IPv4Address;
Info.LocalPort = CurrentADF->Port;
Count = CopyBufferToBufferChain(Buffer, Offset, (PUCHAR)&Info, sizeof(ADDRESS_INFO));
Offset += Count;
CurrentADFEntry = CurrentADFEntry->Flink;
}
KeReleaseSpinLock(&AddressFileListLock, OldIrql);
*BufferSize = Offset;
return STATUS_SUCCESS;
default:
/* We can't handle this ID */
return TDI_INVALID_PARAMETER;
}
}
return TDI_INVALID_PARAMETER;
} }
TDI_STATUS InfoTdiSetInformationEx( TDI_STATUS InfoTdiSetInformationEx
PTDI_REQUEST Request, (PTDI_REQUEST Request,
TDIObjectID *ID, TDIObjectID *ID,
PVOID Buffer, PVOID Buffer,
UINT BufferSize) UINT BufferSize)
/* /*
* FUNCTION: Sets extended information * FUNCTION: Sets extended information
* ARGUMENTS: * ARGUMENTS:
@ -516,30 +207,30 @@ TDI_STATUS InfoTdiSetInformationEx(
* Status of operation * Status of operation
*/ */
{ {
switch( ID->toi_class ) { switch( ID->toi_class ) {
case INFO_CLASS_PROTOCOL: case INFO_CLASS_PROTOCOL:
switch( ID->toi_type ) { switch( ID->toi_type ) {
case INFO_TYPE_PROVIDER: case INFO_TYPE_PROVIDER:
switch( ID->toi_id ) { switch( ID->toi_id ) {
case IP_MIB_ROUTETABLE_ENTRY_ID: case IP_MIB_ROUTETABLE_ENTRY_ID:
if( ID->toi_entity.tei_entity == CL_NL_ENTITY && if( ID->toi_entity.tei_entity == CL_NL_ENTITY &&
ID->toi_entity.tei_instance == TL_INSTANCE && ID->toi_entity.tei_instance == TL_INSTANCE &&
BufferSize >= sizeof(IPROUTE_ENTRY) ) { BufferSize >= sizeof(IPROUTE_ENTRY) ) {
/* Add route -- buffer is an IPRouteEntry */ /* Add route -- buffer is an IPRouteEntry */
PIPROUTE_ENTRY ire = (PIPROUTE_ENTRY)Buffer; PIPROUTE_ENTRY ire = (PIPROUTE_ENTRY)Buffer;
RouteFriendlyAddRoute( ire ); RouteFriendlyAddRoute( ire );
} else { } else {
return TDI_INVALID_PARAMETER; return TDI_INVALID_PARAMETER;
/* In my experience, we are being over /* In my experience, we are being over
protective compared to windows */ protective compared to windows */
}
break;
}
break;
} }
break; break;
}
break;
} }
break;
}
return TDI_INVALID_PARAMETER;
}
return TDI_INVALID_PARAMETER;
}

View file

@ -0,0 +1,108 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/interface.c
* PURPOSE: Convenient abstraction for getting and setting information
* in IP_INTERFACE.
* PROGRAMMERS: Art Yerkes
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <lan.h>
#include <address.h>
#include <pool.h>
#include <ip.h>
NTSTATUS GetInterfaceIPv4Address( PIP_INTERFACE Interface,
ULONG TargetType,
PULONG Address ) {
PLIST_ENTRY CurrentIFEntry;
PLIST_ENTRY CurrentADEEntry;
PADDRESS_ENTRY CurrentADE;
CurrentADEEntry = Interface->ADEListHead.Flink;
while (CurrentADEEntry != &Interface->ADEListHead)
{
CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry);
if (CurrentADE->Type == TargetType) {
*Address = CurrentADE->Address->Address.IPv4Address;
return STATUS_SUCCESS;
}
CurrentADEEntry = CurrentADEEntry->Flink;
}
return STATUS_UNSUCCESSFUL;
}
UINT CountInterfaces() {
DWORD Count = 0;
KIRQL OldIrql;
PLIST_ENTRY CurrentIFEntry;
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
while (CurrentIFEntry != &InterfaceListHead) {
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
return Count;
}
UINT CountInterfaceAddresses( PIP_INTERFACE Interface ) {
UINT AddrCount = 0;
PADDRESS_ENTRY CurrentADE;
PLIST_ENTRY CurrentADEntry;
CurrentADEntry = Interface->ADEListHead.Flink;
while( CurrentADEntry != &Interface->ADEListHead ) {
CurrentADEntry = CurrentADEntry->Flink;
CurrentADE = CONTAINING_RECORD(CurrentADEntry,
ADDRESS_ENTRY,
ListEntry);
if( CurrentADE->Type == ADE_UNICAST )
AddrCount++;
}
return AddrCount;
}
NTSTATUS GetInterfaceSpeed( PIP_INTERFACE Interface, PUINT Speed ) {
NDIS_STATUS NdisStatus;
PLAN_ADAPTER IF = (PLAN_ADAPTER)Interface->Context;
/* Get maximum link speed */
NdisStatus = NDISCall(IF,
NdisRequestQueryInformation,
OID_GEN_LINK_SPEED,
Speed,
sizeof(UINT));
return
NdisStatus != NDIS_STATUS_SUCCESS ?
STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
}
NTSTATUS GetInterfaceName( PIP_INTERFACE Interface,
PCHAR NameBuffer,
UINT Len ) {
NDIS_STATUS NdisStatus;
PLAN_ADAPTER IF = (PLAN_ADAPTER)Interface->Context;
/* Get maximum link speed */
NdisStatus = NDISCall(IF,
NdisRequestQueryInformation,
OID_GEN_FRIENDLY_NAME,
NameBuffer,
Len);
return
NdisStatus != NDIS_STATUS_SUCCESS ?
STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
}

View file

@ -0,0 +1,30 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/dispatch.h
* PURPOSE: TDI dispatch routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/08-2000 Created
* TODO: Validate device object in all dispatch routines
*/
#include <roscfg.h>
#include <tcpip.h>
#include <dispatch.h>
#include <routines.h>
#include <datagram.h>
#include <info.h>
NTSTATUS IRPFinish( PIRP Irp, NTSTATUS Status ) {
IoSetCancelRoutine( Irp, NULL );
if( Status == STATUS_PENDING )
IoMarkIrpPending( Irp );
else {
Irp->IoStatus.Status = Status;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
}
return Status;
}

View file

@ -17,6 +17,8 @@
#include <udp.h> #include <udp.h>
#include <tcp.h> #include <tcp.h>
#include <rosrtl/string.h> #include <rosrtl/string.h>
#include <info.h>
#include <memtrack.h>
#define NDEBUG #define NDEBUG
@ -33,7 +35,7 @@ PDEVICE_OBJECT RawIPDeviceObject = NULL;
NDIS_HANDLE GlobalPacketPool = NULL; NDIS_HANDLE GlobalPacketPool = NULL;
NDIS_HANDLE GlobalBufferPool = NULL; NDIS_HANDLE GlobalBufferPool = NULL;
KSPIN_LOCK EntityListLock; KSPIN_LOCK EntityListLock;
TDIEntityID *EntityList = NULL; TDIEntityInfo *EntityList = NULL;
ULONG EntityCount = 0; ULONG EntityCount = 0;
ULONG EntityMax = 0; ULONG EntityMax = 0;
UDP_STATISTICS UDPStats; UDP_STATISTICS UDPStats;
@ -456,18 +458,9 @@ TiDispatchOpenClose(
Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST;
} }
if (Status != STATUS_PENDING) {
IrpSp->Control &= ~SL_PENDING_RETURNED;
Irp->IoStatus.Status = Status;
TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
return Status; return IRPFinish( Irp, Status );
} }
@ -487,7 +480,7 @@ TiDispatchInternal(
* Status of the operation * Status of the operation
*/ */
{ {
NTSTATUS Status; NTSTATUS Status;
PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION IrpSp;
IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp);
@ -560,17 +553,9 @@ TiDispatchInternal(
Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST;
} }
if (Status != STATUS_PENDING) {
Irp->IoStatus.Status = Status;
TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status)); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
return Status; return IRPFinish( Irp, Status );
} }
@ -627,17 +612,9 @@ TiDispatch(
} }
} }
if (Status != STATUS_PENDING) {
Irp->IoStatus.Status = Status;
TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status)); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
return Status; return IRPFinish( Irp, Status );
} }
@ -726,6 +703,14 @@ DriverEntry(
NDIS_STRING DeviceName; NDIS_STRING DeviceName;
TI_DbgPrint(MAX_TRACE, ("Called.\n")); TI_DbgPrint(MAX_TRACE, ("Called.\n"));
TrackingInit();
TrackTag(NDIS_BUFFER_TAG);
TrackTag(NDIS_PACKET_TAG);
TrackTag(FBSD_MALLOC);
TrackTag(EXALLOC_TAG);
InitOskitTCP();
/* TdiInitialize() ? */ /* TdiInitialize() ? */
@ -770,6 +755,28 @@ DriverEntry(
return Status; return Status;
} }
/* Setup network layer and transport layer entities */
KeInitializeSpinLock(&EntityListLock);
EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * MAX_TDI_ENTITIES );
if (!NT_SUCCESS(Status)) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
TiUnload(DriverObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
EntityList[0].tei_entity = CL_NL_ENTITY;
EntityList[0].tei_instance = 0;
EntityList[0].context = 0;
EntityList[0].info_req = InfoNetworkLayerTdiQueryEx;
EntityList[0].info_set = InfoNetworkLayerTdiSetEx;
EntityList[1].tei_entity = CL_TL_ENTITY;
EntityList[1].tei_instance = 0;
EntityList[1].context = 0;
EntityList[1].info_req = InfoTransportLayerTdiQueryEx;
EntityList[1].info_set = InfoTransportLayerTdiSetEx;
EntityCount = 2;
EntityMax = MAX_TDI_ENTITIES;
/* Allocate NDIS packet descriptors */ /* Allocate NDIS packet descriptors */
NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT)); NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT));
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
@ -830,22 +837,6 @@ DriverEntry(
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
/* Setup network layer and transport layer entities */
KeInitializeSpinLock(&EntityListLock);
EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * MAX_TDI_ENTITIES );
if (!NT_SUCCESS(Status)) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
TiUnload(DriverObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
EntityList[0].tei_entity = CL_NL_ENTITY;
EntityList[0].tei_instance = 0;
EntityList[1].tei_entity = CL_TL_ENTITY;
EntityList[1].tei_instance = 0;
EntityCount = 2;
EntityMax = MAX_TDI_ENTITIES;
/* Use direct I/O */ /* Use direct I/O */
IPDeviceObject->Flags |= DO_DIRECT_IO; IPDeviceObject->Flags |= DO_DIRECT_IO;
RawIPDeviceObject->Flags |= DO_DIRECT_IO; RawIPDeviceObject->Flags |= DO_DIRECT_IO;

View file

@ -0,0 +1,146 @@
#define MEMTRACK_NO_POOL
#include <roscfg.h>
#include <tcpip.h>
#include <ntddk.h>
#include <memtrack.h>
#ifdef MEMTRACK
LIST_ENTRY AllocatedObjectsList;
KSPIN_LOCK AllocatedObjectsLock;
DWORD TagsToShow[MEMTRACK_MAX_TAGS_TO_TRACK] = { 0 };
VOID TrackTag( DWORD Tag ) {
UINT i;
for( i = 0; TagsToShow[i]; i++ );
TagsToShow[i] = Tag;
}
VOID TrackingInit() {
KeInitializeSpinLock( &AllocatedObjectsLock );
InitializeListHead( &AllocatedObjectsList );
}
VOID ShowTrackedThing( PCHAR What, PALLOCATION_TRACKER Thing,
PCHAR File, UINT Line ) {
/* if( ShowTag( Thing->Tag ) ) */
if( File ) {
DbgPrint( "[%s] Thing %08x %c%c%c%c (%s:%d) (Called from %s:%d)\n",
What,
Thing->Thing,
((PCHAR)&Thing->Tag)[3],
((PCHAR)&Thing->Tag)[2],
((PCHAR)&Thing->Tag)[1],
((PCHAR)&Thing->Tag)[0],
Thing->FileName,
Thing->LineNo,
File, Line );
} else {
DbgPrint( "[%s] Thing %08x %c%c%c%c (%s:%d)\n",
What,
Thing->Thing,
((PCHAR)&Thing->Tag)[3],
((PCHAR)&Thing->Tag)[2],
((PCHAR)&Thing->Tag)[1],
((PCHAR)&Thing->Tag)[0],
Thing->FileName,
Thing->LineNo );
}
}
VOID TrackWithTag( DWORD Tag, PVOID Thing, PCHAR FileName, DWORD LineNo ) {
PALLOCATION_TRACKER TrackedThing =
ExAllocatePool( NonPagedPool, sizeof(*TrackedThing) );
KIRQL OldIrql;
PLIST_ENTRY Entry;
PALLOCATION_TRACKER ThingInList;
KeAcquireSpinLock( &AllocatedObjectsLock, &OldIrql );
Entry = AllocatedObjectsList.Flink;
while( Entry != &AllocatedObjectsList ) {
ThingInList = CONTAINING_RECORD(Entry, ALLOCATION_TRACKER, Entry);
if( ThingInList->Thing == Thing ) {
RemoveEntryList(Entry);
ShowTrackedThing( "Alloc", ThingInList, FileName, LineNo );
ExFreePool( ThingInList );
TrackDumpFL( FileName, LineNo );
KeReleaseSpinLock( &AllocatedObjectsLock, OldIrql );
DbgPrint("TRACK: SPECIFIED ALREADY ALLOCATED ITEM %x\n", Thing);
KeBugCheck( 0 );
}
Entry = Entry->Flink;
}
KeReleaseSpinLock( &AllocatedObjectsLock, OldIrql );
if( TrackedThing ) {
TrackedThing->Tag = Tag;
TrackedThing->Thing = Thing;
TrackedThing->FileName = FileName;
TrackedThing->LineNo = LineNo;
ExInterlockedInsertTailList( &AllocatedObjectsList,
&TrackedThing->Entry,
&AllocatedObjectsLock );
ShowTrackedThing( "Alloc", TrackedThing, FileName, LineNo );
}
/*TrackDumpFL( FileName, LineNo );*/
}
BOOL ShowTag( DWORD Tag ) {
UINT i;
for( i = 0; TagsToShow[i] && TagsToShow[i] != Tag; i++ );
return TagsToShow[i] ? TRUE : FALSE;
}
VOID UntrackFL( PCHAR File, DWORD Line, PVOID Thing ) {
KIRQL OldIrql;
PLIST_ENTRY Entry;
PALLOCATION_TRACKER ThingInList;
KeAcquireSpinLock( &AllocatedObjectsLock, &OldIrql );
Entry = AllocatedObjectsList.Flink;
while( Entry != &AllocatedObjectsList ) {
ThingInList = CONTAINING_RECORD(Entry, ALLOCATION_TRACKER, Entry);
if( ThingInList->Thing == Thing ) {
RemoveEntryList(Entry);
ShowTrackedThing( "Free ", ThingInList, File, Line );
ExFreePool( ThingInList );
KeReleaseSpinLock( &AllocatedObjectsLock, OldIrql );
/* TrackDumpFL( File, Line ); */
return;
}
Entry = Entry->Flink;
}
KeReleaseSpinLock( &AllocatedObjectsLock, OldIrql );
TrackDumpFL( File, Line );
DbgPrint("UNTRACK: SPECIFIED ALREADY FREE ITEM %x\n", Thing);
KeBugCheck( 0 );
}
VOID TrackDumpFL( PCHAR File, DWORD Line ) {
KIRQL OldIrql;
PLIST_ENTRY Entry;
PALLOCATION_TRACKER Thing;
DbgPrint("Dump: %s:%d\n", File, Line);
KeAcquireSpinLock( &AllocatedObjectsLock, &OldIrql );
Entry = AllocatedObjectsList.Flink;
while( Entry != &AllocatedObjectsList ) {
Thing = CONTAINING_RECORD(Entry, ALLOCATION_TRACKER, Entry);
ShowTrackedThing( "Dump ", Thing, 0, 0 );
Entry = Entry->Flink;
}
KeReleaseSpinLock( &AllocatedObjectsLock, OldIrql );
}
#endif/*MEMTRACK*/

View file

@ -0,0 +1,248 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/ninfo.c
* PURPOSE: Network information
* PROGRAMMERS: Art Yerkes
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <address.h>
#include <info.h>
#include <pool.h>
#include <prefix.h>
#include <ip.h>
#include <route.h>
TDI_STATUS InfoTdiQueryGetAddrTable( PNDIS_BUFFER Buffer,
PUINT BufferSize ) {
PIP_INTERFACE CurrentIF;
PLIST_ENTRY CurrentIFEntry;
TDI_STATUS Status = TDI_INVALID_REQUEST;
KIRQL OldIrql;
UINT Count = 1; /* Start adapter indices at 1 */
UINT IfCount = CountInterfaces();
PIPADDR_ENTRY IpAddress =
ExAllocatePool( NonPagedPool, sizeof( IPADDR_ENTRY ) * IfCount );
PIPADDR_ENTRY IpCurrent = IpAddress;
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
while (CurrentIFEntry != &InterfaceListHead)
{
CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
IpCurrent->Index = Count;
IpCurrent->Addr = 0;
IpCurrent->BcastAddr = 0;
IpCurrent->Mask = 0;
/* Locate the diffrent addresses and put them the right place */
GetInterfaceIPv4Address( CurrentIF,
ADE_UNICAST,
&IpAddress->Addr );
GetInterfaceIPv4Address( CurrentIF,
ADE_MULTICAST,
&IpAddress->BcastAddr );
GetInterfaceIPv4Address( CurrentIF,
ADE_ADDRMASK,
&IpAddress->Mask );
IpCurrent++;
CurrentIFEntry = CurrentIFEntry->Flink;
Count++;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
Status = InfoCopyOut( IpAddress, sizeof(*IpAddress) * Count,
Buffer, BufferSize );
ExFreePool( IpAddress );
TI_DbgPrint(MAX_TRACE, ("Returning %08x\n", Status));
return Status;
}
/* Get IPRouteEntry s for each of the routes in the system */
TDI_STATUS InfoTdiQueryGetRouteTable( PNDIS_BUFFER Buffer, PUINT BufferSize ) {
PIP_INTERFACE CurrentIF;
PLIST_ENTRY CurrentIFEntry;
TDI_STATUS Status;
KIRQL OldIrql;
UINT RtCount = CountFIBs(),
Size = sizeof( IPROUTE_ENTRY ) * RtCount;
PFIB_ENTRY RCache =
ExAllocatePool( NonPagedPool, sizeof( FIB_ENTRY ) * RtCount ),
RCacheCur = RCache;
PIPROUTE_ENTRY RouteEntries = ExAllocatePool( NonPagedPool, Size ),
RtCurrent = RouteEntries;
TI_DbgPrint(MAX_TRACE, ("Called, routes = %d, RCache = %08x\n",
RtCount, RCache));
if( !RCache || !RouteEntries ) {
if( RCache ) ExFreePool( RCache );
if( RouteEntries ) ExFreePool( RouteEntries );
return STATUS_NO_MEMORY;
}
RtlZeroMemory( RouteEntries, Size );
RtCount = CopyFIBs( RCache );
while( RtCurrent < RouteEntries + RtCount ) {
/* Copy Desitnation */
if( RCacheCur->NetworkAddress && RCacheCur->Netmask &&
RCacheCur->Router && RCacheCur->Router->Address ) {
TI_DbgPrint(MAX_TRACE, ("%d: NA %08x NM %08x GW %08x MT %d\n",
RtCurrent - RouteEntries,
RCacheCur->NetworkAddress->Address,
RCacheCur->Netmask->Address,
RCacheCur->Router->Address->Address,
RCacheCur->Metric));
RtlCopyMemory( &RtCurrent->Dest,
&RCacheCur->NetworkAddress->Address,
sizeof(RtCurrent->Dest) );
RtlCopyMemory( &RtCurrent->Mask,
&RCacheCur->Netmask->Address,
sizeof(RtCurrent->Mask) );
/* Currently, this address is stuffed into the pointer.
* That probably is not intended. */
RtlCopyMemory( &RtCurrent->Gw,
&RCacheCur->Router->Address->Address,
sizeof(RtCurrent->Gw) );
RtCurrent->Metric1 = RCacheCur->Metric;
RtCurrent->Type = 2 /* PF_INET */;
KeAcquireSpinLock(&EntityListLock, &OldIrql);
for( RtCurrent->Index = EntityCount - 1;
RtCurrent->Index >= 0 &&
RCacheCur->Router->Interface !=
EntityList[RtCurrent->Index].context;
RtCurrent->Index-- );
RtCurrent->Index = EntityList[RtCurrent->Index].tei_instance;
KeReleaseSpinLock(&EntityListLock, OldIrql);
} else {
TI_DbgPrint(MAX_TRACE, ("%d: BAD: NA %08x NM %08x GW %08x MT %d\n",
RtCurrent - RouteEntries,
RCacheCur->NetworkAddress,
RCacheCur->Netmask,
RCacheCur->Router,
RCacheCur->Router ?
RCacheCur->Router->Address : 0,
RCacheCur->Metric));
}
RtCurrent++; RCacheCur++;
}
Status = InfoCopyOut( RouteEntries, Size, Buffer, BufferSize );
ExFreePool( RouteEntries );
ExFreePool( RCache );
TI_DbgPrint(MAX_TRACE, ("Returning %08x\n", Status));
return Status;
}
TDI_STATUS InfoTdiQueryGetIPSnmpInfo( PNDIS_BUFFER Buffer,
PUINT BufferSize ) {
KIRQL OldIrql;
PIP_INTERFACE CurrentIF;
PLIST_ENTRY CurrentIFEntry;
IPSNMP_INFO SnmpInfo;
UINT IfCount = CountInterfaces();
UINT AddrCount = 0;
UINT RouteCount = CountRouteNodes( NULL );
TDI_STATUS Status = TDI_INVALID_REQUEST;
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
RtlZeroMemory(&SnmpInfo, sizeof(IPSNMP_INFO));
/* Count number of addresses */
AddrCount = 0;
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
CurrentIFEntry = InterfaceListHead.Flink;
while (CurrentIFEntry != &InterfaceListHead)
{
CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
AddrCount += CountInterfaceAddresses( CurrentIF );
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
SnmpInfo.NumIf = IfCount;
SnmpInfo.NumAddr = AddrCount;
SnmpInfo.NumRoutes = RouteCount;
Status = InfoCopyOut( &SnmpInfo, sizeof(SnmpInfo),
Buffer, BufferSize );
TI_DbgPrint(MAX_TRACE, ("Returning %08x\n", Status));
return Status;
}
TDI_STATUS InfoNetworkLayerTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize ) {
TDI_STATUS Status = TDI_INVALID_REQUEST;
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
switch( InfoClass ) {
case INFO_CLASS_GENERIC:
if( InfoType == INFO_TYPE_PROVIDER && InfoId == ENTITY_TYPE_ID ) {
ULONG Return = CL_NL_IP;
Status = InfoCopyOut( &Return, sizeof(Return),
Buffer, BufferSize );
}
break;
case INFO_CLASS_PROTOCOL:
switch( InfoType ) {
case INFO_TYPE_PROVIDER:
switch( InfoId ) {
case IP_MIB_ADDRTABLE_ENTRY_ID:
Status = InfoTdiQueryGetAddrTable( Buffer, BufferSize );
break;
case IP_MIB_ROUTETABLE_ENTRY_ID:
Status = InfoTdiQueryGetRouteTable( Buffer, BufferSize );
break;
case IP_MIB_STATS_ID:
Status = InfoTdiQueryGetIPSnmpInfo( Buffer, BufferSize );
break;
}
break;
}
}
TI_DbgPrint(MAX_TRACE, ("Returning %08x\n", Status));
return Status;
}
TDI_STATUS InfoNetworkLayerTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize ) {
}

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <pool.h> #include <pool.h>

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <routines.h> #include <routines.h>
#include <pool.h> #include <pool.h>
@ -16,89 +17,6 @@
static UINT RandomNumber = 0x12345678; static UINT RandomNumber = 0x12345678;
inline NTSTATUS BuildDatagramSendRequest(
PDATAGRAM_SEND_REQUEST *SendRequest,
PIP_ADDRESS RemoteAddress,
USHORT RemotePort,
PNDIS_BUFFER Buffer,
DWORD BufferSize,
DATAGRAM_COMPLETION_ROUTINE Complete,
PVOID Context,
DATAGRAM_BUILD_ROUTINE Build,
ULONG Flags)
/*
* FUNCTION: Allocates and intializes a datagram send request
* ARGUMENTS:
* SendRequest = Pointer to datagram send request
* RemoteAddress = Pointer to remote IP address
* RemotePort = Remote port number
* Buffer = Pointer to NDIS buffer to send
* BufferSize = Size of Buffer
* Complete = Completion routine
* Context = Pointer to context information
* Build = Datagram build routine
* Flags = Protocol specific flags
* RETURNS:
* Status of operation
*/
{
PDATAGRAM_SEND_REQUEST Request;
Request = ExAllocatePool(NonPagedPool, sizeof(DATAGRAM_SEND_REQUEST));
if (!Request)
return STATUS_INSUFFICIENT_RESOURCES;
InitializeDatagramSendRequest(
Request,
RemoteAddress,
RemotePort,
Buffer,
BufferSize,
Complete,
Context,
Build,
Flags);
*SendRequest = Request;
return STATUS_SUCCESS;
}
inline NTSTATUS BuildTCPSendRequest(
PTCP_SEND_REQUEST *SendRequest,
DATAGRAM_COMPLETION_ROUTINE Complete,
PVOID Context,
PVOID ProtocolContext)
/*
* FUNCTION: Allocates and intializes a TCP send request
* ARGUMENTS:
* SendRequest = Pointer to TCP send request
* Complete = Completion routine
* Context = Pointer to context information
* ProtocolContext = Protocol specific context
* RETURNS:
* Status of operation
*/
{
PTCP_SEND_REQUEST Request;
Request = ExAllocatePool(NonPagedPool, sizeof(TCP_SEND_REQUEST));
if (!Request)
return STATUS_INSUFFICIENT_RESOURCES;
InitializeTCPSendRequest(
Request,
Complete,
Context,
ProtocolContext);
*SendRequest = Request;
return STATUS_SUCCESS;
}
UINT Random( UINT Random(
VOID) VOID)
/* /*
@ -389,35 +307,6 @@ UINT CopyPacketToBufferChain(
} }
VOID FreeNdisPacket(
PNDIS_PACKET Packet)
/*
* FUNCTION: Frees an NDIS packet
* ARGUMENTS:
* Packet = Pointer to NDIS packet to be freed
*/
{
PNDIS_BUFFER Buffer, NextBuffer;
TI_DbgPrint(DEBUG_BUFFER, ("Packet (0x%X)\n", Packet));
/* Free all the buffers in the packet first */
NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
for (; Buffer != NULL; Buffer = NextBuffer) {
PVOID Data;
UINT Length;
NdisGetNextBuffer(Buffer, &NextBuffer);
NdisQueryBuffer(Buffer, &Data, &Length);
NdisFreeBuffer(Buffer);
ExFreePool(Data);
}
/* Finally free the NDIS packet discriptor */
NdisFreePacket(Packet);
}
PVOID AdjustPacket( PVOID AdjustPacket(
PNDIS_PACKET Packet, PNDIS_PACKET Packet,
UINT Available, UINT Available,
@ -538,32 +427,21 @@ VOID DisplayIPPacket(
for (; Buffer != NULL; Buffer = NextBuffer) { for (; Buffer != NULL; Buffer = NextBuffer) {
NdisGetNextBuffer(Buffer, &NextBuffer); NdisGetNextBuffer(Buffer, &NextBuffer);
NdisQueryBuffer(Buffer, (PVOID)&p, &Length); NdisQueryBuffer(Buffer, (PVOID)&p, &Length);
OskitDumpBuffer( p, Length );
for (i = 0; i < Length; i++) {
if (i % 16 == 0)
DbgPrint("\n");
DbgPrint("%02X ", (p[i]) & 0xFF);
}
DbgPrint("\n");
} }
} else { } else {
p = IPPacket->Header; p = IPPacket->Header;
Length = IPPacket->ContigSize; Length = IPPacket->ContigSize;
for (i = 0; i < Length; i++) { OskitDumpBuffer( p, Length );
if (i % 16 == 0)
DbgPrint("\n");
DbgPrint("%02X ", (p[i]) & 0xFF);
}
DbgPrint("\n");
} }
if (IPPacket->NdisPacket) { if (IPPacket->NdisPacket) {
NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, NULL, &Length); NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, NULL, &Length);
Length -= MaxLLHeaderSize; Length -= MaxLLHeaderSize;
CharBuffer = ExAllocatePool(NonPagedPool, Length); CharBuffer = exAllocatePool(NonPagedPool, Length);
Length = CopyPacketToBuffer(CharBuffer, IPPacket->NdisPacket, MaxLLHeaderSize, Length); Length = CopyPacketToBuffer(CharBuffer, IPPacket->NdisPacket, MaxLLHeaderSize, Length);
DisplayIPHeader(CharBuffer, Length); DisplayIPHeader(CharBuffer, Length);
ExFreePool(CharBuffer); exFreePool(CharBuffer);
} else { } else {
CharBuffer = IPPacket->Header; CharBuffer = IPPacket->Header;
Length = IPPacket->ContigSize; Length = IPPacket->ContigSize;
@ -633,10 +511,10 @@ VOID DisplayTCPPacket(
if (IPPacket->NdisPacket) { if (IPPacket->NdisPacket) {
NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, NULL, &Length); NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, NULL, &Length);
Length -= MaxLLHeaderSize; Length -= MaxLLHeaderSize;
Buffer = ExAllocatePool(NonPagedPool, Length); Buffer = exAllocatePool(NonPagedPool, Length);
Length = CopyPacketToBuffer(Buffer, IPPacket->NdisPacket, MaxLLHeaderSize, Length); Length = CopyPacketToBuffer(Buffer, IPPacket->NdisPacket, MaxLLHeaderSize, Length);
DisplayTCPHeader(Buffer, Length); DisplayTCPHeader(Buffer, Length);
ExFreePool(Buffer); exFreePool(Buffer);
} else { } else {
Buffer = IPPacket->Header; Buffer = IPPacket->Header;
Length = IPPacket->ContigSize; Length = IPPacket->ContigSize;
@ -644,4 +522,90 @@ VOID DisplayTCPPacket(
} }
} }
#endif /* DBG */ #endif DBG /* DBG */
void GetDataPtr( PNDIS_PACKET Packet,
UINT Offset,
PUCHAR *DataOut,
PUINT Size ) {
PNDIS_BUFFER Buffer;
NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
if( !Buffer ) return NULL;
SkipToOffset( Buffer, Offset, DataOut, Size );
}
#undef NdisAllocatePacket
#undef NdisAllocateBuffer
#undef NdisFreeBuffer
#undef NdisFreePacket
NDIS_STATUS AllocatePacketWithBufferX( PNDIS_PACKET *NdisPacket,
PCHAR Data, UINT Len,
PCHAR File, UINT Line ) {
PNDIS_PACKET Packet;
PNDIS_BUFFER Buffer;
NDIS_STATUS Status;
PCHAR NewData;
NewData = ExAllocatePool( NonPagedPool, Len );
if( !NewData ) return NDIS_STATUS_NOT_ACCEPTED; // XXX
TrackWithTag(EXALLOC_TAG, NewData, File, Line);
if( Data )
RtlCopyMemory(NewData, Data, Len);
NdisAllocatePacket( &Status, &Packet, GlobalPacketPool );
if( Status != NDIS_STATUS_SUCCESS ) {
ExFreePool( NewData );
return Status;
}
TrackWithTag(NDIS_PACKET_TAG, Packet, File, Line);
NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, NewData, Len );
if( Status != NDIS_STATUS_SUCCESS ) {
ExFreePool( NewData );
FreeNdisPacket( Packet );
}
TrackWithTag(NDIS_BUFFER_TAG, Buffer, File, Line);
NdisChainBufferAtFront( Packet, Buffer );
*NdisPacket = Packet;
return NDIS_STATUS_SUCCESS;
}
VOID FreeNdisPacketX
( PNDIS_PACKET Packet,
PCHAR File,
UINT Line )
/*
* FUNCTION: Frees an NDIS packet
* ARGUMENTS:
* Packet = Pointer to NDIS packet to be freed
*/
{
PNDIS_BUFFER Buffer, NextBuffer;
TI_DbgPrint(DEBUG_BUFFER, ("Packet (0x%X)\n", Packet));
/* Free all the buffers in the packet first */
NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
for (; Buffer != NULL; Buffer = NextBuffer) {
PVOID Data;
UINT Length;
NdisGetNextBuffer(Buffer, &NextBuffer);
NdisQueryBuffer(Buffer, &Data, &Length);
NdisFreeBuffer(Buffer);
UntrackFL(File,Line,Buffer);
ExFreePool(Data);
UntrackFL(File,Line,Data);
}
/* Finally free the NDIS packet discriptor */
NdisFreePacket(Packet);
UntrackFL(File,Line,Packet);
}

View file

@ -0,0 +1,40 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/tinfo.c
* PURPOSE: Transport layer information
* PROGRAMMERS: Art Yerkes
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <address.h>
#include <pool.h>
#include <ip.h>
TDI_STATUS InfoTransportLayerTdiQueryEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PNDIS_BUFFER Buffer,
PUINT BufferSize ) {
if( InfoClass == INFO_CLASS_GENERIC &&
InfoType == INFO_TYPE_PROVIDER &&
InfoId == ENTITY_TYPE_ID ) {
ULONG Temp = CL_TL_UDP;
return InfoCopyOut( &Temp, sizeof(Temp), Buffer, BufferSize );
}
return TDI_INVALID_REQUEST;
}
TDI_STATUS InfoTransportLayerTdiSetEx( UINT InfoClass,
UINT InfoType,
UINT InfoId,
PVOID Context,
TDIEntityID *id,
PCHAR Buffer,
UINT BufferSize ) {
}

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <datagram.h> #include <datagram.h>
#include <routines.h> #include <routines.h>
@ -124,13 +125,6 @@ VOID SendDatagramComplete(
CompleteContext = SendRequest->Context; CompleteContext = SendRequest->Context;
BytesSent = SendRequest->BufferSize; BytesSent = SendRequest->BufferSize;
/* Remove data buffer before releasing memory for packet buffers */
NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
NdisUnchainBufferAtBack(Packet, &NdisBuffer);
FreeNdisPacket(Packet);
DereferenceObject(SendRequest->RemoteAddress);
ExFreePool(SendRequest);
/* If there are pending send requests, shedule worker function */ /* If there are pending send requests, shedule worker function */
KeAcquireSpinLock(&DGPendingListLock, &OldIrql); KeAcquireSpinLock(&DGPendingListLock, &OldIrql);
QueueWorkItem = (!IsListEmpty(&DGPendingListHead)); QueueWorkItem = (!IsListEmpty(&DGPendingListHead));
@ -141,7 +135,7 @@ VOID SendDatagramComplete(
TI_DbgPrint(MAX_TRACE, ("Calling 0x%X.\n", Complete)); TI_DbgPrint(MAX_TRACE, ("Calling 0x%X.\n", Complete));
/* Call completion routine for send request */ /* Call completion routine for send request */
(*Complete)(CompleteContext, NdisStatus, BytesSent); (*Complete)(Context, NdisStatus, BytesSent);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
} }
@ -168,8 +162,6 @@ VOID DGSend(
TI_DbgPrint(MAX_TRACE, ("Called.\n")); TI_DbgPrint(MAX_TRACE, ("Called.\n"));
ASSERT(SendRequest->Build);
/* Get the information we need from the address file /* Get the information we need from the address file
now so we minimize the time we hold the spin lock */ now so we minimize the time we hold the spin lock */
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
@ -182,71 +174,73 @@ VOID DGSend(
/* Loop until there are no more send requests in the /* Loop until there are no more send requests in the
transmit queue or until we run out of resources */ transmit queue or until we run out of resources */
for (;;) for (;;)
{ {
Status = (*SendRequest->Build)(SendRequest, ADE->Address, LocalPort, &IPPacket); TI_DbgPrint(MIN_TRACE, ("Looping on DGSend !!!! WHEE!\n"));
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
/* An error occurred, enqueue the send request again and return */ /* An error occurred, enqueue the send request again and return */
InsertHeadList(&AddrFile->TransmitQueue, &SendRequest->ListEntry); InsertHeadList(&AddrFile->TransmitQueue, &SendRequest->ListEntry);
DereferenceObject(ADE); DereferenceObject(ADE);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql); KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
TI_DbgPrint(MIN_TRACE, ("Leaving (insufficient resources).\n")); TI_DbgPrint(MIN_TRACE, ("Leaving (insufficient resources).\n"));
return; return;
} }
/* Get a route to the destination address */ /* Get a route to the destination address */
if (RouteGetRouteToDestination(SendRequest->RemoteAddress, ADE->NTE, &RCN) == IP_SUCCESS) if (RouteGetRouteToDestination(&SendRequest->RemoteAddress, ADE->NTE, &RCN) == IP_SUCCESS)
{ {
/* Set completion routine and send the packet */ /* Set completion routine and send the packet */
IPPacket = &SendRequest->Packet;
PC(IPPacket->NdisPacket)->Complete = SendDatagramComplete; PC(IPPacket->NdisPacket)->Complete = SendDatagramComplete;
PC(IPPacket->NdisPacket)->Context = SendRequest; PC(IPPacket->NdisPacket)->Context = SendRequest;
if (IPSendDatagram(IPPacket, RCN) != STATUS_SUCCESS) if (IPSendDatagram(IPPacket, RCN) != STATUS_SUCCESS)
{ {
SendDatagramComplete(SendRequest, TI_DbgPrint(MIN_TRACE, ("!! Datagram sent !! (completing)\n"));
IPPacket->NdisPacket, SendDatagramComplete(SendRequest,
NDIS_STATUS_REQUEST_ABORTED); IPPacket->NdisPacket,
} NDIS_STATUS_REQUEST_ABORTED);
}
/* We're done with the RCN */ /* We're done with the RCN */
DereferenceObject(RCN); DereferenceObject(RCN);
} }
else else
{ {
/* No route to destination */ /* No route to destination */
/* FIXME: Which error code should we use here? */ /* FIXME: Which error code should we use here? */
TI_DbgPrint(MIN_TRACE, ("No route to destination address (0x%X).\n", TI_DbgPrint(MIN_TRACE,
SendRequest->RemoteAddress->Address.IPv4Address)); ("No route to destination address (0x%X).\n",
SendDatagramComplete(SendRequest, SendRequest->RemoteAddress.Address.IPv4Address));
IPPacket->NdisPacket, SendDatagramComplete(SendRequest,
NDIS_STATUS_REQUEST_ABORTED); IPPacket->NdisPacket,
} NDIS_STATUS_REQUEST_ABORTED);
}
(*IPPacket->Free)(IPPacket);
/* Check transmit queue for more to send */ /* Check transmit queue for more to send */
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
if (!IsListEmpty(&AddrFile->TransmitQueue)) if (!IsListEmpty(&AddrFile->TransmitQueue))
{ {
/* Transmit queue is not empty, process one more request */ /* Transmit queue is not empty, process one more request */
CurrentEntry = RemoveHeadList(&AddrFile->TransmitQueue); CurrentEntry = RemoveHeadList(&AddrFile->TransmitQueue);
SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry); SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql); KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
} TI_DbgPrint(MIN_TRACE, ("List is not empty\n"));
}
else else
{ {
/* Transmit queue is empty */ /* Transmit queue is empty */
AF_CLR_PENDING(AddrFile, AFF_SEND); AF_CLR_PENDING(AddrFile, AFF_SEND);
DereferenceObject(ADE); DereferenceObject(ADE);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql); KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
TI_DbgPrint(MAX_TRACE, ("Leaving (empty queue).\n")); TI_DbgPrint(MAX_TRACE, ("Leaving (empty queue).\n"));
return; return;
} }
} }
} }
@ -346,7 +340,7 @@ VOID DGDeliverData(
{ {
DereferenceObject(Current->RemoteAddress); DereferenceObject(Current->RemoteAddress);
} }
ExFreePool(Current); exFreePool(Current);
} }
} }
else if (AddrFile->RegisteredReceiveDatagramHandler) else if (AddrFile->RegisteredReceiveDatagramHandler)
@ -431,8 +425,7 @@ VOID DGCancelSendRequest(
{ {
/* Complete the request and free its resources */ /* Complete the request and free its resources */
(*Current->Complete)(Current->Context, STATUS_CANCELLED, 0); (*Current->Complete)(Current->Context, STATUS_CANCELLED, 0);
DereferenceObject(Current->RemoteAddress); exFreePool(Current);
ExFreePool(Current);
} }
else else
{ {
@ -489,7 +482,7 @@ VOID DGCancelReceiveRequest(
{ {
DereferenceObject(Current->RemoteAddress); DereferenceObject(Current->RemoteAddress);
} }
ExFreePool(Current); exFreePool(Current);
} }
else else
{ {
@ -528,83 +521,80 @@ NTSTATUS DGTransmit(
KeReleaseSpinLock(&AddressFile->Lock, OldIrql); KeReleaseSpinLock(&AddressFile->Lock, OldIrql);
/* Send the datagram */ /* Send the datagram */
DGSend(AddressFile, SendRequest); DGSend(AddressFile, SendRequest);
TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n")); TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n"));
} }
return STATUS_PENDING; return STATUS_PENDING;
} }
NTSTATUS DGSendDatagram( NTSTATUS DGSendDatagram( PTDI_REQUEST Request,
PTDI_REQUEST Request, PTDI_CONNECTION_INFORMATION ConnInfo,
PTDI_CONNECTION_INFORMATION ConnInfo, PIP_PACKET Packet ) {
PNDIS_BUFFER Buffer,
ULONG DataSize,
DATAGRAM_BUILD_ROUTINE Build)
/* /*
* FUNCTION: Sends a datagram to a remote address * FUNCTION: Sends a datagram to a remote address
* ARGUMENTS: * ARGUMENTS:
* Request = Pointer to TDI request * Request = Pointer to TDI request
* ConnInfo = Pointer to connection information * ConnInfo = Pointer to connection information
* Buffer = Pointer to NDIS buffer with data * Packet = Pointer to NDIS buffer with data
* DataSize = Size in bytes of data to be sent
* Build = Pointer to datagram build routine
* RETURNS: * RETURNS:
* Status of operation * Status of operation
*/ */
{ PADDRESS_FILE AddrFile;
PADDRESS_FILE AddrFile; KIRQL OldIrql;
KIRQL OldIrql; NTSTATUS Status;
NTSTATUS Status; PDATAGRAM_SEND_REQUEST SendRequest;
PDATAGRAM_SEND_REQUEST SendRequest;
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
AddrFile = Request->Handle.AddressHandle;
AddrFile = Request->Handle.AddressHandle;
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
if (AF_IS_VALID(AddrFile)) {
if (AF_IS_VALID(AddrFile)) /* Initialize a send request */
{ SendRequest = exAllocatePool( NonPagedPool,
/* Initialize a send request */ sizeof( DATAGRAM_SEND_REQUEST ) );
Status = BuildDatagramSendRequest(&SendRequest,
NULL, if( SendRequest ) {
0, KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
Buffer, return STATUS_INSUFFICIENT_RESOURCES;
DataSize, }
Request->RequestNotifyObject,
Request->RequestContext, SendRequest->Complete = Request->RequestNotifyObject;
Build, SendRequest->Context = Request->RequestContext;
0); NdisQueryPacketLength( Packet->NdisPacket,
if (NT_SUCCESS(Status)) &SendRequest->BufferSize );
{ SendRequest->Packet = *Packet;
Status = AddrGetAddress(ConnInfo->RemoteAddress,
&SendRequest->RemoteAddress, if (NT_SUCCESS(Status)) {
&SendRequest->RemotePort, Status = AddrGetAddress(ConnInfo->RemoteAddress,
&AddrFile->AddrCache); &SendRequest->RemoteAddress,
if (NT_SUCCESS(Status)) &SendRequest->RemotePort,
{ &AddrFile->AddrCache);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql); if (NT_SUCCESS(Status))
return DGTransmit(AddrFile, SendRequest); {
} KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
else return DGTransmit(AddrFile, SendRequest);
{ }
ExFreePool(SendRequest); else
} {
} exFreePool(SendRequest);
else }
{ }
Status = STATUS_INSUFFICIENT_RESOURCES; else
} {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
} }
else else
{ {
Status = STATUS_ADDRESS_CLOSED; Status = STATUS_ADDRESS_CLOSED;
} }
KeReleaseSpinLock(&AddrFile->Lock, OldIrql); KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
TI_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X)\n", Status)); TI_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X)\n", Status));
return Status; return Status;
} }
@ -645,7 +635,7 @@ NTSTATUS DGReceiveDatagram(
if (AF_IS_VALID(AddrFile)) if (AF_IS_VALID(AddrFile))
{ {
ReceiveRequest = ExAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST)); ReceiveRequest = exAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST));
if (ReceiveRequest) if (ReceiveRequest)
{ {
/* Initialize a receive request */ /* Initialize a receive request */
@ -660,7 +650,7 @@ NTSTATUS DGReceiveDatagram(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
KeReleaseSpinLock(&AddrFile->Lock, OldIrql); KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
ExFreePool(ReceiveRequest); exFreePool(ReceiveRequest);
return Status; return Status;
} }
} }

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <rawip.h> #include <rawip.h>
#include <routines.h> #include <routines.h>
@ -21,8 +22,7 @@ BOOLEAN RawIPInitialized = FALSE;
NTSTATUS BuildRawIPPacket( NTSTATUS BuildRawIPPacket(
PVOID Context, PVOID Context,
PIP_ADDRESS LocalAddress, PIP_ADDRESS LocalAddress,
USHORT LocalPort, USHORT LocalPort )
PIP_PACKET *IPPacket)
/* /*
* FUNCTION: Builds an UDP packet * FUNCTION: Builds an UDP packet
* ARGUMENTS: * ARGUMENTS:
@ -35,43 +35,26 @@ NTSTATUS BuildRawIPPacket(
*/ */
{ {
PVOID Header; PVOID Header;
PIP_PACKET Packet;
NDIS_STATUS NdisStatus; NDIS_STATUS NdisStatus;
PNDIS_BUFFER HeaderBuffer; PNDIS_BUFFER HeaderBuffer;
PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context; PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context;
PIP_PACKET Packet = &SendRequest->Packet;
TI_DbgPrint(MAX_TRACE, ("TCPIP.SYS: NDIS data buffer is at (0x%X).\n", SendRequest->Buffer));
TI_DbgPrint(MAX_TRACE, ("NDIS data buffer Next is at (0x%X).\n", SendRequest->Buffer->Next));
TI_DbgPrint(MAX_TRACE, ("NDIS data buffer Size is (0x%X).\n", SendRequest->Buffer->Size));
TI_DbgPrint(MAX_TRACE, ("NDIS data buffer MappedSystemVa is (0x%X).\n", SendRequest->Buffer->MappedSystemVa));
TI_DbgPrint(MAX_TRACE, ("NDIS data buffer StartVa is (0x%X).\n", SendRequest->Buffer->StartVa));
TI_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteCount is (0x%X).\n", SendRequest->Buffer->ByteCount));
TI_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteOffset is (0x%X).\n", SendRequest->Buffer->ByteOffset));
/* Prepare packet */ /* Prepare packet */
/* FIXME: Assumes IPv4 */ /* FIXME: Assumes IPv4 */
Packet = IPCreatePacket(IP_ADDRESS_V4);
if (!Packet) if (!Packet)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
IPInitializePacket(Packet,IP_ADDRESS_V4);
Packet->Flags = IP_PACKET_FLAG_RAW; /* Don't touch IP header */ Packet->Flags = IP_PACKET_FLAG_RAW; /* Don't touch IP header */
Packet->TotalSize = SendRequest->BufferSize; Packet->TotalSize = SendRequest->BufferSize;
/* Allocate NDIS packet */
NdisAllocatePacket(&NdisStatus, &Packet->NdisPacket, GlobalPacketPool);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS packet. NdisStatus = (0x%X)\n", NdisStatus))
(*Packet->Free)(Packet);
return STATUS_INSUFFICIENT_RESOURCES;
}
if (MaxLLHeaderSize != 0) { if (MaxLLHeaderSize != 0) {
Header = ExAllocatePool(NonPagedPool, MaxLLHeaderSize); Header = ExAllocatePool(NonPagedPool, MaxLLHeaderSize);
if (!Header) { if (!Header) {
TI_DbgPrint(MIN_TRACE, ("Cannot allocate memory for packet headers.\n")); TI_DbgPrint(MIN_TRACE, ("Cannot allocate memory for packet headers.\n"));
NdisFreePacket(Packet->NdisPacket); FreeNdisPacket(Packet->NdisPacket);
(*Packet->Free)(Packet);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
@ -87,21 +70,15 @@ NTSTATUS BuildRawIPPacket(
if (NdisStatus != NDIS_STATUS_SUCCESS) { if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS buffer for packet headers. NdisStatus = (0x%X)\n", NdisStatus)); TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS buffer for packet headers. NdisStatus = (0x%X)\n", NdisStatus));
ExFreePool(Header); ExFreePool(Header);
NdisFreePacket(Packet->NdisPacket); FreeNdisPacket(Packet->NdisPacket);
(*Packet->Free)(Packet);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
/* Chain header at front of packet */ /* Chain header at front of packet */
NdisChainBufferAtFront(Packet->NdisPacket, HeaderBuffer); NdisChainBufferAtFront(Packet->NdisPacket, HeaderBuffer);
} }
/* Chain data after link level header if it exists */
NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer);
DISPLAY_IP_PACKET(Packet); DISPLAY_IP_PACKET(Packet);
*IPPacket = Packet;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -122,8 +99,30 @@ NTSTATUS RawIPSendDatagram(
* Status of operation * Status of operation
*/ */
{ {
return DGSendDatagram(Request, ConnInfo, NDIS_STATUS Status;
Buffer, DataSize, BuildRawIPPacket); PCHAR BufferData;
UINT BufferLen;
PADDRESS_FILE AddrFile =
(PADDRESS_FILE)Request->Handle.AddressHandle;
PDATAGRAM_SEND_REQUEST SendRequest;
SendRequest = ExAllocatePool( NonPagedPool, sizeof(*SendRequest) );
NdisQueryBuffer( Buffer, &BufferData, &BufferLen );
Status = AllocatePacketWithBuffer( &SendRequest->Packet.NdisPacket,
BufferData,
BufferLen );
if( Status != NDIS_STATUS_SUCCESS ) {
BuildRawIPPacket( SendRequest,
(PIP_ADDRESS)&AddrFile->ADE->Address->Address.
IPv4Address,
AddrFile->Port );
Status = DGSendDatagram(Request, ConnInfo, &SendRequest->Packet);
NdisFreeBuffer( Buffer );
}
return Status;
} }

View file

@ -0,0 +1,323 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: transport/tcp/event.c
* PURPOSE: Transmission Control Protocol -- Events from oskittcp
* PROGRAMMERS: Art Yerkes
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <limits.h>
#include <tcpip.h>
#include <tcp.h>
#include <pool.h>
#include <route.h>
#include <router.h>
#include <address.h>
#include <neighbor.h>
#include <datagram.h>
#include <checksum.h>
#include <routines.h>
#include <oskittcp.h>
extern ULONG TCP_IPIdentification;
void TCPRecvNotify( PCONNECTION_ENDPOINT Connection, UINT Flags ) {
int error = 0;
NTSTATUS Status = 0;
CHAR DataBuffer[1024];
UINT BytesRead = 0, BytesTaken = 0;
PTDI_IND_RECEIVE ReceiveHandler;
PTDI_IND_DISCONNECT DisconnectHandler;
PVOID HandlerContext;
SOCKADDR Addr;
TI_DbgPrint(MID_TRACE,("XX> Called\n"));
do {
error = OskitTCPRecv( Connection->SocketContext,
&Addr,
DataBuffer,
1024,
&BytesRead,
Flags | OSK_MSG_DONTWAIT | OSK_MSG_PEEK );
switch( error ) {
case 0:
ReceiveHandler = Connection->AddressFile->ReceiveHandler;
HandlerContext = Connection->AddressFile->ReceiveHandlerContext;
TI_DbgPrint(MID_TRACE,("Received %d bytes\n", BytesRead));
if( Connection->AddressFile->RegisteredReceiveHandler )
Status = ReceiveHandler( HandlerContext,
NULL,
TDI_RECEIVE_NORMAL,
BytesRead,
BytesRead,
&BytesTaken,
DataBuffer,
NULL );
else
Status = STATUS_UNSUCCESSFUL;
if( Status == STATUS_SUCCESS ) {
OskitTCPRecv( Connection->SocketContext,
&Addr,
DataBuffer,
BytesTaken,
&BytesRead,
Flags | OSK_MSG_DONTWAIT );
}
break;
case OSK_ESHUTDOWN:
case OSK_ECONNRESET:
DisconnectHandler = Connection->AddressFile->DisconnectHandler;
HandlerContext = Connection->AddressFile->DisconnectHandlerContext;
if( Connection->AddressFile->RegisteredDisconnectHandler )
Status = DisconnectHandler( HandlerContext,
NULL,
0,
NULL,
0,
NULL,
(error == OSK_ESHUTDOWN) ?
TDI_DISCONNECT_RELEASE :
TDI_DISCONNECT_ABORT );
else
Status = STATUS_UNSUCCESSFUL;
break;
default:
assert( 0 );
break;
}
} while( error == 0 && BytesRead > 0 && BytesTaken > 0 );
TI_DbgPrint(MID_TRACE,("XX> Leaving\n"));
}
void TCPCloseNotify( PCONNECTION_ENDPOINT Connection ) {
TCPRecvNotify( Connection, 0 );
}
char *FlagNames[] = { "SEL_CONNECT",
"SEL_FIN",
"SEL_ACCEPT",
"SEL_OOB",
"SEL_READ",
"SEL_WRITE",
0 };
int FlagValues[] = { SEL_CONNECT,
SEL_FIN,
SEL_ACCEPT,
SEL_OOB,
SEL_READ,
SEL_WRITE,
0 };
void TCPSocketState( void *ClientData,
void *WhichSocket,
void *WhichConnection,
OSK_UINT Flags,
OSK_UINT SocketState ) {
int i;
PCONNECTION_ENDPOINT Connection =
(PCONNECTION_ENDPOINT)WhichConnection;
TI_DbgPrint(MID_TRACE,("TCPSocketState: (socket %x) %x %x\n",
WhichSocket, Flags, SocketState));
for( i = 0; FlagValues[i]; i++ ) {
if( Flags & FlagValues[i] )
TI_DbgPrint(MID_TRACE,("Flag %s\n", FlagNames[i]));
}
if( Flags & SEL_CONNECT )
/* TCPConnectNotify( Connection ); */ ;
if( Flags & SEL_FIN )
TCPCloseNotify( Connection );
if( Flags & SEL_ACCEPT )
/* TCPAcceptNotify( Connection ); */ ;
if( Flags & SEL_OOB )
TCPRecvNotify( Connection, MSG_OOB );
if( Flags & SEL_WRITE )
/* TCPSendNotify( Connection ); */ ;
if( Flags & SEL_READ )
TCPRecvNotify( Connection, 0 );
}
void TCPPacketSendComplete( PVOID Context,
NDIS_STATUS NdisStatus,
DWORD BytesSent ) {
TI_DbgPrint(MID_TRACE,("called\n"));
PDATAGRAM_SEND_REQUEST Send = (PDATAGRAM_SEND_REQUEST)Context;
if( Send->Packet.NdisPacket )
FreeNdisPacket( Send->Packet.NdisPacket );
exFreePool( Send );
}
NTSTATUS AddHeaderIPv4(
PDATAGRAM_SEND_REQUEST SendRequest,
PIP_ADDRESS LocalAddress,
USHORT LocalPort,
PIP_ADDRESS RemoteAddress,
USHORT RemotePort) {
/*
* FUNCTION: Adds an IPv4 and TCP header to an IP packet
* ARGUMENTS:
* SendRequest = Pointer to send request
* Connection = Pointer to connection endpoint
* LocalAddress = Pointer to our local address
* LocalPort = The port we send this segment from
* IPPacket = Pointer to IP packet
* RETURNS:
* Status of operation
*/
PIPv4_HEADER IPHeader;
PIP_PACKET IPPacket;
PVOID Header;
NDIS_STATUS NdisStatus;
PNDIS_BUFFER HeaderBuffer;
PCHAR BufferContent;
ULONG BufferSize;
ULONG PayloadBufferSize;
IPPacket = &SendRequest->Packet;
BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER);
Header = exAllocatePool(NonPagedPool, BufferSize);
if (!Header)
return STATUS_INSUFFICIENT_RESOURCES;
TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", BufferSize, Header));
NdisQueryPacketLength( IPPacket->NdisPacket, &PayloadBufferSize );
/* Allocate NDIS buffer for maximum Link level, IP and TCP header */
NdisAllocateBuffer(&NdisStatus,
&HeaderBuffer,
GlobalBufferPool,
Header,
BufferSize);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
exFreePool(Header);
TI_DbgPrint(MAX_TRACE, ("Error from NDIS: %08x\n", NdisStatus));
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Chain header at front of NDIS packet */
NdisChainBufferAtFront(IPPacket->NdisPacket, HeaderBuffer);
IPPacket->HeaderSize = 20;
IPPacket->ContigSize = BufferSize;
IPPacket->TotalSize = IPPacket->HeaderSize + PayloadBufferSize;
IPPacket->Header = (PVOID)((ULONG_PTR)Header + MaxLLHeaderSize);
IPPacket->Flags = 0;
/* Build IPv4 header */
IPHeader = (PIPv4_HEADER)IPPacket->Header;
/* Version = 4, Length = 5 DWORDs */
IPHeader->VerIHL = 0x45;
/* Normal Type-of-Service */
IPHeader->Tos = 0;
/* Length of header and data */
IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize);
/* Identification */
IPHeader->Id = WH2N((USHORT)InterlockedIncrement(&TCP_IPIdentification));
/* One fragment at offset 0 */
IPHeader->FlagsFragOfs = WH2N((USHORT)IPv4_DF_MASK);
/* Time-to-Live is 128 */
IPHeader->Ttl = 128;
/* Transmission Control Protocol */
IPHeader->Protocol = IPPROTO_TCP;
/* Checksum is 0 (for later calculation of this) */
IPHeader->Checksum = 0;
/* Source address */
IPHeader->SrcAddr = LocalAddress->Address.IPv4Address;
/* Destination address. FIXME: IPv4 only */
IPHeader->DstAddr = RemoteAddress->Address.IPv4Address;
return STATUS_SUCCESS;
}
int TCPPacketSend(void *ClientData,
void *WhichSocket,
void *WhichConnection,
OSK_PCHAR data,
OSK_UINT len ) {
PADDRESS_FILE AddrFile;
PNDIS_BUFFER NdisPacket;
NDIS_STATUS NdisStatus;
KIRQL OldIrql;
PDATAGRAM_SEND_REQUEST SendRequest;
PNEIGHBOR_CACHE_ENTRY NCE = 0;
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)WhichConnection;
IP_ADDRESS RemoteAddress, LocalAddress;
USHORT RemotePort, LocalPort;
PULONG AckNumber = (PULONG)data;
TI_DbgPrint(MID_TRACE,("TCP OUTPUT:\n"));
OskitDumpBuffer( data, len );
SendRequest =
(PDATAGRAM_SEND_REQUEST)
exAllocatePool( NonPagedPool, sizeof( DATAGRAM_SEND_REQUEST ) );
/* if( !SendRequest || !Connection ) return OSK_EINVAL; */
RemoteAddress.Type = LocalAddress.Type = IP_ADDRESS_V4;
OskitTCPGetAddress( WhichSocket,
&LocalAddress.Address.IPv4Address,
&LocalPort,
&RemoteAddress.Address.IPv4Address,
&RemotePort );
NCE = RouterGetRoute( &RemoteAddress, NULL );
if( !NCE ) return OSK_EADDRNOTAVAIL;
GetInterfaceIPv4Address(NCE->Interface,
ADE_UNICAST,
&LocalAddress.Address.IPv4Address );
if( Connection )
KeAcquireSpinLock( &Connection->Lock, &OldIrql );
NdisStatus =
AllocatePacketWithBuffer( &SendRequest->PacketToSend, data, len );
if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MAX_TRACE, ("Error from NDIS: %08x\n", NdisStatus));
goto end;
}
SendRequest->Packet.NdisPacket = SendRequest->PacketToSend;
SendRequest->Complete = TCPPacketSendComplete;
SendRequest->Context = Connection;
SendRequest->RemoteAddress = RemoteAddress;
SendRequest->RemotePort = RemotePort;
NdisQueryPacketLength( SendRequest->Packet.NdisPacket,
&SendRequest->BufferSize );
AddHeaderIPv4( SendRequest,
&LocalAddress,
LocalPort,
&RemoteAddress,
RemotePort );
if( Connection )
DGTransmit( Connection->AddressFile, SendRequest );
else
DbgPrint("Transmit called without connection.\n");
end:
if( Connection )
KeReleaseSpinLock( &Connection->Lock, OldIrql );
if( !NT_SUCCESS(NdisStatus) ) return OSK_EINVAL;
else return 0;
}

View file

@ -0,0 +1,183 @@
/*
* Copyright (c) 1997-1998 University of Utah and the Flux Group.
* All rights reserved.
*
* This file is part of the Flux OSKit. The OSKit is free software, also known
* as "open source;" you can redistribute it and/or modify it under the terms
* of the GNU General Public License (GPL), version 2, as published by the Free
* Software Foundation (FSF). To explore alternate licensing terms, contact
* the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
*
* The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
* received a copy of the GPL along with the OSKit; see the file COPYING. If
* not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
*/
#include <roscfg.h>
#include <limits.h>
#include <tcpip.h>
#include <tcp.h>
#include <pool.h>
#include <route.h>
#include <address.h>
#include <datagram.h>
#include <checksum.h>
#include <routines.h>
#include <neighbor.h>
#include <oskittcp.h>
#if 0
#include <sys/param.h>
#include <sys/kernel.h>
#include <oskit/c/assert.h>
#include <net/if.h>
#endif
#include <oskittcp.h>
int if_index = 0;
struct ifaddr **ifnet_addrs;
int ifqmaxlen = OSK_IFQ_MAXLEN;
struct ifnet *ifnet;
/*
* Network interface utility routines.
*
* Routines with ifa_ifwith* names take sockaddr *'s as
* parameters.
*/
void
ifinit()
{
}
void
if_attach(ifp)
struct ifnet *ifp;
{
KeBugCheck( 0xface );
}
struct ifnet *
ifunit(char *name)
{
return 0;
}
int ifa_iffind(addr, ifaddr, type)
struct sockaddr *addr;
struct ifaddr *ifaddr;
int type;
{
PNEIGHBOR_CACHE_ENTRY NCE;
IP_ADDRESS Destination;
NTSTATUS Status;
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
TI_DbgPrint(MID_TRACE,("called for type %d\n", type));
if( !addr || !ifaddr ) {
TI_DbgPrint(MID_TRACE,("no addr or no ifaddr (%x %x)\n",
addr, ifaddr));
return OSK_EINVAL;
}
Destination.Type = IP_ADDRESS_V4;
Destination.Address.IPv4Address = addr_in->sin_addr.s_addr;
NCE = RouterGetRoute(&Destination, NULL);
if( !NCE || !NCE->Interface ) {
TI_DbgPrint(MID_TRACE,("no neighbor cache or no interface (%x %x)\n",
NCE, NCE->Interface));
return OSK_EADDRNOTAVAIL;
}
/* XXX - Point-to-point interfaces not supported yet */
memset(&ifaddr->ifa_dstaddr, 0, sizeof( struct sockaddr ) );
addr_in->sin_family = PF_INET;
addr_in = (struct sockaddr_in *)&ifaddr->ifa_addr;
Status = GetInterfaceIPv4Address( NCE->Interface,
type,
&addr_in->sin_addr.s_addr );
if( !NT_SUCCESS(Status) )
addr_in->sin_addr.s_addr = 0;
ifaddr->ifa_flags = 0; /* XXX what goes here? */
ifaddr->ifa_refcnt = 0; /* Anachronistic */
ifaddr->ifa_metric = 1; /* We can get it like in ninfo.c, if we want */
ifaddr->ifa_mtu = NCE->Interface->MTU;
TI_DbgPrint(MID_TRACE,("status in iffind: %x\n", Status));
return NT_SUCCESS(Status) ? 0 : OSK_EADDRNOTAVAIL;
}
/*
* Find an interface on a specific network. If many, choice
* is most specific found.
*/
int ifa_ifwithnet(addr, ifaddr)
struct sockaddr *addr;
struct ifaddr *ifaddr;
{
return ifa_iffind(addr, ifaddr, ADE_UNICAST);
}
/*
* Locate the point to point interface with a given destination address.
*/
/*ARGSUSED*/
struct ifaddr *
ifa_ifwithdstaddr(addr, ifaddr)
register struct sockaddr *addr;
register struct ifaddr *ifaddr;
{
return ifa_iffind(addr, ifaddr, ADE_POINTOPOINT);
}
/*
* Locate an interface based on a complete address.
*/
/*ARGSUSED*/
int ifa_ifwithaddr(addr, ifaddr)
struct sockaddr *addr;
struct ifaddr *ifaddr;
{
int error = ifa_ifwithnet( addr, ifaddr );
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
struct sockaddr_in *faddr_in = (struct sockaddr_in *)ifaddr->ifa_addr;
if( error != 0 ) return error;
else return
(faddr_in->sin_addr.s_addr == addr_in->sin_addr.s_addr) ?
0 : OSK_EADDRNOTAVAIL;
}
/*
* 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
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,702 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: transport/tcp/tcp_input.c
* PURPOSE: Transmission Control Protocol
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 15-01-2003 Imported from linux kernel 2.4.20
*/
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Implementation of the Transmission Control Protocol(TCP).
*
* Version: $Id: tcp_timer.c,v 1.1 2003/01/15 21:57:31 chorns Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Mark Evans, <evansmp@uhura.aston.ac.uk>
* Corey Minyard <wf-rch!minyard@relay.EU.net>
* Florian La Roche, <flla@stud.uni-sb.de>
* Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
* Linus Torvalds, <torvalds@cs.helsinki.fi>
* Alan Cox, <gw4pts@gw4pts.ampr.org>
* Matthew Dillon, <dillon@apollo.west.oic.com>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Jorge Cwik, <jorge@laser.satlink.net>
*/
#if 0
#include <net/tcp.h>
#else
#include "linux.h"
#include "tcpcore.h"
#endif
int sysctl_tcp_syn_retries = TCP_SYN_RETRIES;
int sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES;
//int sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
//int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
int sysctl_tcp_retries1 = TCP_RETR1;
int sysctl_tcp_retries2 = TCP_RETR2;
int sysctl_tcp_orphan_retries;
static void tcp_write_timer(unsigned long);
static void tcp_delack_timer(unsigned long);
static void tcp_keepalive_timer (unsigned long data);
//const char timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
/*
* Using different timers for retransmit, delayed acks and probes
* We may wish use just one timer maintaining a list of expire jiffies
* to optimize.
*/
void tcp_init_xmit_timers(struct sock *sk)
{
#if 0
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
init_timer(&tp->retransmit_timer);
tp->retransmit_timer.function=&tcp_write_timer;
tp->retransmit_timer.data = (unsigned long) sk;
tp->pending = 0;
init_timer(&tp->delack_timer);
tp->delack_timer.function=&tcp_delack_timer;
tp->delack_timer.data = (unsigned long) sk;
tp->ack.pending = 0;
init_timer(&sk->timer);
sk->timer.function=&tcp_keepalive_timer;
sk->timer.data = (unsigned long) sk;
#endif
}
void tcp_clear_xmit_timers(struct sock *sk)
{
#if 0
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
tp->pending = 0;
if (timer_pending(&tp->retransmit_timer) &&
del_timer(&tp->retransmit_timer))
__sock_put(sk);
tp->ack.pending = 0;
tp->ack.blocked = 0;
if (timer_pending(&tp->delack_timer) &&
del_timer(&tp->delack_timer))
__sock_put(sk);
if(timer_pending(&sk->timer) && del_timer(&sk->timer))
__sock_put(sk);
#endif
}
static void tcp_write_err(struct sock *sk)
{
#if 0
sk->err = sk->err_soft ? : ETIMEDOUT;
sk->error_report(sk);
tcp_done(sk);
NET_INC_STATS_BH(TCPAbortOnTimeout);
#endif
}
/* Do not allow orphaned sockets to eat all our resources.
* This is direct violation of TCP specs, but it is required
* to prevent DoS attacks. It is called when a retransmission timeout
* or zero probe timeout occurs on orphaned socket.
*
* Criterium is still not confirmed experimentally and may change.
* We kill the socket, if:
* 1. If number of orphaned sockets exceeds an administratively configured
* limit.
* 2. If we have strong memory pressure.
*/
static int tcp_out_of_resources(struct sock *sk, int do_reset)
{
#if 0
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
int orphans = atomic_read(&tcp_orphan_count);
/* If peer does not open window for long time, or did not transmit
* anything for long time, penalize it. */
if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
orphans <<= 1;
/* If some dubious ICMP arrived, penalize even more. */
if (sk->err_soft)
orphans <<= 1;
if (orphans >= sysctl_tcp_max_orphans ||
(sk->wmem_queued > SOCK_MIN_SNDBUF &&
atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
if (net_ratelimit())
printk(KERN_INFO "Out of socket memory\n");
/* Catch exceptional cases, when connection requires reset.
* 1. Last segment was sent recently. */
if ((s32)(tcp_time_stamp - tp->lsndtime) <= TCP_TIMEWAIT_LEN ||
/* 2. Window is closed. */
(!tp->snd_wnd && !tp->packets_out))
do_reset = 1;
if (do_reset)
tcp_send_active_reset(sk, GFP_ATOMIC);
tcp_done(sk);
NET_INC_STATS_BH(TCPAbortOnMemory);
return 1;
}
return 0;
#else
return 0;
#endif
}
/* Calculate maximal number or retries on an orphaned socket. */
static int tcp_orphan_retries(struct sock *sk, int alive)
{
#if 0
int retries = sysctl_tcp_orphan_retries; /* May be zero. */
/* We know from an ICMP that something is wrong. */
if (sk->err_soft && !alive)
retries = 0;
/* However, if socket sent something recently, select some safe
* number of retries. 8 corresponds to >100 seconds with minimal
* RTO of 200msec. */
if (retries == 0 && alive)
retries = 8;
return retries;
#else
return 0;
#endif
}
/* A write timeout has occurred. Process the after effects. */
static int tcp_write_timeout(struct sock *sk)
{
#if 0
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
int retry_until;
if ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
if (tp->retransmits)
dst_negative_advice(&sk->dst_cache);
retry_until = tp->syn_retries ? : sysctl_tcp_syn_retries;
} else {
if (tp->retransmits >= sysctl_tcp_retries1) {
/* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black
hole detection. :-(
It is place to make it. It is not made. I do not want
to make it. It is disguisting. It does not work in any
case. Let me to cite the same draft, which requires for
us to implement this:
"The one security concern raised by this memo is that ICMP black holes
are often caused by over-zealous security administrators who block
all ICMP messages. It is vitally important that those who design and
deploy security systems understand the impact of strict filtering on
upper-layer protocols. The safest web site in the world is worthless
if most TCP implementations cannot transfer data from it. It would
be far nicer to have all of the black holes fixed rather than fixing
all of the TCP implementations."
Golden words :-).
*/
dst_negative_advice(&sk->dst_cache);
}
retry_until = sysctl_tcp_retries2;
if (sk->dead) {
int alive = (tp->rto < TCP_RTO_MAX);
retry_until = tcp_orphan_retries(sk, alive);
if (tcp_out_of_resources(sk, alive || tp->retransmits < retry_until))
return 1;
}
}
if (tp->retransmits >= retry_until) {
/* Has it gone just too far? */
tcp_write_err(sk);
return 1;
}
return 0;
#else
return 0;
#endif
}
static void tcp_delack_timer(unsigned long data)
{
#if 0
struct sock *sk = (struct sock*)data;
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
bh_lock_sock(sk);
if (sk->lock.users) {
/* Try again later. */
tp->ack.blocked = 1;
NET_INC_STATS_BH(DelayedACKLocked);
if (!mod_timer(&tp->delack_timer, jiffies + TCP_DELACK_MIN))
sock_hold(sk);
goto out_unlock;
}
tcp_mem_reclaim(sk);
if (sk->state == TCP_CLOSE || !(tp->ack.pending&TCP_ACK_TIMER))
goto out;
if ((long)(tp->ack.timeout - jiffies) > 0) {
if (!mod_timer(&tp->delack_timer, tp->ack.timeout))
sock_hold(sk);
goto out;
}
tp->ack.pending &= ~TCP_ACK_TIMER;
if (skb_queue_len(&tp->ucopy.prequeue)) {
struct sk_buff *skb;
net_statistics[smp_processor_id()*2].TCPSchedulerFailed += skb_queue_len(&tp->ucopy.prequeue);
while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
sk->backlog_rcv(sk, skb);
tp->ucopy.memory = 0;
}
if (tcp_ack_scheduled(tp)) {
if (!tp->ack.pingpong) {
/* Delayed ACK missed: inflate ATO. */
tp->ack.ato = min(tp->ack.ato << 1, tp->rto);
} else {
/* Delayed ACK missed: leave pingpong mode and
* deflate ATO.
*/
tp->ack.pingpong = 0;
tp->ack.ato = TCP_ATO_MIN;
}
tcp_send_ack(sk);
NET_INC_STATS_BH(DelayedACKs);
}
TCP_CHECK_TIMER(sk);
out:
if (tcp_memory_pressure)
tcp_mem_reclaim(sk);
out_unlock:
bh_unlock_sock(sk);
sock_put(sk);
#endif
}
static void tcp_probe_timer(struct sock *sk)
{
#if 0
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
int max_probes;
if (tp->packets_out || !tp->send_head) {
tp->probes_out = 0;
return;
}
/* *WARNING* RFC 1122 forbids this
*
* It doesn't AFAIK, because we kill the retransmit timer -AK
*
* FIXME: We ought not to do it, Solaris 2.5 actually has fixing
* this behaviour in Solaris down as a bug fix. [AC]
*
* Let me to explain. probes_out is zeroed by incoming ACKs
* even if they advertise zero window. Hence, connection is killed only
* if we received no ACKs for normal connection timeout. It is not killed
* only because window stays zero for some time, window may be zero
* until armageddon and even later. We are in full accordance
* with RFCs, only probe timer combines both retransmission timeout
* and probe timeout in one bottle. --ANK
*/
max_probes = sysctl_tcp_retries2;
if (sk->dead) {
int alive = ((tp->rto<<tp->backoff) < TCP_RTO_MAX);
max_probes = tcp_orphan_retries(sk, alive);
if (tcp_out_of_resources(sk, alive || tp->probes_out <= max_probes))
return;
}
if (tp->probes_out > max_probes) {
tcp_write_err(sk);
} else {
/* Only send another probe if we didn't close things up. */
tcp_send_probe0(sk);
}
#endif
}
/*
* The TCP retransmit timer.
*/
static void tcp_retransmit_timer(struct sock *sk)
{
#if 0
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
if (tp->packets_out == 0)
goto out;
BUG_TRAP(!skb_queue_empty(&sk->write_queue));
if (tp->snd_wnd == 0 && !sk->dead &&
!((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV))) {
/* Receiver dastardly shrinks window. Our retransmits
* become zero probes, but we should not timeout this
* connection. If the socket is an orphan, time it out,
* we cannot allow such beasts to hang infinitely.
*/
#ifdef TCP_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
NIPQUAD(sk->daddr), htons(sk->dport), sk->num,
tp->snd_una, tp->snd_nxt);
#endif
if (tcp_time_stamp - tp->rcv_tstamp > TCP_RTO_MAX) {
tcp_write_err(sk);
goto out;
}
tcp_enter_loss(sk, 0);
tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
__sk_dst_reset(sk);
goto out_reset_timer;
}
if (tcp_write_timeout(sk))
goto out;
if (tp->retransmits == 0) {
if (tp->ca_state == TCP_CA_Disorder || tp->ca_state == TCP_CA_Recovery) {
if (tp->sack_ok) {
if (tp->ca_state == TCP_CA_Recovery)
NET_INC_STATS_BH(TCPSackRecoveryFail);
else
NET_INC_STATS_BH(TCPSackFailures);
} else {
if (tp->ca_state == TCP_CA_Recovery)
NET_INC_STATS_BH(TCPRenoRecoveryFail);
else
NET_INC_STATS_BH(TCPRenoFailures);
}
} else if (tp->ca_state == TCP_CA_Loss) {
NET_INC_STATS_BH(TCPLossFailures);
} else {
NET_INC_STATS_BH(TCPTimeouts);
}
}
tcp_enter_loss(sk, 0);
if (tcp_retransmit_skb(sk, skb_peek(&sk->write_queue)) > 0) {
/* Retransmission failed because of local congestion,
* do not backoff.
*/
if (!tp->retransmits)
tp->retransmits=1;
tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS,
min(tp->rto, TCP_RESOURCE_PROBE_INTERVAL));
goto out;
}
/* Increase the timeout each time we retransmit. Note that
* we do not increase the rtt estimate. rto is initialized
* from rtt, but increases here. Jacobson (SIGCOMM 88) suggests
* that doubling rto each time is the least we can get away with.
* In KA9Q, Karn uses this for the first few times, and then
* goes to quadratic. netBSD doubles, but only goes up to *64,
* and clamps at 1 to 64 sec afterwards. Note that 120 sec is
* defined in the protocol as the maximum possible RTT. I guess
* we'll have to use something other than TCP to talk to the
* University of Mars.
*
* PAWS allows us longer timeouts and large windows, so once
* implemented ftp to mars will work nicely. We will have to fix
* the 120 second clamps though!
*/
tp->backoff++;
tp->retransmits++;
out_reset_timer:
tp->rto = min(tp->rto << 1, TCP_RTO_MAX);
tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
if (tp->retransmits > sysctl_tcp_retries1)
__sk_dst_reset(sk);
out:;
#endif
}
static void tcp_write_timer(unsigned long data)
{
#if 0
struct sock *sk = (struct sock*)data;
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
int event;
bh_lock_sock(sk);
if (sk->lock.users) {
/* Try again later */
if (!mod_timer(&tp->retransmit_timer, jiffies + (HZ/20)))
sock_hold(sk);
goto out_unlock;
}
if (sk->state == TCP_CLOSE || !tp->pending)
goto out;
if ((long)(tp->timeout - jiffies) > 0) {
if (!mod_timer(&tp->retransmit_timer, tp->timeout))
sock_hold(sk);
goto out;
}
event = tp->pending;
tp->pending = 0;
switch (event) {
case TCP_TIME_RETRANS:
tcp_retransmit_timer(sk);
break;
case TCP_TIME_PROBE0:
tcp_probe_timer(sk);
break;
}
TCP_CHECK_TIMER(sk);
out:
tcp_mem_reclaim(sk);
out_unlock:
bh_unlock_sock(sk);
sock_put(sk);
#endif
}
/*
* Timer for listening sockets
*/
static void tcp_synack_timer(struct sock *sk)
{
#if 0
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
struct tcp_listen_opt *lopt = tp->listen_opt;
int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries;
int thresh = max_retries;
unsigned long now = jiffies;
struct open_request **reqp, *req;
int i, budget;
if (lopt == NULL || lopt->qlen == 0)
return;
/* Normally all the openreqs are young and become mature
* (i.e. converted to established socket) for first timeout.
* If synack was not acknowledged for 3 seconds, it means
* one of the following things: synack was lost, ack was lost,
* rtt is high or nobody planned to ack (i.e. synflood).
* When server is a bit loaded, queue is populated with old
* open requests, reducing effective size of queue.
* When server is well loaded, queue size reduces to zero
* after several minutes of work. It is not synflood,
* it is normal operation. The solution is pruning
* too old entries overriding normal timeout, when
* situation becomes dangerous.
*
* Essentially, we reserve half of room for young
* embrions; and abort old ones without pity, if old
* ones are about to clog our table.
*/
if (lopt->qlen>>(lopt->max_qlen_log-1)) {
int young = (lopt->qlen_young<<1);
while (thresh > 2) {
if (lopt->qlen < young)
break;
thresh--;
young <<= 1;
}
}
if (tp->defer_accept)
max_retries = tp->defer_accept;
budget = 2*(TCP_SYNQ_HSIZE/(TCP_TIMEOUT_INIT/TCP_SYNQ_INTERVAL));
i = lopt->clock_hand;
do {
reqp=&lopt->syn_table[i];
while ((req = *reqp) != NULL) {
if ((long)(now - req->expires) >= 0) {
if ((req->retrans < thresh ||
(req->acked && req->retrans < max_retries))
&& !req->class->rtx_syn_ack(sk, req, NULL)) {
unsigned long timeo;
if (req->retrans++ == 0)
lopt->qlen_young--;
timeo = min((TCP_TIMEOUT_INIT << req->retrans),
TCP_RTO_MAX);
req->expires = now + timeo;
reqp = &req->dl_next;
continue;
}
/* Drop this request */
write_lock(&tp->syn_wait_lock);
*reqp = req->dl_next;
write_unlock(&tp->syn_wait_lock);
lopt->qlen--;
if (req->retrans == 0)
lopt->qlen_young--;
tcp_openreq_free(req);
continue;
}
reqp = &req->dl_next;
}
i = (i+1)&(TCP_SYNQ_HSIZE-1);
} while (--budget > 0);
lopt->clock_hand = i;
if (lopt->qlen)
tcp_reset_keepalive_timer(sk, TCP_SYNQ_INTERVAL);
#endif
}
void tcp_delete_keepalive_timer (struct sock *sk)
{
#if 0
if (timer_pending(&sk->timer) && del_timer (&sk->timer))
__sock_put(sk);
#endif
}
void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len)
{
#if 0
if (!mod_timer(&sk->timer, jiffies+len))
sock_hold(sk);
#endif
}
void tcp_set_keepalive(struct sock *sk, int val)
{
#if 0
if ((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN))
return;
if (val && !sk->keepopen)
tcp_reset_keepalive_timer(sk, keepalive_time_when(&sk->tp_pinfo.af_tcp));
else if (!val)
tcp_delete_keepalive_timer(sk);
#endif
}
static void tcp_keepalive_timer (unsigned long data)
{
#if 0
struct sock *sk = (struct sock *) data;
struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
__u32 elapsed;
/* Only process if socket is not in use. */
bh_lock_sock(sk);
if (sk->lock.users) {
/* Try again later. */
tcp_reset_keepalive_timer (sk, HZ/20);
goto out;
}
if (sk->state == TCP_LISTEN) {
tcp_synack_timer(sk);
goto out;
}
if (sk->state == TCP_FIN_WAIT2 && sk->dead) {
if (tp->linger2 >= 0) {
int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN;
if (tmo > 0) {
tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
goto out;
}
}
tcp_send_active_reset(sk, GFP_ATOMIC);
goto death;
}
if (!sk->keepopen || sk->state == TCP_CLOSE)
goto out;
elapsed = keepalive_time_when(tp);
/* It is alive without keepalive 8) */
if (tp->packets_out || tp->send_head)
goto resched;
elapsed = tcp_time_stamp - tp->rcv_tstamp;
if (elapsed >= keepalive_time_when(tp)) {
if ((!tp->keepalive_probes && tp->probes_out >= sysctl_tcp_keepalive_probes) ||
(tp->keepalive_probes && tp->probes_out >= tp->keepalive_probes)) {
tcp_send_active_reset(sk, GFP_ATOMIC);
tcp_write_err(sk);
goto out;
}
if (tcp_write_wakeup(sk) <= 0) {
tp->probes_out++;
elapsed = keepalive_intvl_when(tp);
} else {
/* If keepalive was lost due to local congestion,
* try harder.
*/
elapsed = TCP_RESOURCE_PROBE_INTERVAL;
}
} else {
/* It is tp->rcv_tstamp + keepalive_time_when(tp) */
elapsed = keepalive_time_when(tp) - elapsed;
}
TCP_CHECK_TIMER(sk);
tcp_mem_reclaim(sk);
resched:
tcp_reset_keepalive_timer (sk, elapsed);
goto out;
death:
tcp_done(sk);
out:
bh_unlock_sock(sk);
sock_put(sk);
#endif
}

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
*/ */
#include <roscfg.h>
#include <tcpip.h> #include <tcpip.h>
#include <udp.h> #include <udp.h>
#include <routines.h> #include <routines.h>
@ -91,7 +92,7 @@ NTSTATUS AddUDPHeaderIPv4(
/* Source address */ /* Source address */
IPHeader->SrcAddr = LocalAddress->Address.IPv4Address; IPHeader->SrcAddr = LocalAddress->Address.IPv4Address;
/* Destination address. FIXME: IPv4 only */ /* Destination address. FIXME: IPv4 only */
IPHeader->DstAddr = SendRequest->RemoteAddress->Address.IPv4Address; IPHeader->DstAddr = SendRequest->RemoteAddress.Address.IPv4Address;
/* Build UDP header */ /* Build UDP header */
UDPHeader = (PUDP_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER)); UDPHeader = (PUDP_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER));
@ -110,8 +111,7 @@ NTSTATUS AddUDPHeaderIPv4(
NTSTATUS BuildUDPPacket( NTSTATUS BuildUDPPacket(
PVOID Context, PVOID Context,
PIP_ADDRESS LocalAddress, PIP_ADDRESS LocalAddress,
USHORT LocalPort, USHORT LocalPort)
PIP_PACKET *IPPacket)
/* /*
* FUNCTION: Builds an UDP packet * FUNCTION: Builds an UDP packet
* ARGUMENTS: * ARGUMENTS:
@ -124,16 +124,16 @@ NTSTATUS BuildUDPPacket(
*/ */
{ {
NTSTATUS Status; NTSTATUS Status;
PIP_PACKET Packet;
NDIS_STATUS NdisStatus; NDIS_STATUS NdisStatus;
PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context; PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context;
PIP_PACKET Packet = &SendRequest->Packet;
TI_DbgPrint(MAX_TRACE, ("Called.\n")); TI_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Prepare packet */ /* Prepare packet */
/* FIXME: Assumes IPv4 */ /* FIXME: Assumes IPv4 */
Packet = IPCreatePacket(IP_ADDRESS_V4); IPInitializePacket(IP_ADDRESS_V4, &SendRequest->Packet);
if (!Packet) if (!Packet)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
@ -141,15 +141,7 @@ NTSTATUS BuildUDPPacket(
sizeof(UDP_HEADER) + sizeof(UDP_HEADER) +
SendRequest->BufferSize; SendRequest->BufferSize;
/* Allocate NDIS packet */ switch (SendRequest->RemoteAddress.Type) {
NdisAllocatePacket(&NdisStatus, &Packet->NdisPacket, GlobalPacketPool);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS packet. NdisStatus = (0x%X)\n", NdisStatus));
(*Packet->Free)(Packet);
return STATUS_INSUFFICIENT_RESOURCES;
}
switch (SendRequest->RemoteAddress->Type) {
case IP_ADDRESS_V4: case IP_ADDRESS_V4:
Status = AddUDPHeaderIPv4(SendRequest, LocalAddress, LocalPort, Packet); Status = AddUDPHeaderIPv4(SendRequest, LocalAddress, LocalPort, Packet);
break; break;
@ -162,18 +154,12 @@ NTSTATUS BuildUDPPacket(
} }
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
TI_DbgPrint(MIN_TRACE, ("Cannot add UDP header. Status = (0x%X)\n", Status)); TI_DbgPrint(MIN_TRACE, ("Cannot add UDP header. Status = (0x%X)\n", Status));
NdisFreePacket(Packet->NdisPacket); FreeNdisPacket(Packet->NdisPacket);
(*Packet->Free)(Packet);
return Status; return Status;
} }
/* Chain data after header */
NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer);
DISPLAY_IP_PACKET(Packet); DISPLAY_IP_PACKET(Packet);
*IPPacket = Packet;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -194,11 +180,18 @@ NTSTATUS UDPSendDatagram(
* Status of operation * Status of operation
*/ */
{ {
return DGSendDatagram(Request, PDATAGRAM_SEND_REQUEST SendRequest;
ConnInfo, PADDRESS_FILE AddrFile =
Buffer, (PADDRESS_FILE)Request->Handle.AddressHandle;
DataSize,
BuildUDPPacket); BuildUDPPacket( SendRequest,
(PIP_ADDRESS)&AddrFile->ADE->Address->Address.
IPv4Address,
AddrFile->Port );
return DGSendDatagram(Request,
ConnInfo,
&SendRequest->Packet);
} }

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.13 2004/05/29 21:24:44 hbirr Exp $ # $Id: makefile,v 1.14 2004/06/09 18:11:39 arty Exp $
PATH_TO_TOP = ../.. PATH_TO_TOP = ../..

View file

@ -15,8 +15,8 @@
#ifdef DBG #ifdef DBG
/* See debug.h for debug/trace constants */ /* See debug.h for debug/trace constants */
DWORD DebugTraceLevel = MIN_TRACE; //DWORD DebugTraceLevel = MIN_TRACE;
//DWORD DebugTraceLevel = DEBUG_ULTRA; DWORD DebugTraceLevel = DEBUG_ULTRA;
#endif /* DBG */ #endif /* DBG */
@ -566,27 +566,29 @@ WSPAccept(
Request.lpfnCondition = lpfnCondition; Request.lpfnCondition = lpfnCondition;
Request.dwCallbackData = dwCallbackData; Request.dwCallbackData = dwCallbackData;
Status = NtDeviceIoControlFile( Status = NtDeviceIoControlFile(
(HANDLE)s, (HANDLE)s,
NULL, NULL,
NULL, NULL,
NULL, NULL,
&Iosb, &Iosb,
IOCTL_AFD_ACCEPT, IOCTL_AFD_ACCEPT,
&Request, &Request,
sizeof(FILE_REQUEST_ACCEPT), sizeof(FILE_REQUEST_ACCEPT),
&Reply, &Reply,
sizeof(FILE_REPLY_ACCEPT)); sizeof(FILE_REPLY_ACCEPT));
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
/* FIXME: Wait only for blocking sockets */ /* FIXME: Wait only for blocking sockets */
Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
} }
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
*lpErrno = Reply.Status; *lpErrno = Reply.Status;
return INVALID_SOCKET; return INVALID_SOCKET;
} }
*addrlen = Reply.addrlen; *addrlen = Reply.addrlen;

View file

@ -28,10 +28,20 @@ extern HANDLE GlobalHeap;
extern BOOL Initialized; /* TRUE if WSAStartup() has been successfully called */ extern BOOL Initialized; /* TRUE if WSAStartup() has been successfully called */
extern WSPUPCALLTABLE UpcallTable; extern WSPUPCALLTABLE UpcallTable;
#define WS2_INTERNAL_MAX_ALIAS 16
typedef struct _WINSOCK_GETSERVBYNAME_CACHE {
UINT Size;
SERVENT ServerEntry;
PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS];
CHAR Data[1];
} WINSOCK_GETSERVBYNAME_CACHE, *PWINSOCK_GETSERVBYNAME_CACHE;
typedef struct _WINSOCK_THREAD_BLOCK { typedef struct _WINSOCK_THREAD_BLOCK {
INT LastErrorValue; /* Error value from last function that failed */ INT LastErrorValue; /* Error value from last function that failed */
CHAR Intoa[16]; /* Buffer for inet_ntoa() */ CHAR Intoa[16]; /* Buffer for inet_ntoa() */
PWINSOCK_GETSERVBYNAME_CACHE
Getservbyname; /* Buffer used by getservbyname */
} WINSOCK_THREAD_BLOCK, *PWINSOCK_THREAD_BLOCK; } WINSOCK_THREAD_BLOCK, *PWINSOCK_THREAD_BLOCK;

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.14 2004/05/29 21:24:47 hbirr Exp $ # $Id: makefile,v 1.15 2004/06/09 18:11:39 arty Exp $
PATH_TO_TOP = ../.. PATH_TO_TOP = ../..

View file

@ -17,7 +17,6 @@
/* See debug.h for debug/trace constants */ /* See debug.h for debug/trace constants */
DWORD DebugTraceLevel = MIN_TRACE; DWORD DebugTraceLevel = MIN_TRACE;
//DWORD DebugTraceLevel = DEBUG_ULTRA;
#endif /* DBG */ #endif /* DBG */
@ -37,7 +36,8 @@ INT
EXPORT EXPORT
WSAGetLastError(VOID) WSAGetLastError(VOID)
{ {
PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
if (p) { if (p) {
return p->LastErrorValue; return p->LastErrorValue;
@ -667,6 +667,7 @@ DllMain(HANDLE hInstDll,
} }
p->LastErrorValue = NO_ERROR; p->LastErrorValue = NO_ERROR;
p->Getservbyname = NULL;
NtCurrentTeb()->WinSockData = p; NtCurrentTeb()->WinSockData = p;
break; break;

View file

@ -7,8 +7,13 @@
* REVISIONS: * REVISIONS:
* CSH 01/09-2000 Created * CSH 01/09-2000 Created
*/ */
#include <ctype.h>
#include <ws2_32.h> #include <ws2_32.h>
#ifndef BUFSIZ
#define BUFSIZ 1024
#endif/*BUFSIZ*/
/* Name resolution APIs */ /* Name resolution APIs */
/* /*
@ -420,9 +425,58 @@ getprotobynumber(
return (LPPROTOENT)NULL; return (LPPROTOENT)NULL;
} }
#define SKIPWS(ptr,act) \
{while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
#define SKIPANDMARKSTR(ptr,act) \
{while(*ptr && !isspace(*ptr)) ptr++; \
if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
static BOOL DecodeServEntFromString( IN PCHAR ServiceString,
OUT PCHAR *ServiceName,
OUT PCHAR *PortNumberStr,
OUT PCHAR *ProtocolStr,
IN PCHAR *Aliases,
IN DWORD MaxAlias ) {
UINT NAliases = 0;
WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
SKIPWS(ServiceString, return FALSE);
*ServiceName = ServiceString;
SKIPANDMARKSTR(ServiceString, return FALSE);
SKIPWS(ServiceString, return FALSE);
*PortNumberStr = ServiceString;
SKIPANDMARKSTR(ServiceString, ;);
while( *ServiceString && NAliases < MaxAlias - 1 ) {
SKIPWS(ServiceString, break);
if( *ServiceString ) {
SKIPANDMARKSTR(ServiceString, ;);
if( strlen(ServiceString) ) {
WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
*Aliases++ = ServiceString;
NAliases++;
}
}
}
*Aliases = NULL;
*ProtocolStr = strchr(*PortNumberStr,'/');
if( !*ProtocolStr ) return FALSE;
**ProtocolStr = 0; (*ProtocolStr)++;
WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
*ServiceName, *ProtocolStr, *PortNumberStr,
NAliases));
return TRUE;
}
#define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
/* /*
* @unimplemented * @implemented
*/ */
LPSERVENT LPSERVENT
EXPORT EXPORT
@ -430,9 +484,157 @@ getservbyname(
IN CONST CHAR FAR* name, IN CONST CHAR FAR* name,
IN CONST CHAR FAR* proto) IN CONST CHAR FAR* proto)
{ {
UNIMPLEMENTED BOOL Found = FALSE;
HANDLE ServicesFile;
CHAR ServiceDBData[BUFSIZ] = { 0 };
PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
ProtocolStr = 0, Comment = 0;
PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
UINT i,SizeNeeded = 0,
SystemDirSize = sizeof(ServiceDBData) - 1;
DWORD ReadSize = 0, ValidData = 0;
PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
if( !p ) {
WSASetLastError( WSANOTINITIALISED );
return NULL;
}
return (LPSERVENT)NULL; if( !name ) {
WSASetLastError( WSANO_RECOVERY );
return NULL;
}
if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) {
WSASetLastError( WSANO_RECOVERY );
WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
return NULL; /* Can't get system directory */
}
strncat( SystemDirectory, ServicesFileLocation, SystemDirSize );
ServicesFile = CreateFileA( SystemDirectory,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_SEQUENTIAL_SCAN,
NULL );
if( ServicesFile == INVALID_HANDLE_VALUE ) {
WSASetLastError( WSANO_RECOVERY );
return NULL;
}
/* Scan the services file ...
*
* We will read up to BUFSIZ bytes per pass, until the buffer does not
* contain a full line, then we will try to read more.
*
* We fall from the loop if the buffer does not have a line terminator.
*/
/* Initial Read */
while( !Found &&
ReadFile( ServicesFile, ServiceDBData + ValidData,
sizeof( ServiceDBData ) - ValidData,
&ReadSize, NULL ) ) {
ValidData += ReadSize;
ReadSize = 0;
NextLine = ThisLine = ServiceDBData;
/* Find the beginning of the next line */
while( NextLine < ServiceDBData + ValidData &&
*NextLine != '\r' && *NextLine != '\n' ) NextLine++;
/* Zero and skip, so we can treat what we have as a string */
if( NextLine >= ServiceDBData + ValidData )
break;
*NextLine = 0; NextLine++;
Comment = strchr( ThisLine, '#' );
if( Comment ) *Comment = 0; /* Terminate at comment start */
if( DecodeServEntFromString( ThisLine,
&ServiceName,
&PortNumberStr,
&ProtocolStr,
Aliases,
WS2_INTERNAL_MAX_ALIAS ) &&
!strcmp( ServiceName, name ) &&
(proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) {
WS_DbgPrint(MAX_TRACE,("Found the service entry.\n"));
Found = TRUE;
SizeNeeded = sizeof(WINSOCK_GETSERVBYNAME_CACHE) +
(NextLine - ThisLine);
break;
}
/* Get rid of everything we read so far */
while( NextLine <= ServiceDBData + ValidData &&
isspace( *NextLine ) ) NextLine++;
WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
ServiceDBData + ValidData - NextLine));
memmove( ServiceDBData, NextLine,
ServiceDBData + ValidData - NextLine );
ValidData -= NextLine - ServiceDBData;
WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
}
/* This we'll do no matter what */
CloseHandle( ServicesFile );
if( !Found ) {
WS_DbgPrint(MAX_TRACE,("Not found\n"));
WSASetLastError( WSANO_DATA );
return NULL;
}
if( !p->Getservbyname || p->Getservbyname->Size < SizeNeeded ) {
/* Free previous getservbyname buffer, allocate bigger */
if( p->Getservbyname )
HeapFree(GlobalHeap, 0, p->Getservbyname);
p->Getservbyname = HeapAlloc(GlobalHeap, 0, SizeNeeded);
if( !p->Getservbyname ) {
WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
SizeNeeded));
WSASetLastError( WSATRY_AGAIN );
return NULL;
}
p->Getservbyname->Size = SizeNeeded;
}
/* Copy the data */
memmove( p->Getservbyname->Data,
ThisLine,
NextLine - ThisLine );
ADJ_PTR(ServiceName,ThisLine,p->Getservbyname->Data);
ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyname->Data);
WS_DbgPrint(MAX_TRACE,
("ServiceName: %s, Protocol: %s\n", ServiceName, ProtocolStr));
for( i = 0; Aliases[i]; i++ ) {
ADJ_PTR(Aliases[i],ThisLine,p->Getservbyname->Data);
WS_DbgPrint(MAX_TRACE,("Aliase %d: %s\n", i, Aliases[i]));
}
memcpy(p->Getservbyname,Aliases,sizeof(Aliases));
/* Create the struct proper */
p->Getservbyname->ServerEntry.s_name = ServiceName;
p->Getservbyname->ServerEntry.s_aliases = p->Getservbyname->Aliases;
p->Getservbyname->ServerEntry.s_port = htons(atoi(PortNumberStr));
p->Getservbyname->ServerEntry.s_proto = ProtocolStr;
return &p->Getservbyname->ServerEntry;
} }