📄 eth.c
字号:
}
eth_fd->ef_rd_buf= 0;
}
PRIVATE int eth_checkopt (eth_fd)
eth_fd_t *eth_fd;
{
/* bug: we don't check access modes yet */
unsigned long flags;
unsigned int en_di_flags;
eth_port_t *eth_port;
acc_t *acc, *acc2;
eth_port= eth_fd->ef_port;
flags= eth_fd->ef_ethopt.nweo_flags;
#if DEBUG & 256
{ where(); printf("eth_fd_table[%d].ef_ethopt.nweo_flags= 0x%x\n",
eth_fd-eth_fd_table, flags); }
#endif
en_di_flags= (flags >>16) | (flags & 0xffff);
if ((en_di_flags & NWEO_ACC_MASK) &&
(en_di_flags & NWEO_LOC_MASK) &&
(en_di_flags & NWEO_BROAD_MASK) &&
(en_di_flags & NWEO_MULTI_MASK) &&
(en_di_flags & NWEO_PROMISC_MASK) &&
(en_di_flags & NWEO_REM_MASK) &&
(en_di_flags & NWEO_TYPE_MASK) &&
(en_di_flags & NWEO_RW_MASK))
{
eth_fd->ef_flags |= EFF_OPTSET;
eth_fd->ef_pack_stat= EPS_EMPTY;
if (flags & NWEO_EN_LOC)
eth_fd->ef_pack_stat |= EPS_LOC;
if (flags & NWEO_EN_BROAD)
eth_fd->ef_pack_stat |= EPS_BROAD;
if (flags & NWEO_EN_MULTI)
eth_fd->ef_pack_stat |= EPS_MULTI;
if (flags & NWEO_EN_PROMISC)
eth_fd->ef_pack_stat |= (EPS_PROMISC|EPS_MULTI|
EPS_BROAD);
}
else
eth_fd->ef_flags &= ~EFF_OPTSET;
for (acc= eth_fd->ef_rd_buf; acc;)
{
acc2= acc->acc_ext_link;
bf_afree(acc);
acc= acc2;
}
eth_fd->ef_rd_buf= 0;
return NW_OK;
}
PUBLIC int eth_get_work(eth_port)
eth_port_t *eth_port;
{
eth_fd_t *eth_fd;
int i;
#if DEBUG & 256
{ where(); printf("eth_get_work called\n"); }
#endif
if (eth_port->etp_wr_pack)
return 0;
if (!(eth_port->etp_flags & EPF_MORE2WRITE))
return 0;
for (i=0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
{
if ((eth_fd->ef_flags & (EFF_INUSE|EFF_WRITE_IP)) !=
(EFF_INUSE|EFF_WRITE_IP))
continue;
if (eth_fd->ef_port != eth_port)
continue;
#if DEBUG & 256
{ where(); printf("eth_get_work calling restart_write_fd\n"); }
#endif
restart_write_fd(eth_fd);
if (eth_port->etp_wr_pack)
return 1;
}
eth_port->etp_flags &= ~EPF_MORE2WRITE;
return 0;
}
PUBLIC void eth_arrive (eth_port, pack)
eth_port_t *eth_port;
acc_t *pack;
{
time_t exp_tim;
eth_hdr_t *eth_hdr;
static ether_addr_t broadcast= {255, 255, 255, 255, 255, 255},
multi_addr, rem_addr, packaddr;
int pack_stat;
ether_type_t type;
eth_fd_t *eth_fd, *share_fd;
acc_t *acc;
int i;
#if DEBUG & 256
{ where(); printf("eth_arrive(0x%x, 0x%x) called\n", eth_port, pack); }
#endif
assert(pack->acc_linkC);
exp_tim= get_time() + EXPIRE_TIME;
pack= bf_packIffLess(pack, ETH_HDR_SIZE);
eth_hdr= (eth_hdr_t*)ptr2acc_data(pack);
#if DEBUG & 256
{ where(); printf("src= "); writeEtherAddr(ð_hdr->eh_src); printf(" dst= "); writeEtherAddr(ð_hdr->eh_dst);
printf(" proto= 0x%x\n", ntohs(eth_hdr->eh_proto));
printf(" my addr= "); writeEtherAddr(ð_port->etp_ethaddr);
printf("\n"); }
#endif
packaddr= eth_hdr->eh_dst;
if (packaddr.ea_addr[0] & 0x01)
{
/* multi cast or broadcast */
if (!eth_addrcmp(packaddr, broadcast))
pack_stat= EPS_BROAD;
else
{
pack_stat= EPS_MULTI;
#if DEBUG
{ where(); printf("Got a multicast packet\n"); }
#endif
}
}
else
{
if (!eth_addrcmp (packaddr, eth_port->etp_ethaddr))
pack_stat= EPS_LOC;
else
pack_stat= EPS_PROMISC;
}
type= eth_hdr->eh_proto;
#if DEBUG & 256
{ where(); printf("pack_stat= 0x%x\n", pack_stat); }
#endif
share_fd= 0;
for (i=0, eth_fd=eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
{
if (!(eth_fd->ef_flags & EFF_OPTSET))
{
#if DEBUG & 256
{ where(); printf("fd %d doesn't have EFF_OPTSET\n", i); }
#endif
continue;
}
if (eth_fd->ef_port != eth_port)
{
#if DEBUG
{ where(); printf("fd %d uses port %d, packet is on port %d\n", i,
eth_fd->ef_port-eth_port_table, eth_port-eth_port_table); }
#endif
continue;
}
if (!(eth_fd->ef_pack_stat & pack_stat))
{
#if DEBUG & 256
{ where(); printf("fd %d has ef_pack_stat 0x%x, expecting 0x%x\n", i,
eth_fd->ef_pack_stat, pack_stat); }
#endif
continue;
}
if ((eth_fd->ef_ethopt.nweo_flags & NWEO_TYPESPEC) &&
type != eth_fd->ef_ethopt.nweo_type)
{
#if DEBUG & 256
{ where(); printf("fd %d uses type 0x%x, expecting 0x%x\n", i,
eth_fd->ef_ethopt.nweo_type, type); }
#endif
continue;
}
#if DEBUG & 256
{ where(); printf("multi OK\n"); }
#endif
if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC)
{
rem_addr= eth_fd->ef_ethopt.nweo_rem;
if (eth_addrcmp (eth_hdr->eh_src,
rem_addr))
continue;
}
#if DEBUG & 256
{ where(); printf("rem NW_OK\n"); }
#endif
if (eth_fd->ef_rd_buf)
{
if (eth_fd->ef_ethopt.nweo_flags == NWEO_SHARED)
{
share_fd= eth_fd;
continue;
}
}
acc= bf_dupacc(pack);
acc->acc_ext_link= NULL;
if (!eth_fd->ef_rd_buf)
{
eth_fd->ef_rd_buf= acc;
eth_fd->ef_exp_tim= exp_tim;
}
else
eth_fd->ef_rd_tail->acc_ext_link= acc;
eth_fd->ef_rd_tail= acc;
if (eth_fd->ef_flags & EFF_READ_IP)
packet2user(eth_fd);
if ((eth_fd->ef_ethopt.nweo_flags & NWEO_ACC_MASK) != NWEO_COPY)
{
bf_afree(pack);
pack= 0;
break;
}
}
if (share_fd && pack)
{
acc= bf_dupacc(pack);
acc->acc_ext_link= NULL;
if (!share_fd->ef_rd_buf)
{
share_fd->ef_rd_buf= acc;
share_fd->ef_exp_tim= exp_tim;
}
else
share_fd->ef_rd_tail->acc_ext_link= acc;
share_fd->ef_rd_tail= acc;
}
if (pack)
bf_afree(pack);
}
PRIVATE int packet2user (eth_fd)
eth_fd_t *eth_fd;
{
acc_t *pack, *header;
int result;
size_t size;
#if DEBUG & 256
{ where(); printf("packet2user() called\n"); }
#endif
pack= eth_fd->ef_rd_buf;
eth_fd->ef_rd_buf= pack->acc_ext_link;
if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
{
pack= bf_packIffLess (pack, ETH_HDR_SIZE);
assert (pack->acc_length >= ETH_HDR_SIZE);
if (pack->acc_linkC >1)
{
header= bf_dupacc (pack);
bf_afree(pack);
pack= header;
}
assert (pack->acc_linkC == 1);
pack->acc_offset += ETH_HDR_SIZE;
pack->acc_length -= ETH_HDR_SIZE;
}
size= bf_bufsize (pack);
eth_fd->ef_flags &= ~EFF_READ_IP;
result= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, (size_t)0, pack,
FALSE);
if (result >=0)
reply_thr_put(eth_fd, size, FALSE);
return result<0 ? result : NW_OK;
}
PRIVATE int ok_for_me (eth_fd, pack)
eth_fd_t *eth_fd;
acc_t *pack;
{
eth_port_t *eth_port;
eth_hdr_t *eth_hdr;
ether_type_t type;
static ether_addr_t broadcast= {255, 255, 255, 255, 255, 255},
packaddr, portaddr, multi_addr, rem_addr;
int pack_kind;
assert (pack->acc_length >= ETH_HDR_SIZE);
eth_port= eth_fd->ef_port;
eth_hdr= (eth_hdr_t *)ptr2acc_data(pack);
packaddr= eth_hdr->eh_dst;
if (packaddr.ea_addr[0] & 0x01)
/* multi cast or broadcast */
if (!eth_addrcmp (packaddr, broadcast))
pack_kind= EPS_BROAD;
else
pack_kind= EPS_MULTI;
else
{
portaddr= eth_port->etp_ethaddr;
if (!eth_addrcmp(packaddr, portaddr))
pack_kind= EPS_LOC;
else
pack_kind= EPS_PROMISC;
}
pack_kind &= eth_fd->ef_pack_stat;
if (!pack_kind)
return FALSE;
type= eth_hdr->eh_proto;
if ((eth_fd->ef_ethopt.nweo_flags & NWEO_TYPESPEC) &&
type != eth_fd->ef_ethopt.nweo_type)
return FALSE;
if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC)
{
rem_addr= eth_fd->ef_ethopt.nweo_rem;
if (eth_addrcmp(eth_hdr->eh_src, rem_addr))
return FALSE;
}
return TRUE;
}
PRIVATE void eth_buffree (priority, reqsize)
int priority;
size_t reqsize;
{
int i, once_more;
time_t curr_tim;
acc_t *acc;
if (priority <ETH_PRI_EXP_FDBUFS)
return;
#if DEBUG & 256
{ where(); printf("eth_buffree called\n"); }
#endif
curr_tim= get_time();
for (i=0; i<ETH_FD_NR; i++)
{
if (!(eth_fd_table[i].ef_flags & EFF_INUSE) )
continue;
acc= eth_fd_table[i].ef_rd_buf;
if (acc && eth_fd_table[i].ef_exp_tim < curr_tim)
{
eth_fd_table[i].ef_rd_buf= acc->acc_ext_link;
bf_afree(acc);
if (bf_free_buffsize >= reqsize)
return;
}
}
if (priority <ETH_PRI_FDBUFS)
return;
once_more= 1;
while (once_more)
{
once_more= 0;
for (i=0; i<ETH_FD_NR; i++)
{
if (!(eth_fd_table[i].ef_flags & EFF_INUSE))
continue;
acc= eth_fd_table[i].ef_rd_buf;
if (acc)
{
eth_fd_table[i].ef_rd_buf= acc->acc_ext_link;
bf_afree(acc);
if (bf_free_buffsize >= reqsize)
return;
once_more= 1;
}
}
}
}
PRIVATE void restart_write_fd(eth_fd)
eth_fd_t *eth_fd;
{
eth_port_t *eth_port;
acc_t *user_data, *header;
int size;
unsigned long nweo_flags;
eth_hdr_t *eth_hdr;
eth_port= eth_fd->ef_port;
if (eth_port->etp_wr_pack)
{
eth_port->etp_flags |= EPF_MORE2WRITE;
return;
}
assert (eth_fd->ef_flags & EFF_WRITE_IP);
eth_fd->ef_flags &= ~EFF_WRITE_IP;
assert (!eth_port->etp_wr_pack);
#if DEBUG & 256
{ where(); printf("calling *get_userdata\n"); }
#endif
user_data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, 0,
eth_fd->ef_write_count, FALSE);
if (!user_data)
{
eth_fd->ef_flags &= ~EFF_WRITE_IP;
reply_thr_get (eth_fd, EFAULT, FALSE);
return;
}
size= bf_bufsize (user_data);
nweo_flags= eth_fd->ef_ethopt.nweo_flags;
if (nweo_flags & NWEO_RWDATONLY)
{
header= bf_memreq(ETH_HDR_SIZE);
header->acc_next= user_data;
user_data= header;
}
user_data= bf_packIffLess (user_data, ETH_HDR_SIZE);
eth_hdr= (eth_hdr_t *)ptr2acc_data(user_data);
if (nweo_flags & NWEO_REMSPEC)
eth_hdr->eh_dst= eth_fd->ef_ethopt.nweo_rem;
eth_hdr->eh_src= eth_port->etp_ethaddr;
if (nweo_flags & NWEO_TYPESPEC)
eth_hdr->eh_proto= eth_fd->ef_ethopt.nweo_type;
assert (!eth_port->etp_wr_pack);
eth_port->etp_wr_pack= user_data;
if (!(eth_port->etp_flags & EPF_WRITE_IP))
{
eth_write_port(eth_port);
}
reply_thr_get (eth_fd, size, FALSE);
}
PRIVATE void reply_thr_get (eth_fd, result, for_ioctl)
eth_fd_t *eth_fd;
size_t result;
int for_ioctl;
{
acc_t *data;
#if DEBUG & 256
{ where(); printf("calling *get_userdata(fd= %d, %d, 0)\n", eth_fd->
ef_srfd, result, 0); }
#endif
data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, result, 0, for_ioctl);
assert (!data);
}
PRIVATE void reply_thr_put (eth_fd, result, for_ioctl)
eth_fd_t *eth_fd;
size_t result;
int for_ioctl;
{
int error;
error= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, result, (acc_t *)0,
for_ioctl);
assert(!error);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -