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 *,
struct in_addr, u_int, struct in_addr, u_int));
void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
void in_pcbrehash __P((struct inpcb *));
u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));void in_pcbrehash __P((struct inpcb *));
void in_rtchange __P((struct inpcb *, int));
void in_setpeeraddr __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) { \
MCLFREE((m)->m_ext.ext_buf); \
} \
(nn) = (m)->m_next; \
/* (nn) = (m)->m_next; */ \
FREE((m), mbtypes[(m)->m_type]); \
}
#endif /* OSKIT */

View file

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

View file

@ -181,11 +181,11 @@ struct socket {
((sb)->sb_flags |= SB_LOCK), 0)
/* release lock on sockbuf sb */
#define sbunlock(sb) { \
#define sbunlock(so, sb) { \
(sb)->sb_flags &= ~SB_LOCK; \
if ((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 socwakeup(so) sowakeup((so), &(so)->so_snd)
#ifdef KERNEL
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 TrackTag(x)
#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/*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_ESRCH 3 /* No such process */
#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_E2BIG 7 /* Argument list too long */
#define OSK_ENOEXEC 8 /* Exec format error */

View file

@ -39,46 +39,34 @@ struct connect_args {
#include <oskittypes.h>
#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 *WhichSocket,
void *WhichConnection,
OSK_PCHAR Data,
OSK_UINT Len );
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 );
OSK_UINT SelFlags,
OSK_UINT SocketState );
typedef int (*OSKITTCP_SEND_PACKET)
( void *ClientData,
void *WhichSocket,
void *WhichConnection,
OSK_PCHAR Data,
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 {
void *ClientData;
OSKITTCP_SOCKET_DATA_AVAILABLE SocketDataAvailable;
OSKITTCP_SOCKET_CONNECT_INDICATION SocketConnectIndication;
OSKITTCP_SOCKET_CLOSE_INDICATION SocketCloseIndication;
OSKITTCP_SOCKET_PENDING_CONNECT_INDICATION SocketPendingConnectIndication;
OSKITTCP_SOCKET_RESET_INDICATION SocketResetIndication;
OSKITTCP_SOCKET_STATE SocketState;
OSKITTCP_SEND_PACKET PacketSend;
OSKITTCP_NEED_BIND Bind;
} OSKITTCP_EVENT_HANDLERS, *POSKITTCP_EVENT_HANDLERS;
extern OSKITTCP_EVENT_HANDLERS OtcpEvent;
@ -92,7 +80,12 @@ extern void RegisterOskitTCPEventHandlers
( POSKITTCP_EVENT_HANDLERS EventHandlers );
extern void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
OSK_UINT IpHeaderLen );
extern int OskitTCPReceive( void *socket,
void *Addr,
OSK_PCHAR Data,
OSK_UINT Len,
OSK_UINT *OutLen,
OSK_UINT Flags );
#undef errno
#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 OSK_MSG_OOB 0x01
#define OSK_MSG_PEEK 0x02
#define OSK_MSG_DONTWAIT 0x80
#endif/*OSKITTCP_H*/

View file

@ -64,38 +64,6 @@ struct multi_kludge {
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
#define SUBNETSARELOCAL 1
#endif

View file

@ -54,9 +54,6 @@ void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
if( OtcpEvent.PacketSend )
OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n",
OtcpEvent.PacketSend));
if( OtcpEvent.Bind )
OS_DbgPrint(OSK_MID_TRACE,("Bind handler registered: %x\n",
OtcpEvent.Bind));
}
void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len ) {
@ -85,42 +82,49 @@ int OskitTCPSocket( void *context,
*aso = so;
}
return error;
#if 0
register struct protosw *prp;
register struct socket *so;
register int error;
if (proto) {
prp = pffindproto(domain, proto, type);
} else {
prp = pffindtype(domain, type);
}
if (prp == 0 || prp->pr_usrreq == 0) {
return (EPROTONOSUPPORT);
}
if (prp->pr_type != type) {
return (EPROTOTYPE);
}
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
getsockaddr(namp, uaddr, len)
/* [<][>][^][v][top][bottom][index][help] */
@ -209,10 +213,13 @@ done:
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 );
struct mbuf mb;
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 );
}
void OskitTCPReceive( VOID *socket, PVOID AddrOut,
OSK_PCHAR Data, OSK_UINT Len, OSK_UINT *OutLen ) {
}
void *OskitTCPAccept( void *socket,
void *AddrOut,
OSK_UINT AddrLen,
OSK_UINT *OutAddrLen ) {
struct mbuf nam;
int error;
VOID *OskitTCPAccept( VOID *socket, PVOID AddrOut ) {
nam.m_data = AddrOut;
nam.m_len = AddrLen;
return soaccept( socket, &nam );
}
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 */
}
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,
USHORT LocalPort,
ULONG RemoteAddress,
@ -268,7 +279,7 @@ void OskitTCPSetAddress( VOID *socket,
RemoteAddress, RemotePort);
}
void OskitTCPGetAddress( VOID *socket,
void OskitTCPGetAddress( void *socket,
PULONG LocalAddress,
PUSHORT LocalPort,
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);
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 );
}
OS_DbgPrint(OSK_MID_TRACE,("Error from upper layer: %d\n", 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.
*/

View file

@ -139,59 +139,6 @@ int ticks;
volatile struct timeval 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.
* Run periodic events from timeout queue.

View file

@ -12,18 +12,18 @@ typedef struct _SLEEPING_THREAD {
} SLEEPING_THREAD, *PSLEEPING_THREAD;
LIST_ENTRY SleepingThreadsList;
KSPIN_LOCK SleepingThreadsLock;
FAST_MUTEX SleepingThreadsLock;
/* clock_init */
int ncallout = 256;
struct callout *callout;
void init_freebsd_sched() {
KeInitializeSpinLock( &SleepingThreadsLock );
ExInitializeFastMutex( &SleepingThreadsLock );
InitializeListHead( &SleepingThreadsList );
}
void tsleep( void *token, int priority, char *wmesg, int tmio ) {
int tsleep( void *token, int priority, char *wmesg, int tmio ) {
KIRQL OldIrql;
KEVENT Event;
PLIST_ENTRY Entry;
@ -37,43 +37,65 @@ void tsleep( void *token, int priority, char *wmesg, int tmio ) {
if( SleepingThread ) {
KeInitializeEvent( &SleepingThread->Event, NotificationEvent, FALSE );
SleepingThread->SleepToken = token;
ExInterlockedInsertTailList( &SleepingThreadsList,
&SleepingThread->Entry,
&SleepingThreadsLock );
}
OS_DbgPrint(OSK_MID_TRACE,("Waiting on %x\n", token));
KeWaitForSingleObject( &SleepingThread->Event,
WrSuspended,
KernelMode,
TRUE,
NULL );
ExAcquireFastMutex( &SleepingThreadsLock );
InsertTailList( &SleepingThreadsList, &SleepingThread->Entry );
ExReleaseFastMutex( &SleepingThreadsLock );
OS_DbgPrint(OSK_MID_TRACE,("Waiting on %x\n", token));
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));
return 0;
}
void wakeup( void *token ) {
void wakeup( struct socket *so, struct selinfo *si, void *token ) {
KIRQL OldIrql;
KEVENT Event;
PLIST_ENTRY Entry;
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;
while( Entry != &SleepingThreadsList ) {
SleepingThread = CONTAINING_RECORD(Entry, SLEEPING_THREAD, Entry);
OS_DbgPrint(OSK_MID_TRACE,("Sleeper @ %x\n", SleepingThread));
if( SleepingThread->SleepToken == token ) {
RemoveEntryList(Entry);
KeReleaseSpinLock( &SleepingThreadsLock, OldIrql );
OS_DbgPrint(OSK_MID_TRACE,("Setting event to wake %x\n", token));
KeSetEvent( &SleepingThread->Event, IO_NO_INCREMENT, FALSE );
ExFreePool( SleepingThread );
return;
KeSetEvent( &SleepingThread->Event, IO_NETWORK_INCREMENT, FALSE );
}
Entry = Entry->Flink;
}
KeReleaseSpinLock( &SleepingThreadsLock, OldIrql );
ExReleaseFastMutex( &SleepingThreadsLock );
OS_DbgPrint(OSK_MID_TRACE,("Wakeup done %x\n", token));
}
@ -142,32 +164,6 @@ static __inline int name(void) \
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) {
OS_DbgPrint(OSK_MID_TRACE,("Called SPLZ\n"));
}
@ -184,26 +180,3 @@ void restore_cpl(unsigned 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 */
/*
* 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) { \
if ((ti)->ti_seq == (tp)->rcv_nxt && \
(tp)->seg_next == (struct tcpiphdr *)(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) { \
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)); \
if (!(ti)->ti_flags & TH_FIN && \
!(ti)->ti_flags & TH_RST) { \
(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; \
tcpstat.tcps_rcvpack++;\
tcpstat.tcps_rcvbyte += (ti)->ti_len;\
sbappend(so, &(so)->so_rcv, (m)); \
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; \
} \
}
#endif
#ifndef TUBA_INCLUDE
int
@ -231,13 +203,30 @@ present:
ti = (struct tcpiphdr *)ti->ti_next;
if (so->so_state & SS_CANTRCVMORE)
m_freem(m);
else
sbappend(so, &so->so_rcv, m);
else {
sbappend(so, &so->so_rcv, (m));
}
} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
sorwakeup(so);
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
* protocol specification dated September, 1981 very closely.
@ -249,6 +238,8 @@ tcp_input(m, iphlen)
{
register struct tcpiphdr *ti;
register struct inpcb *inp;
struct sockaddr_in addr = { 0 };
struct mbuf mhdr = { 0 }, mpayload = { 0 };
caddr_t optp = NULL;
int optlen = 0;
int len, tlen, off;
@ -342,6 +333,8 @@ tcp_input(m, iphlen)
m->m_data += 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.
*/
@ -380,6 +373,22 @@ findpcb:
tiwin = ti->ti_win;
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)) {
#ifdef TCPDEBUG
if (so->so_options & SO_DEBUG) {
@ -589,14 +598,17 @@ findpcb:
*/
++tcpstat.tcps_preddat;
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_rcvbyte += ti->ti_len;
/*
* 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);
#ifdef TCP_ACK_HACK
/*
@ -879,6 +891,7 @@ findpcb:
so));
tp->t_state = TCPS_ESTABLISHED;
tp->t_timer[TCPT_KEEP] = tcp_keepidle;
socwakeup(so);
}
} else {
/*
@ -1173,8 +1186,9 @@ trimthenstep6:
* error and we send an RST and drop the connection.
*/
if (tiflags & TH_SYN) {
tp = tcp_drop(tp, ECONNRESET);
goto dropwithreset;
OS_DbgPrint(OSK_MID_TRACE,("SYN In window\n"));
tp = tcp_drop(tp, ECONNRESET);
goto dropwithreset;
}
/*
@ -1415,7 +1429,7 @@ process_ACK:
ourfinisacked = 0;
}
if (so->so_snd.sb_flags & SB_NOTIFY)
sowwakeup(so);
sowwakeup(so);
tp->snd_una = ti->ti_ack;
if (SEQ_LT(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.
*/
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 */
tiflags &= ~TH_URG; /* XXX */
goto dodata; /* XXX */
@ -1579,6 +1596,9 @@ dodata: /* XXX */
* case PRU_RCVD). If a FIN has already been received on this
* connection then we just ignore the text.
*/
OS_DbgPrint(OSK_MID_TRACE,("TIFlags: %x\n", tiflags));
if ((ti->ti_len || (tiflags&TH_FIN)) &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) {
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);
} else {
m_freem(m);
/*m_freem(m);*/
tiflags &= ~TH_FIN;
}

View file

@ -85,8 +85,7 @@ tcp_output(tp)
struct rmxp_tao *taop;
struct rmxp_tao tao_noncached;
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
OS_DbgPrint(OSK_MID_TRACE,("Start\n"));
/*
* Determine length of data that should be transmitted,
@ -102,7 +101,9 @@ tcp_output(tp)
* slow start to get ack "clock" running again.
*/
tp->snd_cwnd = tp->t_maxseg;
again:
OS_DbgPrint(OSK_MID_TRACE,("Again...\n"));
sendalot = 0;
off = tp->snd_nxt - tp->snd_una;
win = min(tp->snd_wnd, tp->snd_cwnd);
@ -237,9 +238,6 @@ again:
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
* known to peer (as advertised window less
@ -262,9 +260,6 @@ again:
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.
*/
@ -284,9 +279,6 @@ again:
((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
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
* using ``persist'' packets is used to insure receipt of window
@ -321,9 +313,6 @@ again:
/*return (0);*/
send:
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : tp->rcv_nxt %x\n", tp->rcv_nxt));
/*
* Before ESTABLISHED, force sending of initial 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
* wants to use timestamps (TF_REQ_TSTMP is set) or both our side
@ -379,9 +365,6 @@ send:
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),
* options are allowed (!TF_NOOPT) and it's not a RST.
@ -457,9 +440,6 @@ send:
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
* bump the packet length beyond the t_maxopd length.
@ -480,8 +460,6 @@ send:
panic("tcphdr too big");
/*#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
@ -607,21 +585,12 @@ send:
if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg)
win = 0;
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
if (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))
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));
if (SEQ_GT(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.
*/
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
if (len + optlen) {
ti->ti_src.s_addr = tp->t_inpcb->inp_laddr.s_addr;
ti->ti_dst.s_addr = tp->t_inpcb->inp_faddr.s_addr;
@ -651,14 +617,8 @@ send:
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));
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
/*
* In transmit state, time the transmission and arrange for
* the retransmit. In persist state, just set snd_max.
@ -711,9 +671,6 @@ send:
if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
tp->snd_max = tp->snd_nxt + len;
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
#ifdef TCPDEBUG
/*
* Trace.
@ -756,9 +713,7 @@ send:
}
#endif
OS_DbgPrint(OSK_MID_TRACE,
("Before IP_OUTPUT : AckNumber %x\n", ti->ti_ack));
OS_DbgPrint(OSK_MID_TRACE,("Calling ip_output\n"));
error = ip_output(so, m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
so->so_options & SO_DONTROUTE, 0);
}
@ -799,6 +754,8 @@ out:
tp->rcv_adv = tp->rcv_nxt + win;
tp->last_ack_sent = tp->rcv_nxt;
tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
OS_DbgPrint(OSK_MID_TRACE,("sendalot: %d (flags %x)\n",
sendalot, tp->t_flags));
if (sendalot)
goto again;
return (0);

View file

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

View file

@ -393,7 +393,7 @@ restart:
(atomic || space < so->so_snd.sb_lowat || space < clen)) {
if (so->so_state & SS_NBIO)
snderr(EWOULDBLOCK);
sbunlock(&so->so_snd);
sbunlock(so, &so->so_snd);
error = sbwait(&so->so_snd);
splx(s);
if (error)
@ -480,12 +480,14 @@ nopages:
} while (resid);
release:
sbunlock(&so->so_snd);
sbunlock(so, &so->so_snd);
out:
#ifndef __REACTOS__
if (top)
m_freem(top);
m_freem(top);
if (control)
m_freem(control);
m_freem(control);
#endif /* The caller owns top and control */
return (error);
}
@ -506,305 +508,87 @@ out:
* only for the count in uio_resid.
*/
int
soreceive(so, paddr, uio, mp0, controlp, flagsp)
soreceive(so, paddr, uio, _mp0, controlp, flagsp)
register struct socket *so;
struct mbuf **paddr;
struct uio *uio;
struct mbuf **mp0;
struct mbuf **_mp0;
struct mbuf **controlp;
int *flagsp;
{
register struct mbuf *m, **mp;
register int flags, len, error, s, offset;
struct protosw *pr = so->so_proto;
struct mbuf *nextrecord;
int moff, type = 0;
int orig_resid = uio->uio_resid;
struct mbuf dummy = { 0 };
struct mbuf *mb = &dummy, *mn, *mp0 = *_mp0;
int total = 0, copyamt;
mp = mp0;
if (paddr)
*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);
dummy.m_nextpkt = so->so_rcv.sb_mb;
uio->uio_resid = 0;
restart:
error = sblock(&so->so_rcv, SBLOCKWAIT(flags));
if (error)
return (error);
s = splnet();
if( mp0->m_len == 0 )
return 0;
m = so->so_rcv.sb_mb;
/*
* If we have less data than requested, block awaiting more
* (subject to any timeout) if:
* 1. the current count is less than the low water mark, or
* 2. MSG_WAITALL is set, and it is possible to do the entire
* receive operation at once if we block (resid <= hiwat).
* 3. MSG_DONTWAIT is not set
* If MSG_WAITALL is set but resid is larger than the receive buffer,
* we have to do the receive in sections, and thus risk returning
* a short count if a timeout or signal occurs after we start.
*/
if (m == 0 || (((flags & MSG_DONTWAIT) == 0 &&
so->so_rcv.sb_cc < uio->uio_resid) &&
(so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) {
#ifdef DIAGNOSTIC
if (m == 0 && so->so_rcv.sb_cc)
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( so->so_rcv.sb_cc == 0 && so->so_rcv.sb_sel.si_flags & SEL_FIN )
return OSK_ESHUTDOWN;
while( mb->m_nextpkt && total < mp0->m_len ) {
OS_DbgPrint(OSK_MID_TRACE, ("Looking at packet %x\n", mb));
if( *flagsp & MSG_OOB ) {
OS_DbgPrint(OSK_MID_TRACE, ("Searching for oob: %x\n", mb));
while( mb->m_nextpkt && mb->m_nextpkt->m_type != MT_OOBDATA )
mb = mb->m_nextpkt;
} else {
while( mb->m_nextpkt && mb->m_nextpkt->m_type != MT_DATA ) {
OS_DbgPrint
(OSK_MID_TRACE,
("Searching for data: %x (%x@%x)\n",
mb->m_nextpkt->m_type,
mb->m_nextpkt->m_len,
mb->m_nextpkt->m_data));
mb = mb->m_nextpkt;
}
}
if (m && pr->pr_flags & PR_ATOMIC) {
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( !mb->m_nextpkt ) break;
if (flagsp)
*flagsp |= flags;
release:
sbunlock(&so->so_rcv);
splx(s);
return (error);
mn = mb->m_nextpkt;
if( !mn->m_next ) mn->m_next = mn->m_data;
copyamt = min(mn->m_len, mp0->m_len);
OS_DbgPrint(OSK_MID_TRACE,
("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
@ -836,7 +620,7 @@ sorflush(so)
(void) sblock(sb, M_WAITOK);
s = splimp();
socantrcvmore(so);
sbunlock(sb);
sbunlock(so, sb);
asb = *sb;
bzero((caddr_t)sb, sizeof (*sb));
splx(s);
@ -958,7 +742,7 @@ sosetopt(so, level, optname, m0)
}
bad:
if (m)
/*(void) m_free(m);*/
(void) m_free(m);
return (error);
}
@ -1039,8 +823,8 @@ sogetopt(so, level, optname, mp)
}
default:
(void)m_free(m);
return (ENOPROTOOPT);
(void)m_free(m);
return (ENOPROTOOPT);
}
*mp = m;
return (0);
@ -1057,5 +841,5 @@ sohasoutofband(so)
gsignal(-so->so_pgid, SIGURG);
else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
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_ISCONNECTED;
if (head && soqremque(so, 0)) {
soqinsque(head, so, 1);
sorwakeup(head);
wakeup((caddr_t)&head->so_timeo);
soqinsque(head, so, 1);
sorwakeup(head);
wakeup(so, NULL, (caddr_t)&head->so_timeo);
} else {
wakeup((caddr_t)&so->so_timeo);
sorwakeup(so);
sowwakeup(so);
wakeup(so, NULL, (caddr_t)&so->so_timeo);
sorwakeup(so);
socwakeup(so);
}
if( OtcpEvent.SocketConnectIndication )
OtcpEvent.SocketConnectIndication
( OtcpEvent.ClientData,
so,
so->so_connection );
}
void
@ -134,7 +128,7 @@ soisdisconnecting(so)
so->so_state &= ~SS_ISCONNECTING;
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);
sorwakeup(so);
}
@ -146,7 +140,7 @@ soisdisconnected(so)
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
wakeup((caddr_t)&so->so_timeo);
wakeup(so, NULL, (caddr_t)&so->so_timeo);
sowwakeup(so);
sorwakeup(so);
}
@ -194,7 +188,7 @@ sonewconn1(head, connstatus)
}
if (connstatus) {
sorwakeup(head);
wakeup((caddr_t)&head->so_timeo);
wakeup(so, NULL, (caddr_t)&head->so_timeo);
so->so_state |= connstatus;
}
return (so);
@ -327,23 +321,7 @@ sowakeup(so, sb)
{
struct proc *p;
selwakeup(&sb->sb_sel);
#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);
}
wakeup(so, &sb->sb_sel, (caddr_t)&sb->sb_cc);
}
/*
@ -383,7 +361,6 @@ soreserve(so, sndcc, rcvcc)
register struct socket *so;
u_long sndcc, rcvcc;
{
if (sbreserve(&so->so_snd, sndcc) == 0)
goto bad;
if (sbreserve(&so->so_rcv, rcvcc) == 0)
@ -470,28 +447,47 @@ sbappend(so, sb, m)
struct sockbuf *sb;
struct mbuf *m;
{
register struct mbuf *n;
register struct mbuf *n, *new_mbuf;
free( malloc( 2 ) );
if (m == 0)
return;
n = sb->sb_mb;
if (n) {
while (n->m_nextpkt)
n = n->m_nextpkt;
do {
if (n->m_flags & M_EOR) {
sbappendrecord(sb, m); /* XXXXXX!!!! */
return;
}
} while (n->m_next && (n = n->m_next));
OS_DbgPrint(OSK_MID_TRACE,("sbappendrecord: %x\n", n));
while( n && n->m_nextpkt ) n = n->m_nextpkt;
new_mbuf = malloc( sizeof( *m ) + m->m_len );
memset( new_mbuf, 0, sizeof( *m ) );
free( malloc( 2 ) );
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 )
OtcpEvent.SocketDataAvailable
( OtcpEvent.ClientData,
so,
so->so_connection,
m->m_data, m->m_len );
free( malloc( 2 ) );
}
#ifdef SOCKBUF_DEBUG
@ -539,6 +535,7 @@ sbappendrecord(sb, m0)
* Put the first mbuf on the queue.
* Note this permits zero length records.
*/
sballoc(sb, m0);
if (m)
m->m_nextpkt = m0;
@ -615,7 +612,7 @@ sbappendaddr(sb, asa, m0, control)
int space = /*asa->sa_len;*/ sizeof(struct sockaddr);
if (m0 && (m0->m_flags & M_PKTHDR) == 0)
panic("sbappendaddr");
panic("sbappendaddr");
if (m0)
space += m0->m_pkthdr.len;
for (n = control; n; n = n->m_next) {
@ -709,6 +706,8 @@ sbcompress(sb, m, n)
(unsigned)m->m_len);
n->m_len += 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);
continue;
}
@ -771,6 +770,8 @@ sbdrop(sb, len)
m->m_len -= len;
m->m_data += len;
sb->sb_cc -= len;
OS_DbgPrint(OSK_MID_TRACE,("SB->SB_CC = %d\n",
sb->sb_cc));
break;
}
len -= m->m_len;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -48,7 +48,7 @@ typedef struct IPADDR_ENTRY {
typedef struct IPROUTE_ENTRY {
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 Metric2;
ULONG Metric3;
@ -87,13 +87,13 @@ typedef struct IFENTRY {
#define IP_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
#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102
#endif
#ifndef IP_MIB_ROUTETABLE_ENTRY_ID
#define IP_MIB_ROUTETABLE_ENTRY_ID 0x103
#endif
#ifndef MAX_PHYSADDR_SIZE
#define MAX_PHYSADDR_SIZE 8
#endif
@ -137,6 +137,59 @@ TDI_STATUS InfoTdiSetInformationEx(
PVOID Buffer,
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 */
/* 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);
#define FOURCC(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
/* Raw IPv4 style address */
typedef ULONG IPv4_RAW_ADDRESS;
@ -93,7 +94,6 @@ typedef struct _PACKET_CONTEXT {
/* The ProtocolReserved field is structured as a PACKET_CONTEXT */
#define PC(Packet) ((PPACKET_CONTEXT)(&Packet->ProtocolReserved))
/* Address information a.k.a ADE */
typedef struct _ADDRESS_ENTRY {
DEFINE_TAG
@ -105,10 +105,12 @@ typedef struct _ADDRESS_ENTRY {
PIP_ADDRESS Address; /* Pointer to address identifying this entry */
} ADDRESS_ENTRY, *PADDRESS_ENTRY;
/* Values for address type */
#define ADE_UNICAST 0x01
#define ADE_MULTICAST 0x02
#define ADE_ADDRMASK 0x03
/* Values for address type -- also the interface flags */
/* These values are mean to overlap meaningfully with the BSD ones */
#define ADE_UNICAST 0x01
#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 */
typedef struct _NET_TABLE_ENTRY {
@ -162,17 +164,6 @@ typedef struct _IP_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
typedef VOID (*IP_PROTOCOL_HANDLER)(
@ -202,8 +193,6 @@ extern LIST_ENTRY InterfaceListHead;
extern KSPIN_LOCK InterfaceListLock;
extern LIST_ENTRY NetTableListHead;
extern KSPIN_LOCK NetTableListLock;
extern LIST_ENTRY PrefixListHead;
extern KSPIN_LOCK PrefixListLock;
extern UINT MaxLLHeaderSize;
extern UINT MinLLFrameSize;

View file

@ -56,7 +56,6 @@ typedef struct LAN_ADAPTER {
UINT MacOptions; /* MAC options for NIC driver/adapter */
UINT Speed; /* Link speed */
UINT PacketFilter; /* Packet filter for this adapter */
PNDIS_PACKET TDPackets; /* Transfer Data packets */
} LAN_ADAPTER, *PLAN_ADAPTER;
/* 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 */
PIP_ADDRESS NetworkAddress; /* Address 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 */
UINT Metric; /* Cost of this route */
} FIB_ENTRY, *PFIB_ENTRY;
@ -34,7 +33,6 @@ PIP_INTERFACE RouterFindOnLinkInterface(
PFIB_ENTRY RouterAddRoute(
PIP_ADDRESS NetworkAddress,
PIP_ADDRESS Netmask,
PNET_TABLE_ENTRY NTE,
PNEIGHBOR_CACHE_ENTRY Router,
UINT Metric);
@ -58,6 +56,10 @@ NTSTATUS RouterStartup(
NTSTATUS RouterShutdown(
VOID);
UINT CountFIBs();
UINT CopyFIBs( PFIB_ENTRY Target );
#endif /* __ROUTER_H */
/* EOF */

View file

@ -8,25 +8,7 @@
#define __ROUTINES_H
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);
inline NTSTATUS BuildTCPSendRequest(
PTCP_SEND_REQUEST *SendRequest,
DATAGRAM_COMPLETION_ROUTINE Complete,
PVOID Context,
PVOID ProtocolContext);
UINT Random(
VOID);
UINT Random(VOID);
UINT CopyBufferToBufferChain(
PNDIS_BUFFER DstBuffer,
@ -53,8 +35,10 @@ UINT CopyPacketToBufferChain(
UINT SrcOffset,
UINT Length);
VOID FreeNdisPacket(
PNDIS_PACKET Packet);
VOID FreeNdisPacketX(
PNDIS_PACKET Packet,
PCHAR File,
UINT Line);
PVOID AdjustPacket(
PNDIS_PACKET Packet,

View file

@ -35,6 +35,9 @@ typedef struct TCPv4_HEADER {
#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 */
typedef struct TCPv4_PSEUDO_HEADER {
@ -70,10 +73,9 @@ typedef struct TCPv4_PSEUDO_HEADER {
#define SRF_SYN TCP_SYN
#define SRF_FIN TCP_FIN
PTCP_SEGMENT TCPCreateSegment(
PIP_PACKET IPPacket,
ULONG SequenceNumber,
PTCPv4_HEADER TCPHeader,
ULONG SegmentLength);
VOID TCPFreeSegment(
@ -81,25 +83,8 @@ VOID TCPFreeSegment(
VOID TCPAddSegment(
PCONNECTION_ENDPOINT Connection,
PTCP_SEGMENT Segment);
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);
PTCP_SEGMENT Segment,
PULONG Acknowledged);
NTSTATUS TCPConnect(
PTDI_REQUEST Request,
@ -108,10 +93,16 @@ NTSTATUS TCPConnect(
NTSTATUS TCPListen(
PTDI_REQUEST Request,
PTDI_CONNECTION_INFORMATION ConnInfo,
PTDI_CONNECTION_INFORMATION ReturnInfo);
UINT Backlog );
NTSTATUS TCPSendDatagram(
NTSTATUS TCPReceiveData(
PTDI_REQUEST Request,
PNDIS_BUFFER Buffer,
ULONG ReceiveLength,
ULONG ReceiveFlags,
PULONG BytesReceived);
NTSTATUS TCPSendData(
PTDI_REQUEST Request,
PTDI_CONNECTION_INFORMATION ConnInfo,
PNDIS_BUFFER Buffer,

View file

@ -63,6 +63,8 @@
#define MAX(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
@ -110,6 +112,34 @@
#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 */
extern PDEVICE_OBJECT TCPDeviceObject;
@ -123,7 +153,7 @@ extern KSPIN_LOCK AddressFileListLock;
extern NDIS_HANDLE GlobalPacketPool;
extern NDIS_HANDLE GlobalBufferPool;
extern KSPIN_LOCK EntityListLock;
extern TDIEntityID *EntityList;
extern TDIEntityInfo *EntityList;
extern ULONG EntityCount;
extern ULONG EntityMax;
extern UDP_STATISTICS UDPStats;

View file

@ -65,7 +65,7 @@
#else /* DBG */
#define DEFINE_TAG
#define INIT_TAG (Object, Tag)
#define INIT_TAG(Object, Tag)
/*
* VOID ReferenceObject(
@ -127,17 +127,18 @@ typedef NTSTATUS (*DATAGRAM_BUILD_ROUTINE)(
PIP_PACKET *IPPacket);
typedef struct _DATAGRAM_SEND_REQUEST {
LIST_ENTRY ListEntry; /* Entry on list */
PIP_ADDRESS RemoteAddress; /* Pointer to remote IP address */
USHORT RemotePort; /* Remote port number */
PNDIS_BUFFER Buffer; /* Pointer to NDIS buffer to send */
DWORD BufferSize; /* Size of Buffer */
LIST_ENTRY ListEntry;
PNDIS_PACKET PacketToSend;
DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */
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 */
} DATAGRAM_SEND_REQUEST, *PDATAGRAM_SEND_REQUEST;
#if 0
#define InitializeDatagramSendRequest( \
_SendRequest, \
_RemoteAddress, \
@ -157,6 +158,7 @@ typedef struct _DATAGRAM_SEND_REQUEST {
(_SendRequest)->Build = (_Build); \
(_SendRequest)->Flags = (_Flags); \
}
#endif /* These things bug me... They hide the member names. */
/* Transport address file context structure. The FileObject->FsContext2
field holds a pointer to this structure */
@ -254,32 +256,17 @@ typedef struct _AF_SEARCH {
USHORT Protocol; /* Protocol number */
} AF_SEARCH, *PAF_SEARCH;
/*******************************************************
* Connection-oriented communication support structures *
*******************************************************/
typedef struct _TCP_SEND_REQUEST {
typedef struct _TCP_RECEIVE_REQUEST {
LIST_ENTRY ListEntry; /* Entry on list */
PNDIS_BUFFER Buffer; /* Pointer to receive buffer */
ULONG BufferSize; /* Size of Buffer */
DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */
PVOID Context; /* Pointer to context information */
PVOID ProtocolContext; /* Protocol specific context */
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); \
}
} TCP_RECEIVE_REQUEST, *PTCP_RECEIVE_REQUEST;
/* Connection states */
typedef enum {
@ -302,8 +289,10 @@ typedef enum {
typedef struct _TCP_SEGMENT {
LIST_ENTRY ListEntry;
PIP_PACKET IPPacket; /* Pointer to IP packet */
PVOID SegmentData; /* Pointer to segment data */
ULONG SequenceNumber; /* Sequence number of first byte in segment */
ULONG Length; /* Number of bytes in segment */
ULONG BytesDelivered; /* Number of bytes already delivered to the client */
} TCP_SEGMENT, *PTCP_SEGMENT;
@ -316,15 +305,16 @@ typedef struct _CONNECTION_ENDPOINT {
ULONG RefCount; /* Number of references to this object */
PVOID ClientContext; /* Pointer to client context information */
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 */
USHORT LocalPort; /* Local port number (network byte order) */
PIP_ADDRESS RemoteAddress; /* Pointer to remote IP address */
USHORT RemotePort; /* Remote port number (network byte order) */
CONNECTION_STATE State; /* Connection state */
/* Send sequence variables */
ULONG SendUnacknowledged; /* Highest sequence number that is acknowledged */
ULONG SendNext; /* Sequence number of last data block sent */
@ -335,20 +325,23 @@ typedef struct _CONNECTION_ENDPOINT {
ULONG SendISS; /* Initial send sequence number */
/* 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 ReceiveUrgentPointer; /* Sequence number of start of urgent data */
ULONG ReceiveIRS; /* Initial receive sequence number */
ULONG ReceiveDelivered; /* Next sequence number to be delivered to the client */
/* Statistics for computing the retransmission timeout */
ULONG TimestampSend; /* Timestamp when sending a segment */
ULONG TimestampAck; /* Timestamp when receiving acknowledgment */
#endif
/* Requests */
PTDI_REQUEST ListenRequest; /* Queued listen request */
LIST_ENTRY ReceiveRequests; /* Queued receive requests */
/* Queues */
LIST_ENTRY ReceivedSegments;
LIST_ENTRY ReceivedSegments;/* Segments that are received */
} 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 = ../../..
@ -8,9 +8,16 @@ TARGET_TYPE = export_driver
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 = \
tcpip/*.o \
@ -19,32 +26,35 @@ TARGET_CLEAN = \
transport/datagram/*.o \
transport/rawip/*.o \
transport/tcp/*.o \
transport/udp/*.o
transport/udp/*.o
TCPIP_OBJECTS = tcpip/main.o tcpip/address.o tcpip/checksum.o \
tcpip/dispatch.o tcpip/fileobjs.o tcpip/info.o \
tcpip/pool.o tcpip/routines.o
tcpip/dispatch.o tcpip/fileobjs.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
NETWORK_OBJECTS = network/icmp.o network/ip.o network/neighbor.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
RAWIP_OBJECTS = transport/rawip/rawip.o
TCP_OBJECTS = transport/tcp/tcp.o transport/tcp/tcpcore.o \
transport/tcp/tcp_input.o transport/tcp/tcp_ipv4.o \
transport/tcp/tcp_output.o transport/tcp/tcp_timer.o
TCP_OBJECTS = transport/tcp/tcp.o transport/tcp/event.o transport/tcp/if.o
UDP_OBJECTS = transport/udp/udp.o
ARCH_OBJECTS = tcpip/i386/checksum.o
TARGET_OBJECTS = \
$(TCPIP_OBJECTS) \
$(INFO_OBJECTS) \
$(DATALINK_OBJECTS) \
$(NETWORK_OBJECTS) \
$(DATAGRAM_OBJECTS) \
$(RAWIP_OBJECTS) \
$(TCP_OBJECTS) \
$(FREEBSD_OBJECTS) \
$(REACTOS_OBJECTS) \
$(UDP_OBJECTS) \
$(ARCH_OBJECTS)
$(ARCH_OBJECTS) \
include $(PATH_TO_TOP)/rules.mak

View file

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

View file

@ -7,6 +7,7 @@
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <ip.h>
#include <tcp.h>
@ -14,6 +15,7 @@
#include <neighbor.h>
#include <receive.h>
#include <address.h>
#include <prefix.h>
#include <route.h>
#include <icmp.h>
#include <pool.h>
@ -25,8 +27,6 @@ LIST_ENTRY InterfaceListHead;
KSPIN_LOCK InterfaceListLock;
LIST_ENTRY NetTableListHead;
KSPIN_LOCK NetTableListLock;
LIST_ENTRY PrefixListHead;
KSPIN_LOCK PrefixListLock;
UINT MaxLLHeaderSize; /* Largest maximum header size */
UINT MinLLFrameSize; /* Largest minimum frame size */
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(
PVOID Object)
/*
@ -55,7 +66,7 @@ VOID FreeADE(
* 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
*/
{
ExFreePool(Object);
exFreePool(Object);
}
@ -79,7 +90,7 @@ VOID FreeIF(
* Object = Pointer to an interface structure
*/
{
ExFreePool(Object);
exFreePool(Object);
}
@ -114,7 +125,7 @@ PADDRESS_ENTRY CreateADE(
A2S(Address), A2S(NTE->Address)));
/* Allocate space for an ADE and set it up */
ADE = ExAllocatePool(NonPagedPool, sizeof(ADDRESS_ENTRY));
ADE = exAllocatePool(NonPagedPool, sizeof(ADDRESS_ENTRY));
if (!ADE) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NULL;
@ -221,119 +232,35 @@ PIP_PACKET IPCreatePacket(
INIT_TAG(IPPacket, TAG('I','P','K','T'));
IPPacket->Free = FreePacket;
IPPacket->RefCount = 1;
IPPacket->Type = Type;
IPPacket->Free = FreePacket;
IPPacket->RefCount = 1;
IPPacket->Type = Type;
IPPacket->HeaderSize = 20;
return IPPacket;
}
PPREFIX_LIST_ENTRY CreatePLE(
PIP_INTERFACE IF,
PIP_ADDRESS Prefix,
UINT Length)
PIP_PACKET IPInitializePacket(
PIP_PACKET IPPacket,
ULONG Type)
/*
* FUNCTION: Creates a prefix list entry and binds it to an interface
* FUNCTION: Creates an IP packet object
* ARGUMENTS:
* IF = Pointer to interface
* Prefix = Pointer to prefix
* Length = Length of prefix
* Type = Type of IP packet
* 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
* Pointer to the created IP packet. NULL if there was not enough free resources.
*/
{
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);
/* FIXME: Is this needed? */
RtlZeroMemory(IPPacket, sizeof(IP_PACKET));
INIT_TAG(IPPacket, TAG('I','P','K','T'));
IPPacket->Free = DontFreePacket;
IPPacket->RefCount = 1;
IPPacket->Type = Type;
return IPPacket;
}
@ -364,7 +291,7 @@ PNET_TABLE_ENTRY IPCreateNTE(
TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address)));
/* Allocate room for an NTE */
NTE = ExAllocatePool(NonPagedPool, sizeof(NET_TABLE_ENTRY));
NTE = exAllocatePool(NonPagedPool, sizeof(NET_TABLE_ENTRY));
if (!NTE) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NULL;
@ -392,7 +319,7 @@ PNET_TABLE_ENTRY IPCreateNTE(
ADE = CreateADE(IF, NTE->Address, ADE_UNICAST, NTE);
if (!ADE) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
ExFreePool(NTE);
exFreePool(NTE);
return NULL;
}
@ -400,7 +327,7 @@ PNET_TABLE_ENTRY IPCreateNTE(
NTE->PLE = CreatePLE(IF, NTE->Address, PrefixLength);
if (!NTE->PLE) {
DestroyADE(IF, ADE);
ExFreePool(NTE);
exFreePool(NTE);
return NULL;
}
@ -462,7 +389,7 @@ VOID DestroyNTE(
}
#endif
/* And free the NTE */
ExFreePool(NTE);
exFreePool(NTE);
}
@ -792,7 +719,7 @@ PIP_INTERFACE IPCreateInterface(
}
#endif
IF = ExAllocatePool(NonPagedPool, sizeof(IP_INTERFACE));
IF = exAllocatePool(NonPagedPool, sizeof(IP_INTERFACE));
if (!IF) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NULL;
@ -821,6 +748,8 @@ PIP_INTERFACE IPCreateInterface(
KeInitializeSpinLock(&IF->Lock);
InsertTDIInterfaceEntity( IF );
return IF;
}
@ -838,6 +767,8 @@ VOID IPDestroyInterface(
TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF));
RemoveTDIInterfaceEntity( IF );
KeAcquireSpinLock(&NetTableListLock, &OldIrql1);
KeAcquireSpinLock(&IF->Lock, &OldIrql2);
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));
}
#endif
ExFreePool(IF);
exFreePool(IF);
}
@ -891,30 +823,29 @@ BOOLEAN IPRegisterInterface(
KeReleaseSpinLock(&IF->Lock, OldIrql);
return FALSE;
}
#if 1
/* Reference objects for forward information base */
ReferenceObject(Current->Address);
ReferenceObject(Current->PLE->Prefix);
ReferenceObject(Current);
ReferenceObject(NCE);
/* 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"));
DereferenceObject(Current->Address);
DereferenceObject(Current->PLE->Prefix);
DereferenceObject(Current);
DereferenceObject(NCE);
}
#else
RCN = RouteAddRouteToDestination(Current->Address, Current, IF, NCE);
if (!RCN) {
TI_DbgPrint(MIN_TRACE, ("Could not create RCN.\n"));
DereferenceObject(Current->Address);
KeReleaseSpinLock(&IF->Lock, OldIrql);
return FALSE;
}
/* Don't need this any more since the route cache references the NCE */
DereferenceObject(NCE);
#endif
CurrentEntry = CurrentEntry->Flink;
}
@ -1096,9 +1027,7 @@ NTSTATUS IPStartup(
InitializeListHead(&ReassemblyListHead);
KeInitializeSpinLock(&ReassemblyListLock);
/* Initialize the prefix list and protecting lock */
InitializeListHead(&PrefixListHead);
KeInitializeSpinLock(&PrefixListLock);
InitPLE();
/* Initialize our periodic timer and its associated DPC object. When the
timer expires, the IPTimeout deferred procedure call (DPC) is queued */

View file

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

View file

@ -6,9 +6,15 @@
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* NOTES: The route cache is implemented as a binary search
* 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:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <route.h>
#include <router.h>
@ -23,7 +29,7 @@ KSPIN_LOCK RouteCacheLock;
NPAGED_LOOKASIDE_LIST IPRCNList;
#if DBG
#ifdef DBG
VOID PrintTree(
PROUTE_CACHE_NODE Node)
/*
@ -50,6 +56,17 @@ VOID PrintTree(
}
#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(
PVOID Object)
@ -168,6 +185,8 @@ PROUTE_CACHE_NODE ExpandExternalRCN(VOID)
{
PROUTE_CACHE_NODE RCN;
MTMARK();
TI_DbgPrint(DEBUG_RCACHE, ("Called.\n"));
RCN = ExAllocateFromNPagedLookasideList(&IPRCNList);
@ -176,6 +195,8 @@ PROUTE_CACHE_NODE ExpandExternalRCN(VOID)
return NULL;
}
MTMARK();
RCN->Free = FreeRCN;
if (ExternalRCN->Left)
@ -186,6 +207,8 @@ PROUTE_CACHE_NODE ExpandExternalRCN(VOID)
RCN->Left = ExternalRCN;
RCN->Right = ExternalRCN;
MTMARK();
return RCN;
}
@ -364,7 +387,7 @@ VOID RemoveSubtree(
DereferenceObject(Node->NTE);
DereferenceObject(Node->NCE);
#if DBG
#ifdef DBG
if (Node->RefCount != 1)
TI_DbgPrint(MIN_TRACE, ("RCN at (0x%X) has (%d) references (should be 1).\n", Node, Node->RefCount));
#endif

View file

@ -4,12 +4,18 @@
* FILE: network/router.c
* PURPOSE: IP routing subsystem
* 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:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <address.h>
#include <router.h>
#include <prefix.h>
#include <pool.h>
@ -48,7 +54,6 @@ VOID DestroyFIBE(
DereferenceObject(FIBE->NetworkAddress);
DereferenceObject(FIBE->Netmask);
DereferenceObject(FIBE->Router);
DereferenceObject(FIBE->NTE);
#ifdef DBG
FIBE->RefCount--;
@ -79,7 +84,7 @@ VOID DestroyFIBEs(
CurrentEntry = FIBListHead.Flink;
while (CurrentEntry != &FIBListHead) {
NextEntry = CurrentEntry->Flink;
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry);
/* Destroy the FIB entry */
DestroyFIBE(Current);
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(
PIP_ADDRESS Address1,
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, ("Address1 (%s) Address2 (%s).\n",
A2S(Address1), A2S(Address2)));
/*TI_DbgPrint(DEBUG_ROUTER, ("Target (%s) \n", A2S(Address1)));*/
/*TI_DbgPrint(DEBUG_ROUTER, ("Adapter (%s).\n", A2S(Address2)));*/
if (Address1->Type == IP_ADDRESS_V4)
Size = sizeof(IPv4_RAW_ADDRESS);
else
Size = sizeof(IPv6_RAW_ADDRESS);
Addr1 = (PUCHAR)&Address1->Address;
Addr2 = (PUCHAR)&Address2->Address;
Addr1 = (PUCHAR)&Address1->Address.IPv4Address;
Addr2 = (PUCHAR)&Address2->Address.IPv4Address;
/* Find first non-matching byte */
for (i = 0; ; i++) {
if (i == Size)
return 8 * i; /* The two addresses are equal */
if (Addr1[i] != Addr2[i])
break;
}
for (i = 0; i < Size && Addr1[i] == Addr2[i]; i++);
if( i == Size ) return 8 * i;
/* Find first non-matching bit */
Bitmask = 0x80;
for (j = 0; ; j++) {
if ((Addr1[i] & Bitmask) != (Addr2[i] & Bitmask))
break;
for (j = 0; (Addr1[i] & Bitmask) != (Addr2[i] & Bitmask); j++)
Bitmask >>= 1;
}
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));
#if 0
TI_DbgPrint(DEBUG_ROUTER, ("Address (%s) Prefix (%s).\n",
A2S(Address), A2S(Prefix)));
#endif
/* Check that initial integral bytes match */
while (Length > 8) {
@ -207,7 +243,8 @@ PNET_TABLE_ENTRY RouterFindBestNTE(
CurrentEntry = Interface->NTEListHead.Flink;
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);
if (BestNTE) {
@ -271,7 +308,6 @@ PIP_INTERFACE RouterFindOnLinkInterface(
PFIB_ENTRY RouterAddRoute(
PIP_ADDRESS NetworkAddress,
PIP_ADDRESS Netmask,
PNET_TABLE_ENTRY NTE,
PNEIGHBOR_CACHE_ENTRY Router,
UINT Metric)
/*
@ -279,24 +315,23 @@ PFIB_ENTRY RouterAddRoute(
* ARGUMENTS:
* NetworkAddress = Pointer to address of network
* Netmask = Pointer to netmask of network
* NTE = Pointer to NTE to use
* Router = Pointer to NCE of router to use
* Metric = Cost of this route
* RETURNS:
* Pointer to FIB entry if the route was added, NULL if not
* 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
* these references
*/
{
PFIB_ENTRY FIBE;
TI_DbgPrint(DEBUG_ROUTER, ("Called. NetworkAddress (0x%X) Netmask (0x%X) NTE (0x%X) "
"Router (0x%X) Metric (%d).\n", NetworkAddress, Netmask, NTE, Router, Metric));
TI_DbgPrint(DEBUG_ROUTER, ("Called. NetworkAddress (0x%X) Netmask (0x%X) "
"Router (0x%X) Metric (%d).\n", NetworkAddress, Netmask, Router, Metric));
TI_DbgPrint(DEBUG_ROUTER, ("NetworkAddress (%s) Netmask (%s) NTE (%s) Router (%s).\n",
A2S(NetworkAddress), A2S(Netmask), A2S(NTE->Address), A2S(Router->Address)));
TI_DbgPrint(DEBUG_ROUTER, ("NetworkAddress (%s) Netmask (%s) Router (%s).\n",
A2S(NetworkAddress), A2S(Netmask), A2S(Router->Address)));
FIBE = ExAllocatePool(NonPagedPool, sizeof(FIB_ENTRY));
if (!FIBE) {
@ -304,13 +339,11 @@ PFIB_ENTRY RouterAddRoute(
return NULL;
}
INIT_TAG(NTE, TAG('N','T','E',' '));
INIT_TAG(Router, TAG('R','O','U','T'));
FIBE->Free = FreeFIB;
FIBE->NetworkAddress = NetworkAddress;
FIBE->Netmask = Netmask;
FIBE->NTE = NTE;
FIBE->Router = Router;
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, ("Destination (%s) NTE (%s).\n",
A2S(Destination), A2S(NTE->Address)));
TI_DbgPrint(DEBUG_ROUTER, ("Destination (%s)\n", A2S(Destination)));
if( NTE )
TI_DbgPrint(DEBUG_ROUTER, ("NTE (%s).\n", A2S(NTE->Address)));
KeAcquireSpinLock(&FIBLock, &OldIrql);
@ -476,7 +510,7 @@ PFIB_ENTRY RouterCreateRouteIPv4(
ReferenceObject(pNetworkAddress);
ReferenceObject(pNetmask);
FIBE = RouterAddRoute(pNetworkAddress, pNetmask, NTE, NCE, 1);
FIBE = RouterAddRoute(pNetworkAddress, pNetmask, NCE, 1);
if (!FIBE) {
/* Not enough free resources */
NBRemoveNeighbor(NCE);

View file

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

View file

@ -7,6 +7,7 @@
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <address.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) {
AddrInitIPv4(IPAddress, ValidAddr->in_addr);
*Address = IPAddress;

View file

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

View file

@ -8,6 +8,7 @@
* 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>
@ -53,13 +54,9 @@ NTSTATUS DispPrepareIrpForCancel(
Irp->IoStatus.Status = STATUS_CANCELLED;
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"));
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));
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
IRPFinish(Irp, STATUS_SUCCESS);
}
@ -239,7 +236,7 @@ NTSTATUS DispTdiAccept(
{
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
return STATUS_NOT_IMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
@ -378,11 +375,14 @@ NTSTATUS DispTdiConnect(
Request.RequestNotifyObject = DispDataRequestComplete;
Request.RequestContext = Irp;
/* XXX Handle connected UDP, etc... */
Status = TCPConnect(
&Request,
Parameters->RequestConnectionInformation,
Parameters->ReturnConnectionInformation);
TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
return Status;
}
@ -555,36 +555,7 @@ NTSTATUS DispTdiListen(
Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
/* Initialize a listen request */
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);
}
Status = TCPListen( Request, 1024 /* BACKLOG */ );
return Status;
}
@ -683,9 +654,61 @@ NTSTATUS DispTdiReceive(
* 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"));
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);
TranContext = IrpSp->FileObject->FsContext;
if (TranContext == NULL)
{
TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
return STATUS_INVALID_ADDRESS;
}
/* Initialize a receive request */
Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
Request.RequestNotifyObject = DispDataRequestComplete;
@ -720,22 +749,26 @@ NTSTATUS DispTdiReceiveDatagram(
IrpSp->FileObject->FsContext,
Irp,
(PDRIVER_CANCEL)DispCancelRequest);
if (NT_SUCCESS(Status)) {
Status = UDPReceiveDatagram(
&Request,
DgramInfo->ReceiveDatagramInformation,
(PNDIS_BUFFER)Irp->MdlAddress,
DgramInfo->ReceiveLength,
DgramInfo->ReceiveFlags,
DgramInfo->ReturnDatagramInformation,
&BytesReceived);
if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, BytesReceived);
/* Return STATUS_PENDING because DispPrepareIrpForCancel marks
the Irp as pending */
Status = STATUS_PENDING;
if (NT_SUCCESS(Status))
{
Status = UDPReceiveDatagram(
&Request,
DgramInfo->ReceiveDatagramInformation,
(PNDIS_BUFFER)Irp->MdlAddress,
DgramInfo->ReceiveLength,
DgramInfo->ReceiveFlags,
DgramInfo->ReturnDatagramInformation,
&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));
@ -753,9 +786,46 @@ NTSTATUS DispTdiSend(
* 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"));
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));
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return STATUS_INVALID_PARAMETER;
return IRPFinish(Irp, STATUS_INVALID_PARAMETER);
}
Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);

View file

@ -7,6 +7,7 @@
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <datagram.h>
#include <address.h>
@ -16,6 +17,7 @@
#include <udp.h>
#include <ip.h>
#include <fileobjs.h>
#include <oskittcp.h>
/* List of all address file objects managed by this driver */
LIST_ENTRY AddressFileListHead;
@ -98,7 +100,8 @@ VOID DeleteAddress(
CurrentEntry = AddrFile->TransmitQueue.Flink;
while (CurrentEntry != &AddrFile->TransmitQueue) {
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 */
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
(*SendRequest->Complete)(SendRequest->Context, STATUS_ADDRESS_CLOSED, 0);
@ -309,7 +312,7 @@ NTSTATUS FileOpenAddress(
case IPPROTO_TCP:
/* FIXME: If specified port is 0, a port is chosen dynamically */
AddrFile->Port = Address->Address[0].Address[0].sin_port;
AddrFile->Send = TCPSendDatagram;
AddrFile->Send = TCPSendData;
break;
case IPPROTO_UDP:
@ -437,7 +440,9 @@ NTSTATUS FileOpenConnection(
PTDI_REQUEST Request,
PVOID ClientContext)
{
NTSTATUS Status;
PCONNECTION_ENDPOINT Connection;
PADDRESS_FILE AddrFile;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
@ -455,15 +460,26 @@ NTSTATUS FileOpenConnection(
/* Reference the object */
Connection->RefCount = 1;
/* Put connection in the closed state */
Connection->State = ctClosed;
/* Save client context pointer */
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);
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 */
Request->Handle.ConnectionContext = Connection;
@ -497,43 +513,9 @@ NTSTATUS FileCloseConnection(
Connection = Request->Handle.ConnectionContext;
#if 0
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
if ((!AF_IS_BUSY(Connection)) && (Connection->RefCount == 1)) {
/* Set connection endpoint file object exclusive to us */
AF_SET_BUSY(Connection);
AF_CLR_VALID(Connection);
TCPClose(Request);
DeleteConnectionEndpoint(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"));
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:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <info.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(
PTDI_REQUEST Request,
TDIObjectID *ID,
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;
VOID InsertTDIInterfaceEntity( PIP_INTERFACE Interface ) {
KIRQL OldIrql;
UINT Count = 0, i;
BufSize = *BufferSize;
TI_DbgPrint(MAX_TRACE,
("Inserting interface %08x (%d entities already)\n",
Interface, EntityCount));
/* Make return parameters consistent every time */
*BufferSize = 0;
KeAcquireSpinLock( &EntityListLock, &OldIrql );
Entity = ID->toi_entity.tei_entity;
if (Entity != CL_NL_ENTITY)
{
/* We can't handle this entity */
return TDI_INVALID_PARAMETER;
/* Count IP Entities */
for( i = 0; i < EntityCount; i++ )
if( EntityList[i].tei_entity == IF_ENTITY ) {
Count++;
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)
{
/* 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;
KeReleaseSpinLock( &EntityListLock, OldIrql );
}
TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer,
UINT BufSize,
PUINT BufferSize)
{
UINT Count, Size, Temp;
UINT Count, Size, BufSize = *BufferSize;
KIRQL OldIrql;
TDIEntityID *EntityOutList;
PLIST_ENTRY CurrentIFEntry;
/* Count Adapters */
KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
TI_DbgPrint(MAX_TRACE,("About to copy %d TDIEntityIDs to user\n",
EntityCount));
CurrentIFEntry = InterfaceListHead.Flink;
Count = EntityCount;
while( CurrentIFEntry != &InterfaceListHead ) {
Count++;
CurrentIFEntry = CurrentIFEntry->Flink;
}
KeReleaseSpinLock(&InterfaceListLock, OldIrql);
Size = Count * sizeof(TDIEntityID);
KeAcquireSpinLock(&EntityListLock, &OldIrql);
Size = EntityCount * sizeof(TDIEntityID);
*BufferSize = Size;
if (BufSize < Size)
{
KeReleaseSpinLock( &EntityListLock, OldIrql );
/* The buffer is too small to contain requested data */
return TDI_BUFFER_TOO_SMALL;
}
DbgPrint("About to copy %d TDIEntityIDs (%d bytes) to user\n",
Count, Size);
KeAcquireSpinLock(&EntityListLock, &OldIrql);
/* Update entity list */
for( Temp = EntityCount; Temp < Count; Temp++ ) {
EntityList[Temp].tei_entity = IF_ENTITY;
EntityList[Temp].tei_instance = Temp - EntityCount;
/* Return entity list -- Copy only the TDIEntityID parts. */
for( Count = 0; Count < EntityCount; Count++ ) {
CopyBufferToBufferChain(Buffer,
Count * sizeof(TDIEntityID),
(PUCHAR)&EntityList[Count],
sizeof(TDIEntityID));
}
EntityMax = Count;
/* Return entity list */
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size);
KeReleaseSpinLock(&EntityListLock, OldIrql);
*BufferSize = Size;
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(
PTDI_REQUEST Request,
TDIObjectID *ID,
@ -341,170 +130,72 @@ TDI_STATUS InfoTdiQueryInformationEx(
* Status of operation
*/
{
PLIST_ENTRY CurrentIFEntry;
PLIST_ENTRY CurrentADEEntry;
PLIST_ENTRY CurrentADFEntry;
PADDRESS_FILE CurrentADF;
PADDRESS_ENTRY CurrentADE;
PIP_INTERFACE CurrentIF;
ADDRESS_INFO Info;
KIRQL OldIrql;
UINT BufSize;
UINT Entity;
UINT Offset;
ULONG Temp;
UINT Count;
UINT Size;
TDIEntityID EntityId;
KIRQL OldIrql;
UINT i;
PVOID context;
NTSTATUS Status = STATUS_SUCCESS;
TDIEntityID EntityId;
BOOL FoundEntity = FALSE;
InfoRequest_f InfoRequest;
Offset = 0;
BufSize = *BufferSize;
TI_DbgPrint(MAX_TRACE,
("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 */
Entity = ID->toi_entity.tei_entity;
if (Entity == GENERIC_ENTITY)
/* Check wether it is a query for a list of entities */
if (ID->toi_entity.tei_entity == GENERIC_ENTITY)
{
if ((ID->toi_class != INFO_CLASS_GENERIC) ||
(ID->toi_type != INFO_TYPE_PROVIDER) ||
(ID->toi_id != ENTITY_LIST_ID))
{
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;
}
if ((ID->toi_class != INFO_CLASS_GENERIC) ||
(ID->toi_type != INFO_TYPE_PROVIDER) ||
(ID->toi_id != ENTITY_LIST_ID))
Status = TDI_INVALID_PARAMETER;
else
{
return TDI_INVALID_PARAMETER;
}
Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&Temp, sizeof(ULONG));
return TDI_SUCCESS;
Status = InfoTdiQueryListEntities(Buffer, BufferSize);
} else {
KeAcquireSpinLock( &EntityListLock, &OldIrql );
for( i = 0; i < EntityCount; i++ ) {
if( EntityList[i].tei_entity == ID->toi_entity.tei_entity &&
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)
{
if (ID->toi_type != INFO_TYPE_PROVIDER)
{
return TDI_INVALID_PARAMETER;
}
TI_DbgPrint(MAX_TRACE,("Status: %08x\n", Status));
switch (ID->toi_id)
{
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;
return Status;
}
TDI_STATUS InfoTdiSetInformationEx(
PTDI_REQUEST Request,
TDIObjectID *ID,
PVOID Buffer,
UINT BufferSize)
TDI_STATUS InfoTdiSetInformationEx
(PTDI_REQUEST Request,
TDIObjectID *ID,
PVOID Buffer,
UINT BufferSize)
/*
* FUNCTION: Sets extended information
* ARGUMENTS:
@ -516,30 +207,30 @@ TDI_STATUS InfoTdiSetInformationEx(
* Status of operation
*/
{
switch( ID->toi_class ) {
case INFO_CLASS_PROTOCOL:
switch( ID->toi_type ) {
case INFO_TYPE_PROVIDER:
switch( ID->toi_id ) {
case IP_MIB_ROUTETABLE_ENTRY_ID:
if( ID->toi_entity.tei_entity == CL_NL_ENTITY &&
ID->toi_entity.tei_instance == TL_INSTANCE &&
BufferSize >= sizeof(IPROUTE_ENTRY) ) {
/* Add route -- buffer is an IPRouteEntry */
PIPROUTE_ENTRY ire = (PIPROUTE_ENTRY)Buffer;
RouteFriendlyAddRoute( ire );
} else {
return TDI_INVALID_PARAMETER;
/* In my experience, we are being over
protective compared to windows */
switch( ID->toi_class ) {
case INFO_CLASS_PROTOCOL:
switch( ID->toi_type ) {
case INFO_TYPE_PROVIDER:
switch( ID->toi_id ) {
case IP_MIB_ROUTETABLE_ENTRY_ID:
if( ID->toi_entity.tei_entity == CL_NL_ENTITY &&
ID->toi_entity.tei_instance == TL_INSTANCE &&
BufferSize >= sizeof(IPROUTE_ENTRY) ) {
/* Add route -- buffer is an IPRouteEntry */
PIPROUTE_ENTRY ire = (PIPROUTE_ENTRY)Buffer;
RouteFriendlyAddRoute( ire );
} else {
return TDI_INVALID_PARAMETER;
/* In my experience, we are being over
protective compared to windows */
}
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 <tcp.h>
#include <rosrtl/string.h>
#include <info.h>
#include <memtrack.h>
#define NDEBUG
@ -33,7 +35,7 @@ PDEVICE_OBJECT RawIPDeviceObject = NULL;
NDIS_HANDLE GlobalPacketPool = NULL;
NDIS_HANDLE GlobalBufferPool = NULL;
KSPIN_LOCK EntityListLock;
TDIEntityID *EntityList = NULL;
TDIEntityInfo *EntityList = NULL;
ULONG EntityCount = 0;
ULONG EntityMax = 0;
UDP_STATISTICS UDPStats;
@ -456,18 +458,9 @@ TiDispatchOpenClose(
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));
return Status;
return IRPFinish( Irp, Status );
}
@ -487,7 +480,7 @@ TiDispatchInternal(
* Status of the operation
*/
{
NTSTATUS Status;
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
@ -560,17 +553,9 @@ TiDispatchInternal(
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));
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));
return Status;
return IRPFinish( Irp, Status );
}
@ -726,6 +703,14 @@ DriverEntry(
NDIS_STRING DeviceName;
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
TrackingInit();
TrackTag(NDIS_BUFFER_TAG);
TrackTag(NDIS_PACKET_TAG);
TrackTag(FBSD_MALLOC);
TrackTag(EXALLOC_TAG);
InitOskitTCP();
/* TdiInitialize() ? */
@ -770,6 +755,28 @@ DriverEntry(
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 */
NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
@ -830,22 +837,6 @@ DriverEntry(
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 */
IPDeviceObject->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:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <pool.h>

View file

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

View file

@ -7,6 +7,7 @@
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <rawip.h>
#include <routines.h>
@ -21,8 +22,7 @@ BOOLEAN RawIPInitialized = FALSE;
NTSTATUS BuildRawIPPacket(
PVOID Context,
PIP_ADDRESS LocalAddress,
USHORT LocalPort,
PIP_PACKET *IPPacket)
USHORT LocalPort )
/*
* FUNCTION: Builds an UDP packet
* ARGUMENTS:
@ -35,43 +35,26 @@ NTSTATUS BuildRawIPPacket(
*/
{
PVOID Header;
PIP_PACKET Packet;
NDIS_STATUS NdisStatus;
PNDIS_BUFFER HeaderBuffer;
PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context;
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));
PIP_PACKET Packet = &SendRequest->Packet;
/* Prepare packet */
/* FIXME: Assumes IPv4 */
Packet = IPCreatePacket(IP_ADDRESS_V4);
if (!Packet)
return STATUS_INSUFFICIENT_RESOURCES;
IPInitializePacket(Packet,IP_ADDRESS_V4);
Packet->Flags = IP_PACKET_FLAG_RAW; /* Don't touch IP header */
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) {
Header = ExAllocatePool(NonPagedPool, MaxLLHeaderSize);
if (!Header) {
TI_DbgPrint(MIN_TRACE, ("Cannot allocate memory for packet headers.\n"));
NdisFreePacket(Packet->NdisPacket);
(*Packet->Free)(Packet);
FreeNdisPacket(Packet->NdisPacket);
return STATUS_INSUFFICIENT_RESOURCES;
}
@ -87,21 +70,15 @@ NTSTATUS BuildRawIPPacket(
if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS buffer for packet headers. NdisStatus = (0x%X)\n", NdisStatus));
ExFreePool(Header);
NdisFreePacket(Packet->NdisPacket);
(*Packet->Free)(Packet);
FreeNdisPacket(Packet->NdisPacket);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Chain header at front of packet */
NdisChainBufferAtFront(Packet->NdisPacket, HeaderBuffer);
}
/* Chain data after link level header if it exists */
NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer);
DISPLAY_IP_PACKET(Packet);
*IPPacket = Packet;
return STATUS_SUCCESS;
}
@ -122,8 +99,30 @@ NTSTATUS RawIPSendDatagram(
* Status of operation
*/
{
return DGSendDatagram(Request, ConnInfo,
Buffer, DataSize, BuildRawIPPacket);
NDIS_STATUS Status;
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:
* CSH 01/08-2000 Created
*/
#include <roscfg.h>
#include <tcpip.h>
#include <udp.h>
#include <routines.h>
@ -91,7 +92,7 @@ NTSTATUS AddUDPHeaderIPv4(
/* Source address */
IPHeader->SrcAddr = LocalAddress->Address.IPv4Address;
/* Destination address. FIXME: IPv4 only */
IPHeader->DstAddr = SendRequest->RemoteAddress->Address.IPv4Address;
IPHeader->DstAddr = SendRequest->RemoteAddress.Address.IPv4Address;
/* Build UDP header */
UDPHeader = (PUDP_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER));
@ -110,8 +111,7 @@ NTSTATUS AddUDPHeaderIPv4(
NTSTATUS BuildUDPPacket(
PVOID Context,
PIP_ADDRESS LocalAddress,
USHORT LocalPort,
PIP_PACKET *IPPacket)
USHORT LocalPort)
/*
* FUNCTION: Builds an UDP packet
* ARGUMENTS:
@ -124,16 +124,16 @@ NTSTATUS BuildUDPPacket(
*/
{
NTSTATUS Status;
PIP_PACKET Packet;
NDIS_STATUS NdisStatus;
PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context;
PIP_PACKET Packet = &SendRequest->Packet;
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Prepare packet */
/* FIXME: Assumes IPv4 */
Packet = IPCreatePacket(IP_ADDRESS_V4);
IPInitializePacket(IP_ADDRESS_V4, &SendRequest->Packet);
if (!Packet)
return STATUS_INSUFFICIENT_RESOURCES;
@ -141,15 +141,7 @@ NTSTATUS BuildUDPPacket(
sizeof(UDP_HEADER) +
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;
}
switch (SendRequest->RemoteAddress->Type) {
switch (SendRequest->RemoteAddress.Type) {
case IP_ADDRESS_V4:
Status = AddUDPHeaderIPv4(SendRequest, LocalAddress, LocalPort, Packet);
break;
@ -162,18 +154,12 @@ NTSTATUS BuildUDPPacket(
}
if (!NT_SUCCESS(Status)) {
TI_DbgPrint(MIN_TRACE, ("Cannot add UDP header. Status = (0x%X)\n", Status));
NdisFreePacket(Packet->NdisPacket);
(*Packet->Free)(Packet);
FreeNdisPacket(Packet->NdisPacket);
return Status;
}
/* Chain data after header */
NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer);
DISPLAY_IP_PACKET(Packet);
*IPPacket = Packet;
return STATUS_SUCCESS;
}
@ -194,11 +180,18 @@ NTSTATUS UDPSendDatagram(
* Status of operation
*/
{
return DGSendDatagram(Request,
ConnInfo,
Buffer,
DataSize,
BuildUDPPacket);
PDATAGRAM_SEND_REQUEST SendRequest;
PADDRESS_FILE AddrFile =
(PADDRESS_FILE)Request->Handle.AddressHandle;
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 = ../..

View file

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

View file

@ -28,10 +28,20 @@ extern HANDLE GlobalHeap;
extern BOOL Initialized; /* TRUE if WSAStartup() has been successfully called */
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 {
INT LastErrorValue; /* Error value from last function that failed */
CHAR Intoa[16]; /* Buffer for inet_ntoa() */
PWINSOCK_GETSERVBYNAME_CACHE
Getservbyname; /* Buffer used by getservbyname */
} 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 = ../..

View file

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

View file

@ -7,8 +7,13 @@
* REVISIONS:
* CSH 01/09-2000 Created
*/
#include <ctype.h>
#include <ws2_32.h>
#ifndef BUFSIZ
#define BUFSIZ 1024
#endif/*BUFSIZ*/
/* Name resolution APIs */
/*
@ -420,9 +425,58 @@ getprotobynumber(
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
EXPORT
@ -430,9 +484,157 @@ getservbyname(
IN CONST CHAR FAR* name,
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;
}