📄 sctp_n.c
字号:
q->throttle = sp->throttle; q->max_sack = sp->max_sack; q->rto_ini = sp->rto_ini; q->rto_min = sp->rto_min; q->rto_max = sp->rto_max; q->rtx_path = sp->rtx_path; q->hb_itvl = sp->hb_itvl; mp->b_wptr += sizeof(*q); r = (N_qos_range_info_sctp_t *)mp->b_wptr; r->n_qos_type = N_QOS_RANGE_INFO_SCTP; mp->b_wptr += sizeof(*r); *((uint32_t *)mp->b_wptr)++ = sp->ppi; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * N_BIND_ACK 17 - NS User bound to network address * --------------------------------------------------------------- */static int n_bind_ack(sctp_t *sp){ mblk_t *mp; N_bind_ack_t *p; sctp_saddr_t *ss = sp->saddr; size_t add_len = sp->sanum?sizeof(sp->sport)+sp->sanum*sizeof(ss->saddr):0; size_t pro_len = sizeof(sp->ppi); if ( (mp = allocb(sizeof(*p)+add_len+pro_len, BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = (N_bind_ack_t *)mp->b_wptr; p->PRIM_type = N_BIND_ACK; p->ADDR_length = add_len; p->ADDR_offset = add_len?sizeof(*p):0; p->CONIND_number = sp->conind; p->TOKEN_value = (ulong)sp->rq; p->PROTOID_length = pro_len; p->PROTOID_offset = pro_len?sizeof(*p)+add_len:0; mp->b_wptr += sizeof(*p); if ( ss ) *((typeof(sp->sport) *)mp->b_wptr)++ = sp->sport; for ( ; ss; ss = ss->next ) *((typeof(ss->saddr) *)mp->b_wptr)++ = ss->saddr; *((typeof(sp->ppi) *)mp->b_wptr)++ = sp->ppi; sp->i_state = NS_IDLE; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * N_ERROR_ACK 18 - Error Acknowledgement * --------------------------------------------------------------- */static int n_error_ack(sctp_t *sp, int prim, int err){ mblk_t *mp; N_error_ack_t *p; switch ( err ) { case -EBUSY: case -EAGAIN: case -ENOMEM: case -ENOBUFS: seldom(); return(err); case 0: never(); return (err); } if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = (N_error_ack_t *)mp->b_wptr; p->PRIM_type = N_ERROR_ACK; p->ERROR_prim = prim; p->NPI_error = err<0 ? NSYSERR : err; p->UNIX_error = err<0 ? -err : 0; mp->b_wptr += sizeof(*p); switch ( sp->i_state ) { case NS_WACK_OPTREQ: case NS_WACK_UREQ: case NS_WCON_CREQ: sp->i_state = NS_IDLE; break; case NS_WCON_RREQ: sp->i_state = NS_DATA_XFER; break; case NS_WACK_BREQ: sp->i_state = NS_UNBND; break; case NS_WACK_CRES: sp->i_state = NS_WRES_CIND; break; case NS_WACK_DREQ6: sp->i_state = NS_WCON_CREQ; break; case NS_WACK_DREQ7: sp->i_state = NS_WRES_CIND; break; case NS_WACK_DREQ9: sp->i_state = NS_DATA_XFER; break; case NS_WACK_DREQ10: sp->i_state = NS_WCON_RREQ; break; case NS_WACK_DREQ11: sp->i_state = NS_WRES_RIND; break; /* * Note: if we are not in a WACK state we simply do * not change state. This occurs normally when we * send NOUTSTATE or NNOTSUPPORT or are responding * to an N_OPTMGMT_REQ in other than the NS_IDLE * state. */ } putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * N_OK_ACK 19 - Success Acknowledgement * --------------------------------------------------------------- */static int n_ok_ack(sctp_t *sp, ulong prim, ulong seq, ulong tok){ mblk_t *mp; N_ok_ack_t *p; if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = (N_ok_ack_t *)mp->b_wptr; p->PRIM_type = N_OK_ACK; p->CORRECT_prim = prim; mp->b_wptr += sizeof(*p); switch ( sp->i_state ) { case NS_WACK_OPTREQ: sp->i_state = NS_IDLE; break; case NS_WACK_RRES: sp->i_state = NS_DATA_XFER; break; case NS_WACK_UREQ: sp->i_state = NS_UNBND; break; case NS_WACK_CRES: { queue_t *aq = (queue_t *)tok; sctp_t *ap = (sctp_t *)aq->q_ptr; if ( ap ) { ap->i_state = NS_DATA_XFER; sctp_cleanup_read(sp); /* deliver to user what is possible */ sctp_transmit_wakeup(ap); /* reply to peer what is necessary */ } if ( seq ) { bufq_unlink(&sp->conq, (mblk_t *)seq); freemsg((mblk_t *)seq); } if ( aq != sp->rq ) { if ( bufq_length(&sp->conq) ) sp->i_state = NS_WRES_CIND; else sp->i_state = NS_IDLE; } break; } case NS_WACK_DREQ7: if ( seq ) bufq_unlink(&sp->conq, (mblk_t *)seq); case NS_WACK_DREQ6: case NS_WACK_DREQ9: case NS_WACK_DREQ10: case NS_WACK_DREQ11: if ( bufq_length(&sp->conq) ) sp->i_state = NS_WRES_CIND; else sp->i_state = NS_IDLE; break; /* * Note: if we are not in a WACK state we simply do * not change state. This occurs normally when we * are responding to an N_OPTMGMT_REQ in other than * the NS_IDLE state. */ } putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * N_DATACK_IND 24 - Data acknowledgement indication * --------------------------------------------------------------- */static int n_datack_ind(sctp_t *sp, uint32_t ppi, uint16_t sid, uint16_t ssn, uint32_t tsn){ mblk_t *mp; N_datack_ind_t *p; N_qos_sel_data_sctp_t *q; ensure( ((1<<sp->i_state) & (NSF_DATA_XFER)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p)+sizeof(*q), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = (N_datack_ind_t *)mp->b_wptr; p->PRIM_type = N_DATACK_IND; mp->b_wptr += sizeof(*p); q = (N_qos_sel_data_sctp_t *)mp->b_wptr; q->n_qos_type = N_QOS_SEL_DATA_SCTP; q->ppi = ppi; q->sid = sid; q->ssn = ssn; q->tsn = tsn; q->more = 0; mp->b_wptr += sizeof(*q); putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * N_RESET_IND 26 - Inccoming NC reset request indication * --------------------------------------------------------------- */static int n_reset_ind(sctp_t *sp, ulong orig, ulong reason, mblk_t *cp){ mblk_t *mp; N_reset_ind_t *p; ensure( ((1<<sp->i_state) & (NSF_DATA_XFER)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = (N_reset_ind_t *)mp->b_wptr; p->PRIM_type = N_RESET_IND; p->RESET_orig = orig; p->RESET_reason = reason; mp->b_wptr += sizeof(*p); bufq_queue(&sp->conq, cp); sp->i_state = NS_WRES_RIND; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * N_RESET_CON 28 - Reset processing complete * --------------------------------------------------------------- */static int n_reset_con(sctp_t *sp){ mblk_t *mp; N_reset_con_t *p; ensure( ((1<<sp->i_state) & (NSF_WCON_RREQ)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = (N_reset_con_t *)mp->b_wptr; p->PRIM_type = N_RESET_CON; mp->b_wptr += sizeof(*p); sp->i_state = NS_DATA_XFER; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}#if 0/* * N_RECOVER_IND 29 - NC Recovery indication * --------------------------------------------------------------- */static int n_recover_ind(void){ mblk_t *mp; N_recover_ind_t *p; if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = (N_recover_ind_t *)mp->b_wptr; p->PRIM_type = N_RECOVER_IND; mp->b_wptr += sizeof(*p); sp->i_state = NS_DATA_XFER; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * N_RETRIEVE_IND 32 - NC Retrieval indication * --------------------------------------------------------------- */static mblk_t *n_retrieve_ind(mblk_t *dp){ mblk_t *mp; N_retrieve_ind_t *p; ensure( ((1<<sp->i_state) & (NSF_IDLE)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = (N_retrieve_ind_t *)mp->b_wptr; p->PRIM_type = N_RETRIEVE_IND; mp->b_wptr += sizeof(*p); mp->b_cont = dp; sp->i_state = NS_IDLE; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * N_RETRIEVE_CON 33 - NC Retrieval complete confirmation * --------------------------------------------------------------- */static mblk_t *n_retrieve_con(void){ mblk_t *mp; N_retrieve_con_t *p; ensure( ((1<<sp->i_state) & (NSF_IDLE)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = (N_retrieve_con_t *)mp->b_wptr; p->PRIM_type = N_RETREIVE_CON; mp->b_wptr += sizeof(*p); sp->i_state = NS_IDLE; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}#endifstatic int sctp_conn_ind (sctp_t *sp, mblk_t *cp){//ptrace(("sp = %x, CONN_IND: seq = %x\n", (uint)sp, (uint)cp)); return n_conn_ind(sp, cp);}static int sctp_conn_con (sctp_t *sp){//ptrace(("sp = %x, CONN_CONF\n", (uint)sp)); return n_conn_con(sp);}static int sctp_data_ind (sctp_t *sp, uint32_t ppi, uint16_t sid, uint16_t ssn, uint32_t tsn, uint ord, uint more, mblk_t *dp){//ptrace(("sp = %x, DATA_IND: ppi=%u,sid=%u,ssn=%u,tsn=%u,ord=%u,more=%u\n", (uint)sp, ppi,sid,ssn,tsn,ord,more)); if ( ord ) return n_data_ind(sp, ppi, sid, ssn, tsn, more, dp); else return n_exdata_ind(sp, ppi, sid, ssn, tsn, more, dp);}static int sctp_datack_ind(sctp_t *sp, uint32_t ppi, uint16_t sid, uint16_t ssn, uint32_t tsn){//ptrace(("sp = %x, DATACK_IND: ppi=%u,sid=%u,ssn=%u,tsn=%u\n", (uint)sp, ppi,sid,ssn,tsn)); return n_datack_ind(sp, ppi, sid, ssn, tsn);}static int sctp_reset_ind (sctp_t *sp, ulong orig, ulong reason, mblk_t *cp){//ptrace(("sp = %x, RESET_IND\n", (uint)sp)); return n_reset_ind(sp, orig, reason, cp);}static int sctp_reset_con (sctp_t *sp){//ptrace(("sp = %x, RESET_CON\n", (uint)sp)); return n_reset_con(sp);}static int sctp_discon_ind(sctp_t *sp, ulong orig, long reason, mblk_t *cp){//ptrace(("sp = %x, DISCON_IND\n", (uint)sp)); return n_discon_ind(sp, orig, reason, cp);}static int sctp_ordrel_ind(sctp_t *sp){//ptrace(("sp = %x, ORDREL_IND\n", (uint)sp)); sctp_ordrel_req(sp); /* shut it down right now */ return sctp_discon_ind(sp, 0, 0, NULL);}static struct sctp_ifops n_ops ={ sctp_conn_ind, sctp_conn_con, sctp_data_ind, sctp_datack_ind, sctp_reset_ind, sctp_reset_con, sctp_discon_ind, sctp_ordrel_ind, NULL, NULL};/* * ========================================================================= * * NPI User --> NPI Provider (SCTP) Primitives * * ========================================================================= *//* * N_CONN_REQ 0 - NC request * ------------------------------------------------------------------------- */static int n_conn_req(sctp_t *sp, mblk_t *mp){ int err = -EFAULT; size_t mlen = mp->b_wptr - mp->b_rptr; N_conn_req_t *p = (N_conn_req_t *)mp->b_rptr; N_qos_sel_conn_sctp_t *q = (N_qos_sel_conn_sctp_t *)(mp->b_rptr + p->QOS_offset); do { if ( sp->i_state == NS_IDLE ) { sp->i_state = NS_WCON_CREQ; if ( mlen >= sizeof(*p) ) { if ( !p->QOS_length || mlen >= p->QOS_offset + p->QOS_length ) { if ( !p->QOS_length || q->n_qos_type == N_QOS_SEL_CONN_SCTP ) { if ( !p->QOS_length || p->QOS_length == sizeof(*q) ) { struct sctp_addr *a = (struct sctp_addr *)(mp->b_rptr + p->DEST_offset); size_t anum = (p->DEST_length - sizeof(a->port))/sizeof(a->addr[0]); if ( ( mlen >= p->DEST_offset + p->DEST_length ) && ( anum && p->DEST_length == sizeof(a->port)+anum*sizeof(a->addr[0]) ) && a->port ) { if ( sp->cred.cr_uid == 0 || a->port >= 1024 ) { { if ( p->QOS_length ) { if ( q->i_streams != -1UL ) sp->max_istr = q->i_streams?q->i_streams:1; if ( q->o_streams != -1UL ) sp->req_ostr = q->o_streams?q->o_streams:1; } if ( !sp->max_istr ) sp->max_istr = 1; if ( !sp->req_ostr ) sp->req_ostr = 1; sp->flags &= ~(SCTP_FLAG_REC_CONF_OPT|SCTP_FLAG_EX_DATA_OPT); if ( p->CONN_flags & REC_CONF_OPT ) sp->flags |= SCTP_FLAG_REC_CONF_OPT; if ( p->CONN_flags & EX_DATA_OPT ) sp->flags |= SCTP_FLAG_EX_DATA_OPT; if ( (err = sctp_conn_req(sp, a->port, a->addr, anum, mp->b_cont)) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -