📄 m2pa.c
字号:
freemsg(tp); putnext(q, mp); return(0); case TS_WACK_OPTREQ: /* bad doo doo */ return(-EPROTO); case TS_WACK_DREQ6: case TS_WACK_DREQ7: case TS_WACK_DREQ9: case TS_WACK_DREQ10: case TS_WACK_DREQ11: /* these are all bad */ return(-EPROTO); } return(-EPROTO);}/* * T_CONN_IND * * SCTP has given us a connection indication. Even though we might not set * the CONIND_number to a positive integer (we set it to zero), we may still * receive a T_CONN_IND if the SCTP association has restarted. We should * take appropriate action depending on what we think the state of the * association is: if we are waiting to connect we should accept the * connection with a T_CONN_RES with the current stream, or we should refuse * the request with a T_DISCON_REQ. */static int t_conn_ind(queue_t *q, mblk_t *tp){ mblk_t *mp; m2pa_t *m2 = M2PA_PRIV(q); struct T_conn_ind *p = (struct T_conn_ind *)mp->b_rptr; if ( m2->m_state == LMI_ENABLE_PENDING ) { /* * check if this is our guy, if it isn't reject the * connection. careful: watch for restart conditions, * dual siezures for peer operation. */ } /* * try to reject the connection indication, we don't want * to connect until we are enabled. */}/* * T_CONN_CON * * SCTP has informed us that our connection request was successful. We * should inform the M2PA user and get ready to transfer data. */static int t_conn_con(m2pa_t *m2, mblk_t *mp){ if ( m2->t_state == TS_WCON_CREQ ) { struct T_conn_con *p = (struct T_conn_con *)mp->b_wptr; /* * TODO: check for 2 streams inbound only. */ switch ( m2->state ) { case M2PA_AIP: m2->state = M2PA_INS_LOCAL; m2->t_state = TS_DATA_XFER; /* * TODO: Get SRTT report. */ if ( mp->b_cont ) m2pa_recv_data(mp->b_cont); if ( srtt <= m2->srtt_max ) { if ( m2pa_send_in_service(m2) == -ENOBUFS ) return -EAGAIN; } else { m2->failure_reason = FIXME; t_discon_req(m2); m2->t_state = TS_WACK_DREQ9; sl_out_of_service(m2); m2->state = M2PA_OOS; } break; default: case M2PA_IDLE: case M2PA_OOS: case M2PA_RETRIEVAL: case M2PA_INS_LOCAL: case M2PA_INS: break; } } freemsg(mp); return(0);}/* * T_DATA_IND * * SCTP has given us data on STREAM 0. This is a control channel for M2PA, * so we should process these messages as control messages. */static int t_data_ind(m2pa_t *m2, mblk_t *mp){ struct T_data_ind *p; ptrace(("Unexpected primitive received from T-Provider\n")); (void)m2; (void)mp; return(-EPROTO);}/* * T_EXDATA_IND * * SCTP has given us out-of-order data on STREAM 0. This is a control * channel for M2PA so we should process these messages as control messages. */static int t_exdata_ind(m2pa_t *m2, mblk_t *mp){ struct T_exdata_ind *p; ptrace(("Unexpected primitive received from T-Provider\n")); (void)m2; (void)mp; return(-EPROTO);}/* * T_OPTDATA_IND * * SCTP has given us data on a specific SCTP-stream. We should process this * message for the SCTP-stream indicated. */static int t_optdata_ind(m2pa_t *m2, mblk_t *mp){ struct T_optdata_ind *p; ptrace(("Unexpected primitive received from T-Provider\n")); (void)m2; (void)mp; return(-EPROTO);}/* * T_OPTDATA_CON (Not in XTI/TLI) * * SCTP has given us an indication that an outstanding data message with * given user and provider/peer token values has been acknowledged received * by the peer. We can strike this message from our retrieval buffers. */static int t_optdata_con(m2pa_t *m2, mblk_t *mp){ struct T_optdata_con *p = (T_optdata_con *)mp->b_rptr; mblk_t *dp = (mblk_t *)p->TOKEN_value; mblk_t *bp = m2->txq.q_head; /* little check just to be sure that it is in the bufq */ for ( ; bp && bp != dp; bp = bp->next ); if ( bp != dp ) return (-EPROTO); bufq_unlink(&m2->txq, dp); m2pa_recalc_congestion(m2); freemsg(mp); return(0); ptrace(("Unexpected primitive received from T-Provider\n")); (void)m2; (void)mp; return(-EPROTO);}/* * T_DISCON_IND * * We treat disconnection indications like equipment failure. It changes the * management state of the interface and management is informed so that the * signalling link might be removed from service or another SDT/SDL assigned. * We do not attempt to automatically restore the connection. We wait for * management direction or another start indication. */static int t_discon_ind(queue_t *q, mblk_t *tp){ mblk_t *mp; m2pa_t *m2 = M2PA_PRIV(q); struct T_discon_ind *p = (struct T_discon_ind *)tp->b_wptr; const int reason = t_to_sl_reason(p->DISCON_reason); if ( !(mp = sl_out_of_service_ind(reason)) ) return -EAGAIN; putnext(q, mp); if ( !(mp = lmi_error_ind(LMI_DISC, 0, LMI_DISABLED)) ) return -EAGAIN; putnext(q, mp); m2-> state = SL_OUT_OF_SERVICE; m2->m_state = LMI_DISABLED; m2->t_state = TS_IDLE; freemsg(tp); return(0);}/* * T_ORDREL_IND * * We have received an orderly release indication from the peer. This is * peculiar if we are not expecting it. */static int t_ordrel_ind(queue_t *q, mblk_t *tp){ mblk_t *mp; m2pa_t *m2 = M2PA_PRIV(q); struct T_ordrel_ind *p = (struct T_ordrel_ind *)tp->b_rptr; if ( !(mp = sl_out_of_service_ind(FIXME)) ) return -EAGAIN; putnext(q, mp); if ( !(mp = lmi_error_ind(LMI_DISC, 0, LMI_DISABLED)) ) return -EAGAIN; putnext(q, mp); m2-> state = SL_OUT_OF_SERVICE; m2->m_state = LMI_DISABLED; m2->t_state = TS_IDLE; freemsg(tp); return(0);}/* * T_UNITDATA_IND * * SCTP should not send us this message; however, we might want to use other * transports for M2PA, so we process this message as well as possible. */static int t_unitdata_ind(m2pa_t *m2, mblk_t *mp){ struct T_unitdata_ind *p; ptrace(("Unexpected primitive received from T-Provider\n")); (void)m2; (void)mp; return(-EPROTO);}/* * SCTP should not send us this message; however, we might want to use other * transports for M2PA, so we process this message as well as possible. */static int t_uderror_ind(m2pa_t *m2, mblk_t *mp){ struct T_uderror_ind *p; ptrace(("Unexpected primitive received from T-Provider\n")); (void)m2; (void)mp; return(-EPROTO);}/* * ========================================================================= * * M2PA IOCTLs * * ========================================================================= *//* * ========================================================================= * * Message Handling * * ========================================================================= * * M_DATA Handling * * ------------------------------------------------------------------------- * * M_DATA messages are data messages which are passed between protocol * modules or between protocol modules and users. * */static inline intm2pa_w_data(queue_t *q, mblk_t *mp){ m2pa_t *m2 = M2PA_PRIV(q); return m2pa_send_data(m2, mp);}static inline intm2pa_r_data(queue_t *q, mblk_t *mp){ m2pa_t *m2 = M2PA_PRIV(q); return m2pa_recv_data(m2, mp);}/* * ------------------------------------------------------------------------- * * M_PROTO Handling * * ------------------------------------------------------------------------- * * M_PROTO message are normal protocol messages which are passed between * protocol modules or between protocol modules and users. */static inline intm2pa_w_proto(queue_t *q, mblk_t *mp){ switch ( ((union M2PA_primitives *)(mp->b_rptr))->type ) { case SL_PDU_REQ: return sl_pdu_req(q, mp); case SL_START_REQ: return sl_start_req(q, mp); case SL_STOP_REQ: return sl_stop_req(q, mp); case SL_POWER_ON_REQ: return sl_power_on_req(q, mp); } return(-EOPNOTSUPP);}static inline intm2pa_r_proto(queue_t *q, mblk_t *mp){ switch ( ((union T_primitives *)(mp->b_rptr))->type ) { case T_DATA_IND: return t_data_ind(q, mp); case T_EXDATA_IND: return t_exdata_ind(q, mp); case T_OPTDATA_IND: return t_optdata_ind(q, mp); case T_CONN_IND: return t_conn_ind(q, mp); case T_CONN_CON: return t_conn_con(q, mp); case T_DISCON_IND: return t_discon_ind(q, mp); case T_ORDREL_IND: return t_ordrel_ind(q, mp); case T_UNITDATA_IND: return t_unitdata_ind(q, mp); case T_UDERROR_IND: return t_uderror_ind(q, mp); } return(-EOPNOTSUPP);}/* * ------------------------------------------------------------------------- * * M_PCPROTO Handling * * ------------------------------------------------------------------------- * * M_PCPROTO messages are priority protocol messages which are passed between * protocol modules or between protocol modules and users. */static inline intm2pa_w_pcproto(queue_t *q, mblk_t *mp){ switch ( ((union M2PA_primitives *)(mp->b_rptr))->type ) { case SL_EMERGENCY_REQ: return sl_emergency_req(q, mp); case SL_EMERGENCY_CEASES_REQ: return sl_emergency_ceases_req(q, mp); case SL_RETRIEVE_BSNT_REQ: return sl_retrieve_bsnt_req(q, mp); case SL_RETRIEVAL_REQUEST_AND_FSNC_REQ: return sl_retrieval_request_and_fsnc_req(q, mp); case SL_CLEAR_BUFFERS_REQ: return sl_clear_buffers_req(q, mp); case SL_CLEAR_RTB_REQ: return sl_clear_rtb_req(q, mp); case SL_LOCAL_PROCESSOR_OUTAGE_REQ: return sl_local_processor_outage_req(q, mp); case SL_RESUME_REQ: return sl_resume_req(q, mp); case SL_CONGESTION_DISCARD_REQ: return sl_congestion_discard_req(q, mp); case SL_CONGESTION_ACCEPT_REQ: return sl_congestion_accept_req(q, mp); case SL_NO_CONGESTION_REQ: return sl_no_congestion_req(q, mp); case SL_POWER_ON_REQ: return sl_power_on_req(q, mp); case SL_OPTMGMT_REQ: return sl_optmgmt_req(q, mp); case SL_NOTIFY_REQ: return sl_notify_req(q, mp); case LMI_INFO_REQ: return lmi_info_req(q, mp); case LMI_ATTACH_REQ: return lmi_attach_req(q, mp); case LMI_DETACH_REQ: return lmi_detach_req(q, mp); case LMI_ENABLE_REQ: return lmi_enable_req(q, mp); case LMI_DISABLE_REQ: return lmi_disable_req(q, mp); case LMI_OPTMGMT_REQ: return lmi_optmgmt_req(q, mp); } return(-EOPNOTSUPP);}static inline intm2pa_r_pcproto(queue_t *q, mblk_t *mp){ switch ( ((union T_primitives *)(mp->b_rptr))->type ) { case T_INFO_ACK: return t_info_ack(q, mp); case T_OPTMGMT_ACK: return t_optmgmt_ack(q, mp); case T_BIND_ACK: return t_bind_ack(q, mp); case T_OK_ACK: return t_ok_ack(q, mp); case T_ERROR_ACK: return t_error_ack(q, mp); case T_ADDR_ACK: return t_addr_ack(q, mp); /* new primitives for M2PA support */ case T_OPTDATA_CON: return t_optdata_con(q, mp); } return(-EOPNOTSUPP);}/* * ------------------------------------------------------------------------- * * M_CTL Handling * * ------------------------------------------------------------------------- * * M_CTL messages are used to pass control messages between protocol modules * (not to or from user space). */static inline intm2pa_w_ctl(queue_t *q, mblk_t *mp){ switch ( ((union M2PA_controls *)(mp->b_wptr))->type ) { case M2PA_CTL_XXXX: return m2pa_ctl_xxxx(q, mp); } return(-EOPNOTSUPP);}static inline intm2pa_r_ctl(queue_t *q, mblk_t *mp){ switch ( ((union M2PA_controls *)(mp->b_wptr))->type ) { case T_CTL_XXXX: return t_ctl_xxxx(q, mp); } return(-EOPNOTSUPP);}/* * ------------------------------------------------------------------------- * * M_IOCTL Handling * * ------------------------------------------------------------------------- */static inline intm2pa_do_ioctl(queue_t *q, int cmd, void *arg){ int nr = _IOC_NR(cmd); (void)nr; if ( _IOC_TYPE(cmd) == M2PA_IOC_MAGIC ) switch ( cmd ) { case M2PA_IOCXXXXX: return m2pa_iocxxxx(q, cmd, arg); case M2PA_IOCXXXXX: return m2pa_iocxxxx(q, cmd, arg); case M2PA_IOCXXXXX: return m2pa_iocxxxx(q, cmd, arg); case M2PA_IOCXXXXX: return m2pa_iocxxxx(q, cmd, arg); } return -ENXIO;}static inline intm2pa_w_ioctl(queue_t *q, mblk_t *mp){ struct iocblk *iocp = (struct iocblk *)mp->b_rptr; void *arg = mp->b_cont?mp->b_cont->b_rptr:NULL; int cmd = iocp->ioc_cmd, count = iocp->ioc_count; int ret = -EINVAL; struct linkblk *lp = (struct linkblk *)arg; switch ( cmd ) { case I_STR: if ( count >= _IOC_SIZE(cmd) ) { ret = m2pa_do_ioctl(q, cmd, arg); } if ( ret == -ENXIO ) { if ( q->q_next ) { putnext(q, mp); return(0); } } break; default: case I_LINK: case I_PLINK: case I_UNLINK: case I_PUNLINK: ret = -EINVAL; break; } if ( ret == 0 ) { mp->b_datap->db_type = M_IOCACK; iocp->ioc_error = 0; iocp->ioc_rval = 0; } else { mp->b_datap->db_type = M_IOCNAK; iocp->ioc_error = -ret; iocp->ioc_rval = -1; } qreply(q, mp); return(0);}/* * ------------------------------------------------------------------------- * * M_FLUSH Handling * * ------------------------------------------------------------------------- */static inline voidm2pa_w_flush(queue_t *q, mblk_t *mp){ if ( *mp->b_rptr & FLUSHW ) { flushq(q, FLUSHALL); if ( q->q_next ) { putnext(q, mp); return; } *mp->b_rptr &= ~FLUSHW; } if ( *mp->b_rptr & FLUSHR ) { flushq(RD(q), FLUSHALL); qreply(q, mp); return; } if ( q->q_next) { putnext(q, mp); return; }}/* * ------------------------------------------------------------------------- * * M_ERROR Handling * * ------------------------------------------------------------------------- */static inline voidm2pa_r_error(queue_t *q, mblk_t *mp){ m2pa_t *m2 = M2PA_PRIV(q); m2pa->state = M2PA_MERROR; if ( q->q_next ) { putne
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -