📄 sockpcb.c
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// SOCKPCB.C
//
// Object member functions for the Sock device object.
//
// These functions include protocol control type access to the
// SOCKET object.
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "sock.h"
static SOCK *pSockList[] = { 0, 0, 0, 0, 0 };
// Next User Port for Ephemeral Ports
static uint wUserPort = SOCK_USERPORT_FIRST;
static SOCK *SockPcbFind( SOCK *psFirst, IPN dwLIP, uint LPort,
IPN dwFIP, uint FPort, int *pwc, int FindAll );
static SOCK *SockPcbFindRaw( SOCK *psFirst, uint Prot, IPN dwLIP,
IPN dwFIP, int *pwc, int FindAll );
//--------------------------------------------------------------------
// SockPcbAttach()
//
// Adds a socket to the supplied socket list
//--------------------------------------------------------------------
int SockPcbAttach( HANDLE hSock )
{
SOCK *ps = (SOCK *)hSock;
#ifdef _STRONG_CHECKING
if( ps->Type != HTYPE_SOCK )
{
DbgPrintf(DBG_ERROR,"SockPcbAttach: HTYPE %04x",ps->Type);
return( 0 );
}
if( ps->SockProt > 4 )
{
DbgPrintf(DBG_ERROR,"SockPcbAttach: Invalid SockProt");
return( 0 );
}
#endif
// We'll insert at head of list since its quicker
ps->pProtPrev = 0;
ps->pProtNext = pSockList[ps->SockProt];
pSockList[ps->SockProt] = (HANDLE)ps;
// Patch entry which follows us (if any)
if( ps->pProtNext )
ps->pProtNext->pProtPrev = ps;
return(0);
}
//--------------------------------------------------------------------
// SockPcbDetach()
//
// Removes a socket to the supplied socket list
//--------------------------------------------------------------------
int SockPcbDetach( HANDLE hSock )
{
SOCK *ps = (SOCK *)hSock;
#ifdef _STRONG_CHECKING
if( ps->Type != HTYPE_SOCK )
{
DbgPrintf(DBG_ERROR,"SockPcbDetach: HTYPE %04x",ps->Type);
return( 0 );
}
if( ps->SockProt > 4 )
{
DbgPrintf(DBG_ERROR,"SockPcbDetach: Invalid SockProt");
return( 0 );
}
#endif
// Patch preceeding entry
if( !ps->pProtPrev )
pSockList[ps->SockProt] = (HANDLE)ps->pProtNext;
else
ps->pProtPrev->pProtNext = ps->pProtNext;
// Patch following entry
if( ps->pProtNext )
ps->pProtNext->pProtPrev = ps->pProtPrev;
// Just to be tidy...
ps->pProtPrev = 0;
ps->pProtNext = 0;
return(0);
}
//--------------------------------------------------------------------
// SockPcbFind()
//
// Find the "best" match for the supplied parameters.
//--------------------------------------------------------------------
static SOCK *SockPcbFind
(
SOCK *ps,
IPN dwLIP,
uint LPort,
IPN dwFIP,
uint FPort,
int *pwc,
int FindAll
)
{
SOCK *psBest = 0;
int wcBest = 9;
int wc;
// Find the "best" match for the supplied parameters.
for( ; ps; ps = ps->pProtNext )
{
// Clear wild cards
wc = 0;
// Local port NULL means socket is not bound
if( !ps->LPort )
continue;
// If local ports don't match, this entry can't match
if( ps->LPort != LPort )
continue;
// Local IP must match, or be wildcard
if( ps->dwLIP != dwLIP )
{
if( !dwLIP || !ps->dwLIP )
wc++;
else
continue;
}
// Foreign Port+IP must both match or both be wildcard
if( ps->FPort != FPort || ps->dwFIP != dwFIP )
{
if( (!dwFIP && !FPort) || (!ps->dwFIP && !ps->FPort) )
wc++;
else
continue;
}
if( wc < wcBest )
{
wcBest = wc;
psBest = ps;
}
if( FindAll )
break;
}
if( pwc )
*pwc = wcBest;
return(psBest);
}
//--------------------------------------------------------------------
// SockPcbFindRaw()
//
// Find the "best" match for the supplied parameters.
//--------------------------------------------------------------------
static SOCK *SockPcbFindRaw
(
SOCK *ps,
uint Prot,
IPN dwLIP,
IPN dwFIP,
int *pwc,
int FindAll
)
{
SOCK *psBest = 0;
int wcBest = 9;
int wc;
// Find the "best" match for the supplied parameters.
for( ; ps; ps = ps->pProtNext )
{
// Clear wild cards
wc = 0;
// Protocol must match, or be wildcard
if( ps->Protocol && ps->Protocol != Prot )
continue;
// Local IP must match, or be wildcard
if( ps->dwLIP != dwLIP )
{
if( !dwLIP || !ps->dwLIP )
wc++;
else
continue;
}
// Foreign IP must match, or be wildcard
if( ps->dwFIP != dwFIP )
{
if( !dwFIP || !ps->dwFIP )
wc++;
else
continue;
}
if( wc < wcBest )
{
wcBest = wc;
psBest = ps;
}
if( FindAll )
break;
}
if( pwc )
*pwc = wcBest;
return(psBest);
}
//--------------------------------------------------------------------
// SockPcbBind()
//
// Binds a socket to specified local LIP and LPort
//
// Note: LIP can be NULL (wildcard), but in this implementaion, LPort
// is never a wildcard. When not specified, LPort is assigned to
// an ephemeral port.
//--------------------------------------------------------------------
int SockPcbBind( HANDLE hSock, IPN dwLIP, uint LPort )
{
SOCK *ps = (SOCK *)hSock;
SOCK *psTmp;
int fEphem = 0;
uint SockOpts;
#ifdef _STRONG_CHECKING
if( ps->Type != HTYPE_SOCK )
{
DbgPrintf(DBG_ERROR,"SockPcbBind: HTYPE %04x",ps->Type);
return( 0 );
}
if( ps->SockProt > 4 )
{
DbgPrintf(DBG_ERROR,"SockPcbBind: Invalid SockProt");
return( 0 );
}
#endif
// Anything goes with Raw sockets
if( ps->SockProt == SOCKPROT_RAW )
{
SockOpts = 0;
goto SockPcbBindOk;
}
// On multicast addrs, REUSEADDR is the same as REUSEPORT
SockOpts = ps->OptionFlags & (SO_REUSEPORT|SO_REUSEADDR);
if( SockOpts == SO_REUSEADDR )
{
if( IN_MULTICAST( dwLIP ) )
SockOpts = (SO_REUSEADDR|SO_REUSEPORT);
}
// If LPort is NULL, and we are already bound to an LPort,
// then we'll use the previously bound value.
if( !LPort && ps->LPort )
LPort = ps->LPort;
// OPTION: We *may* want to restrict IP addresses to those actually
// available on our system.
// OPTION: We *may* want to restrict reserved ports to some "system"
// class user.
// Check for ephemeral port
SockPcbBindEphem:
if( !LPort )
{
if( ++wUserPort > SOCK_USERPORT_LAST )
wUserPort = SOCK_USERPORT_FIRST;
LPort = HNC16(wUserPort);
fEphem = 1;
}
// Find the best match
psTmp = SockPcbFind( pSockList[ps->SockProt], dwLIP, LPort, 0, 0, 0, 0 );
// Check for conflict (and that we didn't match ourselves)
if( psTmp && psTmp != ps && LPort == psTmp->LPort )
{
// If the IP's are different, we're OK
if( dwLIP && psTmp->dwLIP && dwLIP != psTmp->dwLIP )
goto SockPcbBindOk;
// We don't allow conflicts on ephemeral ports
if( fEphem )
{
LPort = 0;
goto SockPcbBindEphem;
}
// We have a port conflict. See if we keep going anyway
// Address Conflict
// Exception 1: Check for "REUSEPORT" on both sockets
if( psTmp->OptionFlags & SockOpts & SO_REUSEPORT )
goto SockPcbBindOk;
// Exception 2: One or the other Local IP is "wildcard", but not both,
// and both have REUSEADDR set.
if( ((!dwLIP && psTmp->dwLIP) || (dwLIP && !psTmp->dwLIP)) &&
(psTmp->OptionFlags & SockOpts & SO_REUSEADDR) )
goto SockPcbBindOk;
return( EADDRINUSE );
}
SockPcbBindOk:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -