📄 eth.c
字号:
/*eth.c*/#include "inet.h"#include "buf.h"#include "clock.h"#include "osdep_eth.h"#include "assert.h"#include "buf.h"#include "eth.h"#include "eth_int.h"#include "io.h"#include "sr.h"#include "type.h"INIT_PANIC();#define ETH_FD_NR 32#define EXPIRE_TIME 60*HZ /* seconds */typedef struct eth_fd{ int ef_flags; eth_port_t *ef_port; int ef_srfd; get_userdata_t ef_get_userdata; put_userdata_t ef_put_userdata; nwio_ethopt_t ef_ethopt; size_t ef_write_count; acc_t *ef_rd_buf; acc_t *ef_rd_tail; time_t ef_exp_tim; int ef_pack_stat;} eth_fd_t;#define EFF_FLAGS 0xf# define EFF_EMPTY 0x0# define EFF_INUSE 0x1# define EFF_BUSY 0x6# define EFF_READ_IP 0x2# define EFF_WRITE_IP 0x4# define EFF_OPTSET 0x8FORWARD int eth_checkopt ARGS(( eth_fd_t *eth_fd ));FORWARD void eth_buffree ARGS(( int priority, size_t reqsize ));FORWARD int ok_for_me ARGS(( eth_fd_t *fd, acc_t *pack ));FORWARD int packet2user ARGS(( eth_fd_t *fd ));FORWARD void reply_thr_get ARGS(( eth_fd_t *eth_fd, size_t result, int for_ioctl ));FORWARD void reply_thr_put ARGS(( eth_fd_t *eth_fd, size_t result, int for_ioctl ));FORWARD void restart_write_fd ARGS(( eth_fd_t *eth_fd ));PUBLIC eth_port_t eth_port_table[ETH_PORT_NR];PRIVATE eth_fd_t eth_fd_table[ETH_FD_NR];/* PRIVATE message mess, repl_mess; */PUBLIC void eth_init(){ int i; assert (BUF_S >= sizeof(nwio_ethopt_t)); assert (BUF_S >= ETH_HDR_SIZE); /* these are in fact static assertions, thus a good compiler doesn't generate any code for this */ for (i=0; i<ETH_FD_NR; i++) eth_fd_table[i].ef_flags= EFF_EMPTY; for (i=0; i<ETH_PORT_NR; i++) eth_port_table[i].etp_flags= EFF_EMPTY; bf_logon(eth_buffree); eth_init0(); /* eth_init1(); etc */}PUBLIC int eth_open(port, srfd, get_userdata, put_userdata)int port, srfd;get_userdata_t get_userdata;put_userdata_t put_userdata;{ int i; eth_port_t *eth_port; eth_fd_t *eth_fd;#if DEBUG & 256 { where(); printf("eth_open (%d, ...)\n", port); }#endif eth_port= ð_port_table[port]; if (!(eth_port->etp_flags & EPF_ENABLED)) return EGENERIC; for (i=0; i<ETH_FD_NR && (eth_fd_table[i].ef_flags & EFF_INUSE); i++); if (i>=ETH_FD_NR) {#if DEBUG { where(); printf("out of fds\n"); }#endif return EOUTOFBUFS; } eth_fd= ð_fd_table[i]; eth_fd->ef_flags= EFF_INUSE; eth_fd->ef_ethopt.nweo_flags=NWEO_DEFAULT; eth_fd->ef_port= eth_port; eth_fd->ef_srfd= srfd; eth_fd->ef_rd_buf= 0; eth_fd->ef_get_userdata= get_userdata; eth_fd->ef_put_userdata= put_userdata; return i;}PUBLIC int eth_ioctl(fd, req)int fd;int req;{ acc_t *data; int type; eth_fd_t *eth_fd; eth_port_t *eth_port;#if DEBUG & 256 { where(); printf("eth_ioctl (%d, ...)\n", fd); }#endif eth_fd= ð_fd_table[fd]; eth_port= eth_fd->ef_port; type= req & IOCTYPE_MASK; assert (eth_fd->ef_flags & EFF_INUSE); switch (type) { case NWIOSETHOPT & IOCTYPE_MASK: { nwio_ethopt_t *ethopt; nwio_ethopt_t oldopt, newopt; int result; u32_t new_en_flags, new_di_flags, old_en_flags, old_di_flags; u32_t flags; eth_fd_t *loc_fd; int i; if (req != NWIOSETHOPT) break; #if DEBUG & 256 { where(); printf("calling *get_userdata\n"); }#endif data= (*eth_fd->ef_get_userdata)(eth_fd-> ef_srfd, 0, sizeof(nwio_ethopt_t), TRUE); ethopt= (nwio_ethopt_t *)ptr2acc_data(data); oldopt= eth_fd->ef_ethopt; newopt= *ethopt;#if DEBUG & 256 { where(); printf("newopt.nweo_flags= 0x%x\n", newopt.nweo_flags); }#endif old_en_flags= oldopt.nweo_flags & 0xffff; old_di_flags= (oldopt.nweo_flags >> 16) & 0xffff; new_en_flags= newopt.nweo_flags & 0xffff; new_di_flags= (newopt.nweo_flags >> 16) & 0xffff; if (new_en_flags & new_di_flags) { bf_afree(data); reply_thr_get (eth_fd, EBADMODE, TRUE); return NW_OK; } /* NWEO_ACC_MASK */ if (new_di_flags & NWEO_ACC_MASK) { bf_afree(data); reply_thr_get (eth_fd, EBADMODE, TRUE); return NW_OK; } /* you can't disable access modes */ if (!(new_en_flags & NWEO_ACC_MASK)) new_en_flags |= (old_en_flags & NWEO_ACC_MASK); /* NWEO_LOC_MASK */ if (!((new_en_flags | new_di_flags) & NWEO_LOC_MASK)) { new_en_flags |= (old_en_flags & NWEO_LOC_MASK); new_di_flags |= (old_di_flags & NWEO_LOC_MASK); } /* NWEO_BROAD_MASK */ if (!((new_en_flags | new_di_flags) & NWEO_BROAD_MASK)) { new_en_flags |= (old_en_flags & NWEO_BROAD_MASK); new_di_flags |= (old_di_flags & NWEO_BROAD_MASK); } /* NWEO_MULTI_MASK */ if (!((new_en_flags | new_di_flags) & NWEO_MULTI_MASK)) { new_en_flags |= (old_en_flags & NWEO_MULTI_MASK); new_di_flags |= (old_di_flags & NWEO_MULTI_MASK); newopt.nweo_multi= oldopt.nweo_multi; } /* NWEO_PROMISC_MASK */ if (!((new_en_flags | new_di_flags) & NWEO_PROMISC_MASK)) { new_en_flags |= (old_en_flags & NWEO_PROMISC_MASK); new_di_flags |= (old_di_flags & NWEO_PROMISC_MASK); } /* NWEO_REM_MASK */ if (!((new_en_flags | new_di_flags) & NWEO_REM_MASK)) { new_en_flags |= (old_en_flags & NWEO_REM_MASK); new_di_flags |= (old_di_flags & NWEO_REM_MASK); newopt.nweo_rem= oldopt.nweo_rem; } /* NWEO_TYPE_MASK */ if (!((new_en_flags | new_di_flags) & NWEO_TYPE_MASK)) { new_en_flags |= (old_en_flags & NWEO_TYPE_MASK); new_di_flags |= (old_di_flags & NWEO_TYPE_MASK); newopt.nweo_type= oldopt.nweo_type; } /* NWEO_RW_MASK */ if (!((new_en_flags | new_di_flags) & NWEO_RW_MASK)) { new_en_flags |= (old_en_flags & NWEO_RW_MASK); new_di_flags |= (old_di_flags & NWEO_RW_MASK); } newopt.nweo_flags= ((unsigned long)new_di_flags << 16) | new_en_flags; eth_fd->ef_ethopt= newopt; result= eth_checkopt(eth_fd); if (result<0) eth_fd->ef_ethopt= oldopt; else { unsigned long opt_flags; unsigned changes; opt_flags= oldopt.nweo_flags ^ eth_fd->ef_ethopt.nweo_flags; changes= ((opt_flags >> 16) | opt_flags) & 0xffff; if (changes & (NWEO_BROAD_MASK | NWEO_MULTI_MASK | NWEO_PROMISC_MASK)) { flags= NWEO_NOFLAGS; for (i=0, loc_fd= eth_fd_table; i<ETH_FD_NR; i++, loc_fd++) { if (!(loc_fd->ef_flags | ~(EFF_INUSE | EFF_OPTSET))) continue; if (loc_fd->ef_port != eth_port) continue; flags |= loc_fd->ef_ethopt. nweo_flags; } eth_set_rec_conf(eth_port, flags); } } bf_afree(data); reply_thr_get (eth_fd, result, TRUE); return NW_OK; } case NWIOGETHOPT & IOCTYPE_MASK: { nwio_ethopt_t *ethopt; acc_t *acc; int result; if (req != NWIOGETHOPT) break; acc= bf_memreq(sizeof(nwio_ethopt_t)); ethopt= (nwio_ethopt_t *)ptr2acc_data(acc); *ethopt= eth_fd->ef_ethopt; result= (*eth_fd->ef_put_userdata)(eth_fd-> ef_srfd, 0, acc, TRUE); if (result >= 0) reply_thr_put(eth_fd, NW_OK, TRUE); return result; } case NWIOGETHSTAT & IOCTYPE_MASK: { nwio_ethstat_t *ethstat; acc_t *acc; int result;assert (sizeof(nwio_ethstat_t) <= BUF_S); if (req != NWIOGETHSTAT) break; eth_port= eth_fd->ef_port; if (!(eth_port->etp_flags & EPF_ENABLED)) { reply_thr_put(eth_fd, EGENERIC, TRUE); return NW_OK; } acc= bf_memreq(sizeof(nwio_ethstat_t));compare (bf_bufsize(acc), ==, sizeof(*ethstat)); ethstat= (nwio_ethstat_t *)ptr2acc_data(acc); ethstat->nwes_addr= eth_port->etp_ethaddr; result= eth_get_stat(eth_port, ðstat->nwes_stat);assert (result == 0);#if DEBUG & 256 { where(); printf("returning NW_OK\n"); }#endifcompare (bf_bufsize(acc), ==, sizeof(*ethstat)); result= (*eth_fd->ef_put_userdata)(eth_fd-> ef_srfd, 0, acc, TRUE); if (result >= 0) reply_thr_put(eth_fd, NW_OK, TRUE); return result; } default: break; } reply_thr_put(eth_fd, EBADIOCTL, TRUE); return NW_OK;}PUBLIC int eth_write(fd, count)int fd;size_t count;{ eth_fd_t *eth_fd; eth_port_t *eth_port;#if DEBUG & 256 { where(); printf("eth_write (%d, ...)\n", fd); }#endif eth_fd= ð_fd_table[fd]; eth_port= eth_fd->ef_port; if (!(eth_fd->ef_flags & EFF_OPTSET)) { reply_thr_get (eth_fd, EBADMODE, FALSE); return NW_OK; } assert (!(eth_fd->ef_flags & EFF_WRITE_IP)); eth_fd->ef_write_count= count; if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY) count += ETH_HDR_SIZE; if (count<ETH_MIN_PACK_SIZE || count>ETH_MAX_PACK_SIZE) {#if DEBUG { where(); printf("illegal packetsize (%d)\n",count); }#endif reply_thr_get (eth_fd, EPACKSIZE, FALSE); return NW_OK; } eth_fd->ef_flags |= EFF_WRITE_IP; restart_write_fd(eth_fd); if (eth_fd->ef_flags & EFF_WRITE_IP) return NW_SUSPEND; else return NW_OK;}PUBLIC int eth_read (fd, count)int fd;size_t count;{ eth_fd_t *eth_fd; acc_t *acc, *acc2;#if DEBUG & 256 { where(); printf("eth_read (%d, ...)\n", fd); }#endif eth_fd= ð_fd_table[fd]; if (!(eth_fd->ef_flags & EFF_OPTSET)) { reply_thr_put(eth_fd, EBADMODE, FALSE); return NW_OK; } if (count < ETH_MAX_PACK_SIZE) { reply_thr_put(eth_fd, EPACKSIZE, FALSE); return NW_OK; } if (eth_fd->ef_rd_buf) { if (get_time() <= eth_fd->ef_exp_tim) return packet2user (eth_fd); for (acc= eth_fd->ef_rd_buf; acc;) { acc2= acc->acc_ext_link; bf_afree(acc); acc= acc2; } eth_fd->ef_rd_buf= 0; } eth_fd->ef_flags |= EFF_READ_IP;#if DEBUG & 256 { where(); printf("eth_fd_table[%d].ef_flags= 0x%x\n", eth_fd-eth_fd_table, eth_fd->ef_flags); }#endif return NW_SUSPEND;}PUBLIC int eth_cancel(fd, which_operation)int fd;int which_operation;{ eth_fd_t *eth_fd;#if DEBUG & 2 { where(); printf("eth_cancel (%d)\n", fd); }#endif eth_fd= ð_fd_table[fd]; switch (which_operation) { case SR_CANCEL_READ:assert (eth_fd->ef_flags & EFF_READ_IP); eth_fd->ef_flags &= ~EFF_READ_IP; reply_thr_put(eth_fd, EINTR, FALSE); break; case SR_CANCEL_WRITE:assert (eth_fd->ef_flags & EFF_WRITE_IP); eth_fd->ef_flags &= ~EFF_WRITE_IP; reply_thr_get(eth_fd, EINTR, FALSE); break; default: ip_panic(( "got unknown cancel request" )); } return NW_OK;}PUBLIC void eth_close(fd)int fd;{ eth_fd_t *eth_fd; acc_t *acc, *acc2;#if DEBUG { where(); printf("eth_close (%d)\n", fd); }#endif eth_fd= ð_fd_table[fd]; assert (eth_fd->ef_flags & EFF_INUSE); eth_fd->ef_flags= EFF_EMPTY; for (acc= eth_fd->ef_rd_buf; acc;) { acc2= acc->acc_ext_link; bf_afree(acc); acc= acc2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -