📄 inet.c
字号:
ensure(ss->sock->ops, return (-EFAULT)); ensure(ss->sock->ops->connect, return (-EFAULT)); if ((err = ss->sock->ops->connect(ss->sock, dst, sizeof(*dst), O_NONBLOCK)) == 0 || err == -EINPROGRESS) { return (0); } printd(("%s: %p: ERROR: from sock->ops->connect %d\n", SS_MOD_NAME, ss, err)); return (err);}/* * SOCKET SENDMSG * ------------------------------------------------------------------------ */STATIC intss_sendmsg(ss_t * ss, struct msghdr *msg, int len){ int res; ensure(ss, return (-EFAULT)); ensure(ss->sock, return (-EFAULT)); ensure(ss->sock->ops, return (-EFAULT)); ensure(ss->sock->ops->sendmsg, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT)); ensure(ss->sock->sk->prot, return (-EFAULT)); ensure(ss->sock->sk->prot->sendmsg, return (-EFAULT)); { mm_segment_t fs = get_fs(); set_fs(KERNEL_DS); res = sock_sendmsg(ss->sock, msg, len); set_fs(fs); } if (res <= 0) printd(("%s: %p: ERROR: from sock->sk->prot->sendmsg %d\n", SS_MOD_NAME, ss, res)); return (res);}/* * SOCKET RECVMSG * ------------------------------------------------------------------------ */STATIC intss_recvmsg(ss_t * ss, struct msghdr *msg, int size){ int res; int sflags = MSG_DONTWAIT | MSG_NOSIGNAL; ensure(ss, return (-EFAULT)); ensure(ss->sock, return (-EFAULT)); ensure(ss->sock->ops, return (-EFAULT)); ensure(ss->sock->ops->recvmsg, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT)); ensure(ss->sock->sk->prot, return (-EFAULT)); ensure(ss->sock->sk->prot->recvmsg, return (-EFAULT)); { mm_segment_t fs = get_fs(); set_fs(KERNEL_DS); res = sock_recvmsg(ss->sock, msg, size, sflags); set_fs(fs); } if (res < 0) printd(("%s: %p: ERROR: from sock->ops->recvmsg %d\n", SS_MOD_NAME, ss, res)); return (res);}/* * SOCKET DISCONNECT * ------------------------------------------------------------------------ * Performing a sock_release (ss_socket_put) from the established state does * not affect an abortive release for TCP, but rather, initiates an orderly * shutdown rather than an abortive release. We can try performing a * protocol disconnect and see if that works better. */STATIC intss_disconnect(ss_t * ss){ int err; ensure(ss, return (-EFAULT)); ensure(ss->sock->ops, return (-EFAULT)); ensure(ss->sock->ops->connect, return (-EFAULT)); ensure(ss->sock->sk, return (-EFAULT)); ensure(ss->sock->sk->prot, return (-EFAULT)); ensure(ss->sock->sk->prot->disconnect, return (-EFAULT)); if (!(err = ss->sock->sk->prot->disconnect(ss->sock->sk, O_NONBLOCK))) { ss->sock->state = SS_UNCONNECTED; return (0); } ss->sock->state = SS_DISCONNECTING; printd(("%s: %p: ERROR: from sock->sk->prot->disconnect %d\n", SS_MOD_NAME, ss, err)); return (err);}/* * ========================================================================= * * IP T-Provider --> T-User Primitives (Indication, Confirmation and Ack) * * ========================================================================= *//* * M_ERROR * --------------------------------------------------------------- */STATIC intm_error(queue_t *q, int error){ ss_t *ss = PRIV(q); mblk_t *mp; int hangup = 0; if (error < 0) error = -error; switch (error) { case EBUSY: case ENOBUFS: case EAGAIN: case ENOMEM: return (-error); case EPIPE: case ENETDOWN: case EHOSTUNREACH: hangup = 1; } if ((mp = ss_allocb(q, 2, BPRI_HI))) { if (ss->sock) ss_socket_put(xchg(&ss->sock, NULL)); if (hangup) { printd(("%s: %p: <- M_HANGUP\n", SS_MOD_NAME, ss)); mp->b_datap->db_type = M_HANGUP; putnext(ss->rq, mp); error = EPIPE; } else { printd(("%s: %p: <- M_ERROR %d\n", SS_MOD_NAME, ss, error)); mp->b_datap->db_type = M_ERROR; *(mp->b_wptr)++ = error; *(mp->b_wptr)++ = error; putnext(ss->rq, mp); } return (-error); } rare(); return (-ENOBUFS);}/* * T_CONN_IND 11 - Connection Indication * --------------------------------------------------------------- */STATIC intt_conn_ind(queue_t *q, struct sockaddr *src, ss_opts_t * opts, mblk_t *cp){ ss_t *ss = PRIV(q); mblk_t *mp; struct T_conn_ind *p; size_t src_len = ss_addr_size(ss, src); size_t opt_len = ss_opts_size(ss, opts); if (bufq_length(&ss->conq) <= ss->conind) { if (canputnext(ss->rq)) { if ((mp = ss_allocb(q, sizeof(*p) + src_len + opt_len, BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((typeof(p)) mp->b_wptr)++; p->PRIM_type = T_CONN_IND; p->SRC_length = src_len; p->SRC_offset = src_len ? sizeof(*p) : 0; p->OPT_length = opt_len; p->OPT_offset = opt_len ? sizeof(*p) + src_len : 0; p->SEQ_number = (ulong) cp; if (src_len) { bcopy(src, mp->b_wptr, src_len); mp->b_wptr += src_len; } if (opt_len) { ss_build_opts(ss, opts, &mp->b_wptr); } bufq_queue(&ss->conq, cp); ss_set_state(ss, TS_WRES_CIND); printd(("%s: %p: <- T_CONN_IND\n", SS_MOD_NAME, ss)); putnext(ss->rq, mp); return (QR_ABSORBED); /* absorbed cp */ } ptrace(("%s: ERROR: no buffers\n", SS_MOD_NAME)); return (-ENOBUFS); } ptrace(("%s: ERROR: flow controlled\n", SS_MOD_NAME)); return (-EBUSY); } ptrace(("%s: ERROR: too many conn inds\n", SS_MOD_NAME)); return (-EAGAIN);}/* * T_CONN_CON 12 - Connection Confirmation * --------------------------------------------------------------- */STATIC intt_conn_con(queue_t *q, struct sockaddr *res, ss_opts_t * opts, mblk_t *dp){ ss_t *ss = PRIV(q); mblk_t *mp; struct T_conn_con *p; size_t res_len = ss_addr_size(ss, res); size_t opt_len = ss_opts_size(ss, opts); /* * this shouldn't happen, we probably shouldn't even check */ if (canputnext(ss->rq)) { if ((mp = ss_allocb(q, sizeof(*p) + res_len + opt_len, BPRI_MED))) { mp->b_datap->db_type = M_PROTO; mp->b_band = 1; /* expedite */ p = ((typeof(p)) mp->b_wptr)++; p->PRIM_type = T_CONN_CON; p->RES_length = res_len; p->RES_offset = res_len ? sizeof(*p) : 0; p->OPT_length = opt_len; p->OPT_offset = opt_len ? sizeof(*p) + res_len : 0; if (res_len) { bcopy(res, mp->b_wptr, res_len); mp->b_wptr += res_len; } if (opt_len) { ss_build_opts(ss, opts, &mp->b_wptr); } ss_set_state(ss, TS_DATA_XFER); printd(("%s: %p: <- T_CONN_CON\n", SS_MOD_NAME, ss)); putnext(ss->rq, mp); return (0); } ptrace(("%s: ERROR: no buffers\n", SS_MOD_NAME)); return (-ENOBUFS); } ptrace(("%s: ERROR: flow controlled\n", SS_MOD_NAME)); return (-EBUSY);}/* * T_DISCON_IND 13 - Disconnect Indication * --------------------------------------------------------------- */STATIC mblk_t *t_seq_find(ss_t * ss, mblk_t *rp){ mblk_t *mp; if ((mp = rp)) { struct sock *sk = ((ss_event_t *) rp->b_rptr)->sk; lis_spin_lock(&ss->conq.q_lock); { for (mp = bufq_head(&ss->conq); mp && ((ss_event_t *) mp->b_rptr)->sk != sk; mp = mp->b_next) ; } lis_spin_unlock(&ss->conq.q_lock); } return (mp);}STATIC ulongt_seq_delete(ss_t * ss, mblk_t *rp){ mblk_t *mp; if ((mp = t_seq_find(ss, rp))) { struct socket *sock = NULL; if (!ss_accept(ss, &sock, rp) && sock) sock_release(sock); return ((ulong) mp); } return (0);}STATIC intt_discon_ind(queue_t *q, struct sockaddr *res, uint orig, uint reason, mblk_t *cp, mblk_t *dp){ ss_t *ss = PRIV(q); mblk_t *mp; struct T_discon_ind *p; ulong seq = 0; (void) res; if (canputnext(ss->rq)) { if ((mp = ss_allocb(q, sizeof(*p), BPRI_MED))) { if (!cp || (seq = t_seq_delete(ss, cp))) { mp->b_datap->db_type = M_PROTO; p = ((typeof(p)) mp->b_wptr)++; p->PRIM_type = T_DISCON_IND; p->DISCON_reason = reason; p->SEQ_number = seq; if (!bufq_length(&ss->conq)) ss_set_state(ss, TS_IDLE); else ss_set_state(ss, TS_WRES_CIND); mp->b_cont = dp; printd(("%s: %p: <- T_DISCON_IND\n", SS_MOD_NAME, ss)); putnext(ss->rq, mp); return (0); } freemsg(mp); ptrace(("%s: ERROR: bad sequence number\n", SS_MOD_NAME)); return (-EFAULT); } ptrace(("%s: ERROR: no buffers\n", SS_MOD_NAME)); return (-ENOBUFS); } ptrace(("%s: ERROR: flow controlled\n", SS_MOD_NAME)); return (-EBUSY);}/* * T_DATA_IND 14 - Data Indication * --------------------------------------------------------------- */STATIC intt_data_ind(queue_t *q, uint flags, mblk_t *dp){ ss_t *ss = PRIV(q); mblk_t *mp; struct T_data_ind *p; if ((mp = ss_allocb(q, sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((typeof(p)) mp->b_wptr)++; p->PRIM_type = T_DATA_IND; p->MORE_flag = flags; mp->b_cont = dp; printd(("%s: %p: <- T_DATA_IND\n", SS_MOD_NAME, ss)); putnext(ss->rq, mp); return (QR_ABSORBED); } ptrace(("%s: ERROR: no buffers\n", SS_MOD_NAME)); return (-ENOBUFS);}/* * T_EXDATA_IND 15 - Expedited Data Indication * --------------------------------------------------------------- */STATIC intt_exdata_ind(queue_t *q, uint flags, mblk_t *dp){ ss_t *ss = PRIV(q); mblk_t *mp; struct T_exdata_ind *p; if ((mp = ss_allocb(q, sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; mp->b_band = 1; /* expedite */ p = ((typeof(p)) mp->b_wptr)++; p->PRIM_type = T_EXDATA_IND; p->MORE_flag = flags; mp->b_cont = dp; printd(("%s: %p: <- T_EXDATA_IND\n", SS_MOD_NAME, ss)); putnext(ss->rq, mp); return (QR_ABSORBED); } ptrace(("%s: ERROR: no buffers\n", SS_MOD_NAME)); return (-ENOBUFS);}/* * T_INFO_ACK 16 - Information acknowledgement * --------------------------------------------------------------- */STATIC intt_info_ack(queue_t *q){ ss_t *ss = PRIV(q); mblk_t *mp; struct T_info_ack *p; if ((mp = ss_allocb(q, sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PCPROTO; p = ((typeof(p)) mp->b_wptr)++; *p = ss->p.info; printd(("%s: %p: <- T_INFO_ACK\n", SS_MOD_NAME, ss)); putnext(ss->rq, mp); return (0); } ptrace(("%s: ERROR: No buffers\n", SS_MOD_NAME)); return (-ENOBUFS);}/* * T_BIND_ACK 17 - Bind Acknowledgement * --------------------------------------------------------------- */STATIC intt_bind_ack(queue_t *q, struct sockaddr *add, ulong conind){ ss_t *ss = PRIV(q); mblk_t *mp; struct T_bind_ack *p; size_t add_len = ss_addr_size(ss, add); if ((mp = ss_allocb(q, sizeof(*p) + add_len, BPRI_MED))) { mp->b_datap->db_type = M_PCPROTO; p = ((typeof(p)) mp->b_wptr)++; p->PRIM_type = T_BIND_ACK; p->ADDR_length = add_len; p->ADDR_offset = add_len ? sizeof(*p) : 0; p->CONIND_number = conind; if (add_len) { bcopy(add, mp->b_wptr, add_len); mp->b_wptr += add_len; } ss_set_state(ss, TS_IDLE); printd(("%s: %p: <- T_BIND_ACK\n", SS_MOD_NAME, ss)); putnext(ss->rq, mp); return (0); } ptrace(("%s: ERROR: No buffers\n", SS_MOD_NAME)); return (-ENOBUFS);}/* * T_ERROR_ACK 18 - Error Acknowledgement * ------------------------------------------------------------------------- */STATIC intt_error_ack(queue_t *q, ulong prim, long error){ ss_t *ss = PRIV(q); mblk_t *mp; struct T_error_ack *p; switch (error) { case -EBUSY: case -EAGAIN: case -ENOMEM: case -ENOBUFS: seldom(); return (error); case 0: never(); return (error); } if (!(mp = ss_allocb(q, sizeof(*p), BPRI_MED))) goto enobufs; mp->b_datap->db_type = M_PCPROTO; p = ((typeof(p)) mp->b_wptr)++; p->PRIM_type = T_ERROR_ACK; p->ERROR_prim = prim; p->TLI_error = error < 0 ? TSYSERR : error; p->UNIX_error = error < 0 ? -error : 0; /* * This is to only try and get the state correct for putnext. */ if (error != TOUTSTATE) { switch (ss_get_state(ss)) {#ifdef TS_WACK_OPTREQ case TS_WACK_OPTREQ: ss_set_state(ss, TS_IDLE); break;#endif case TS_WACK_UREQ: ss_set_state(ss, TS_IDLE); break; case TS_WACK_CREQ: ss_set_state(ss, TS_IDLE); break; case TS_WACK_BREQ: ss_set_state(ss, TS_UNBND); break; case TS_WACK_CRES: ss_set_state(ss, TS_WRES_CIND); break; case TS_WACK_DREQ6: ss_set_state(ss, TS_WCON_CREQ); break; case TS_WACK_DREQ7: ss_set_state(ss, TS_WRES_CIND); break; case TS_WACK_DREQ9: ss_set_state(ss, TS_DATA_XFER); break; case TS_WACK_DREQ10: ss_set_state(ss, TS_WIND_ORDREL); break; case TS_WACK_DREQ11: ss_set_state(ss, TS_WREQ_ORDREL); break; /* * Note: if we are not in a WACK state we simply do * not change state. This occurs normally when we * are responding to a T_OPTMGMT_REQ in other than * TS_IDLE state. */ } } printd(("%s: %p: <- T_ERROR_ACK\n", SS_MOD_NAME, ss)); putnext(ss->rq, mp); /* * Returning -EPROTO here will make sure that the old state is * restored correctl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -