📄 inet.c
字号:
} if (!flags || opt->reuse) { opt->reuse = &opt_defaults.reuse; opt->flags |= TF_IP_REUSEADDR; } if (!flags || opt->norte) { opt->norte = &opt_defaults.norte; opt->flags |= TF_IP_DONTROUTE; } if (!flags || opt->bcast) { opt->bcast = &opt_defaults.bcast; opt->flags |= TF_IP_BROADCAST; } if (ss->p.prot.protocol == T_INET_TCP) { if (!flags || opt->nodly) { opt->nodly = &opt_defaults.nodly; opt->flags |= TF_TCP_NODELAY; } if (!flags || opt->mss) { opt->mss = &opt_defaults.mss; opt->flags |= TF_TCP_MAXSEG; } if (!flags || opt->alive) { opt->alive = &opt_defaults.alive; opt->flags |= TF_TCP_KEEPALIVE; } } if (ss->p.prot.protocol == T_INET_UDP) { if (!flags || opt->csum) { opt->csum = &opt_defaults.csum; opt->flags |= TF_UDP_CHECKSUM; } } return (0);}/* * NEGOTIATE Options * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */STATIC intss_opt_negotiate(ss_t * ss, ss_opts_t * opt){ struct sock *sk = NULL; if (ss->sock) sk = ss->sock->sk; if (opt) { opt->flags = 0; if (opt->opt) { ss->options.opt = *(opt->opt);#ifdef LINUX_2_4 if (sk) sk->protinfo.af_inet.opt = &ss->options.opt;#else if (sk) sk->opt = &ss->options.opt;#endif opt->flags |= TF_IP_OPTIONS; } if (opt->tos) { ss->options.tos = *(opt->tos);#ifdef LINUX_2_4 if (sk) sk->protinfo.af_inet.tos = ss->options.tos;#else if (sk) sk->ip_tos = ss->options.tos;#endif opt->flags |= TF_IP_TOS; } if (opt->ttl) { ss->options.ttl = *(opt->ttl);#ifdef LINUX_2_4 if (sk) sk->protinfo.af_inet.ttl = ss->options.ttl;#else if (sk) sk->ip_ttl = ss->options.ttl;#endif opt->flags |= TF_IP_TTL; } if (opt->reuse) { ss->options.reuse = *(opt->reuse) ? 1 : 0; if (sk) sk->reuse = ss->options.reuse; opt->flags |= TF_IP_REUSEADDR; } if (opt->norte) { ss->options.norte = *(opt->norte) ? 1 : 0; if (sk) sk->localroute = ss->options.norte; opt->flags |= TF_IP_DONTROUTE; } if (opt->bcast) { ss->options.bcast = *(opt->bcast) ? 1 : 0; if (sk) sk->broadcast = ss->options.bcast; opt->flags |= TF_IP_BROADCAST; } if (opt->nodly) { ss->options.nodly = *(opt->nodly) ? 1 : 0;#ifdef LINUX_2_4 if (sk) sk->tp_pinfo.af_tcp.nonagle = ss->options.nodly;#else if (sk) sk->nonagle = ss->options.nodly;#endif opt->flags |= TF_TCP_NODELAY; } if (opt->mss) { ss->options.mss = *(opt->mss) ? 1 : 0; if (sk) sk->tp_pinfo.af_tcp.user_mss = ss->options.mss; opt->flags |= TF_TCP_MAXSEG; } if (opt->alive) { ss->options.alive = *(opt->alive) ? 1 : 0; if (sk) sk->keepopen = ss->options.alive; opt->flags |= TF_TCP_KEEPALIVE; } if (opt->csum) { ss->options.csum = *(opt->csum) ? 1 : 0; // if ( sk ) sk->csum = ss->options.csum; opt->flags |= TF_UDP_CHECKSUM; } } return (0);}/* * CURRENT Options * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */STATIC intss_opt_current(ss_t * ss, ss_opts_t * opt){ uint flags = opt->flags; opt->flags = 0; if (!flags || opt->opt) { opt->opt = &ss->options.opt; opt->flags |= TF_IP_OPTIONS; } if (!flags || opt->tos) { opt->tos = &ss->options.tos; opt->flags |= TF_IP_TOS; } if (!flags || opt->ttl) { opt->ttl = &ss->options.ttl; opt->flags |= TF_IP_TTL; } if (!flags || opt->reuse) { opt->reuse = &ss->options.reuse; opt->flags |= TF_IP_REUSEADDR; } if (!flags || opt->norte) { opt->norte = &ss->options.norte; opt->flags |= TF_IP_DONTROUTE; } if (!flags || opt->bcast) { opt->bcast = &ss->options.bcast; opt->flags |= TF_IP_BROADCAST; } if (ss->p.prot.protocol == T_INET_TCP) { if (!flags || opt->nodly) { opt->nodly = &ss->options.nodly; opt->flags |= TF_TCP_NODELAY; } if (!flags || opt->mss) { opt->mss = &ss->options.mss; opt->flags |= TF_TCP_MAXSEG; } if (!flags || opt->alive) { opt->alive = &ss->options.alive; opt->flags |= TF_TCP_KEEPALIVE; } } if (ss->p.prot.protocol == T_INET_UDP) { if (!flags || opt->csum) { opt->csum = &ss->options.csum; opt->flags |= TF_UDP_CHECKSUM; } } return (0);}/* * ========================================================================= * * Address Handling * * ========================================================================= */STATIC intss_addr_size(ss_t * ss, struct sockaddr *add){ if (add) { switch (add->sa_family) { case AF_INET: return sizeof(struct sockaddr_in); case AF_UNIX: return sizeof(struct sockaddr_un); case AF_UNSPEC: return sizeof(add->sa_family); default: return sizeof(struct sockaddr); } } return (0);}/* * ========================================================================= * * STATE Changes * * ========================================================================= */#ifdef _DEBUGSTATIC const char *state_name(long state){ switch (state) { case TS_UNBND: return ("TS_UNBND"); case TS_WACK_BREQ: return ("TS_WACK_BREQ"); case TS_WACK_UREQ: return ("TS_WACK_UREQ"); case TS_IDLE: return ("TS_IDLE"); case TS_WACK_OPTREQ: return ("TS_WACK_OPTREQ"); case TS_WACK_CREQ: return ("TS_WACK_CREQ"); case TS_WCON_CREQ: return ("TS_WCON_CREQ"); case TS_WRES_CIND: return ("TS_WRES_CIND"); case TS_WACK_CRES: return ("TS_WACK_CRES"); case TS_DATA_XFER: return ("TS_DATA_XFER"); case TS_WIND_ORDREL: return ("TS_WIND_ORDREL"); case TS_WREQ_ORDREL: return ("TS_WREQ_ORDREL"); case TS_WACK_DREQ6: return ("TS_WACK_DREQ6"); case TS_WACK_DREQ7: return ("TS_WACK_DREQ7"); case TS_WACK_DREQ9: return ("TS_WACK_DREQ9"); case TS_WACK_DREQ10: return ("TS_WACK_DREQ10"); case TS_WACK_DREQ11: return ("TS_WACK_DREQ11"); case TS_NOSTATES: return ("TS_NOSTATES"); default: return ("(unknown)"); }}#endifSTATIC voidss_set_state(ss_t * ss, long state){ printd(("%s: %p: %s <- %s\n", SS_MOD_NAME, ss, state_name(state), state_name(ss->p.info.CURRENT_state))); ss->p.info.CURRENT_state = state;}STATIC longss_get_state(ss_t * ss){ return (ss->p.info.CURRENT_state);}#ifdef _DEBUGSTATIC const char *tcp_state_name(int state){ switch (state) { case TCP_ESTABLISHED: return ("TCP_ESTABLISHED"); case TCP_SYN_SENT: return ("TCP_SYN_SENT"); case TCP_SYN_RECV: return ("TCP_SYN_RECV"); case TCP_FIN_WAIT1: return ("TCP_FIN_WAIT1"); case TCP_FIN_WAIT2: return ("TCP_FIN_WAIT2"); case TCP_TIME_WAIT: return ("TCP_TIME_WAIT"); case TCP_CLOSE: return ("TCP_CLOSE"); case TCP_CLOSE_WAIT: return ("TCP_CLOSE_WAIT"); case TCP_LAST_ACK: return ("TCP_LAST_ACK"); case TCP_LISTEN: return ("TCP_LISTEN"); case TCP_CLOSING: return ("TCP_CLOSING"); case TCP_MAX_STATES: return ("TCP_MAX_STATES"); default: return ("(unknown)"); }}#endif/* * ------------------------------------------------------------------------ * * Socket Calls * * ------------------------------------------------------------------------ * These are wrappered versions of socket calls. *//* * SOCKET CREATE * ------------------------------------------------------------------------ */STATIC intss_socket(ss_t * ss){ int err; int family, type, protocol; ensure(ss, return (-EFAULT)); unless(ss->sock, return (-EFAULT)); family = ss->p.prot.family; type = ss->p.prot.type; protocol = (ss->p.prot.protocol == IPPROTO_RAW) ? ss->port : ss->p.prot.protocol; printd(("%s: %p: SS_CREATE %d:%d:%d\n", SS_MOD_NAME, ss, family, type, protocol)); if (!(err = sock_create(family, type, protocol, &ss->sock))) { ensure(ss->sock, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT)); ss->sock->sk->allocation = GFP_ATOMIC; ss_socket_get(ss->sock, ss); return (0); } printd(("%s: %p: ERROR: from sock_create %d\n", SS_MOD_NAME, ss, err)); return (err);}/* * SOCKET BIND * ------------------------------------------------------------------------ */STATIC intss_bind(ss_t * ss, struct sockaddr *add){ int err; ensure(ss, return (-EFAULT)); ensure(ss->sock, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT)); ensure(ss->sock->ops, return (-EFAULT)); ensure(ss->sock->ops->bind, return (-EFAULT)); printd(("%s: %p: SS_BIND\n", SS_MOD_NAME, ss)); if (!(err = ss->sock->ops->bind(ss->sock, add, sizeof(*add)))) { ss->src = *add; return (0); } printd(("%s: %p: ERROR: from sock->ops->bind %d\n", SS_MOD_NAME, ss, err)); return (err);}/* * SOCKET LISTEN * ------------------------------------------------------------------------ */STATIC intss_listen(ss_t * ss, uint cons){ int err; int type; ensure(ss, return (-EFAULT)); ensure(ss->sock, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT)); ensure(ss->sock->ops, return (-EFAULT)); ensure(ss->sock->ops->listen, return (-EFAULT)); type = ss->p.prot.type; ensure(type == SOCK_STREAM || type == SOCK_SEQPACKET, return (-EFAULT)); printd(("%s: %p: SS_LISTEN %d\n", SS_MOD_NAME, ss, cons)); if (!(err = ss->sock->ops->listen(ss->sock, cons))) { ss->conind = cons; ss->tcp_state = ss->sock->sk->state; return (0); } printd(("%s: %p: ERROR: from sock->ops->listen %d\n", SS_MOD_NAME, ss, err)); return (err);}/* * SOCKET ACCEPT * ------------------------------------------------------------------------ * Unfortunately, sock->ops->accept will only accept the next sequential * connection indication. In TLI's case, we want to be able to accept or * release connection indications other than the next sequential indication. * To do this we must muck with TCP's accept queue when the SEQ_number is not * the next in the queue. To do this we mimic some of the tcp_accept * behavior. */STATIC intss_accept(ss_t * ss, struct socket **newsock, mblk_t *cp){ struct socket *sock; ensure(newsock, return (-EFAULT)); ensure(cp, return (-EFAULT)); ensure(ss, return (-EFAULT)); ensure(ss->sock, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT)); ensure(ss->sock->ops, return (-EFAULT)); ensure(ss->sock->ops->accept, return (-EFAULT)); printd(("%s: %p: SS_ACCEPT\n", SS_MOD_NAME, ss)); if ((sock = sock_alloc())) { struct sock *sk = ss->sock->sk; struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; struct open_request *req, *req_prev, **reqp; struct sock *ask = ((ss_event_t *) cp->b_rptr)->sk; sock->type = ss->sock->type; sock->ops = ss->sock->ops; lock_sock(sk); if (tp->accept_queue) { /* find connection in queue */ for (reqp = &tp->accept_queue, req_prev = NULL; *reqp && (*reqp)->sk != ask; req_prev = (*reqp), reqp = &(*reqp)->dl_next) ; if ((req = *reqp)) { if (!((*reqp) = (*reqp)->dl_next)) tp->accept_queue_tail = req_prev; sk->ack_backlog--; tcp_openreq_fastfree(req); } release_sock(sk); lock_sock(ask); sock_graft(ask, sock); release_sock(ask); sock->state = SS_CONNECTED; *newsock = sock; bufq_unlink(&ss->conq, cp); freemsg(cp); return (0); } release_sock(sk); ss_socket_put(sock); printd(("%s: %p: invalid accept\n", SS_MOD_NAME, ss)); return (-EAGAIN); } printd(("%s: %p: ERROR: couldn't allocate accepting socket\n", SS_MOD_NAME, ss)); return (-EFAULT);}/* * SOCKET UNBIND * ------------------------------------------------------------------------ * There is no good way to unbind and rebind a socket in Linux, so we just * close the entire socket. The next time we go to bind, we will create * a fresh socket to bind. */STATIC intss_unbind(ss_t * ss){ ensure(ss, return (-EFAULT)); ensure(ss->sock, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT)); printd(("%s: %p: SS_UNBIND\n", SS_MOD_NAME, ss)); ss_socket_put(xchg(&ss->sock, NULL)); return (0);}/* * SOCKET CONNECT * ------------------------------------------------------------------------ */STATIC intss_connect(ss_t * ss, struct sockaddr *dst){ int err; ensure(ss, return (-EFAULT)); ensure(ss->sock, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -