📄 sctp_t.c
字号:
mblk_t *mp; struct T_exdata_ind *p; ensure( ((1<<sp->i_state) & (TSF_DATA_XFER|TSF_WIND_ORDREL)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; mp->b_band = 1; /* expedite */ p = ((struct T_exdata_ind *)mp->b_wptr)++; p->PRIM_type = T_EXDATA_IND; p->MORE_flag = more; mp->b_cont = dp; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * T_INFO_ACK 16 - information acknowledgement * ----------------------------------------------------------------- * Although there is no limit on CDATA and DDATA size, if these are too large then we will * IP fragment the message. */static int t_info_ack(sctp_t *sp){ mblk_t *mp; struct T_info_ack *p; if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = ((struct T_info_ack *)mp->b_wptr)++; p->PRIM_type = T_INFO_ACK; p->TSDU_size = -1; /* no limit on TSDU size */ p->ETSDU_size = -1; /* no limit on ETSDU size */ p->CDATA_size = -1; /* no limit on CDATA size */ p->DDATA_size = -1; /* no limit on DDATA size */ p->ADDR_size = -1; /* no limit on ADDR size */ p->OPT_size = -1; /* no limit on OPTIONS size */ p->TIDU_size = -1; /* no limit on TIDU size */ p->SERV_type = T_COTS_ORD; /* COTS with orderly release */ p->CURRENT_state = sp->i_state; p->PROVIDER_flag = XPG4_1&~T_SNDZERO; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * T_BIND_ACK 17 - bind acknowledgement * ----------------------------------------------------------------- */static int t_bind_ack(sctp_t *sp){ mblk_t *mp; struct T_bind_ack *p; struct sctp_saddr *ss = sp->saddr; size_t add_len = sp->sanum?sizeof(sp->sport)+sp->sanum*sizeof(ss->saddr):0; ensure( (sp->i_state == TS_WACK_BREQ), return(-EFAULT) ); if ( (mp = allocb(sizeof(*p)+add_len, BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = ((struct T_bind_ack *)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 = sp->conind; if ( ss ) *((typeof(sp->sport) *)mp->b_wptr)++ = sp->sport; for ( ; ss; ss = ss->next ) *((typeof(ss->saddr) *)mp->b_wptr)++ = ss->saddr; sp->i_state = TS_IDLE; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * T_ERROR_ACK 18 - error acknowledgement * ----------------------------------------------------------------- */static int t_error_ack(sctp_t *sp, ulong prim, long err){ mblk_t *mp; struct T_error_ack *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 = ((struct T_error_ack *)mp->b_wptr)++; p->PRIM_type = T_ERROR_ACK; p->ERROR_prim = prim; p->TLI_error = err<0 ? TSYSERR : err; p->UNIX_error = err<0 ? -err : 0; switch ( sp->i_state ) {#ifdef TS_WACK_OPTREQ case TS_WACK_OPTREQ:#endif case TS_WACK_UREQ: case TS_WACK_CREQ: sp->i_state = TS_IDLE; break; case TS_WACK_BREQ: sp->i_state = TS_UNBND; break; case TS_WACK_CRES: sp->i_state = TS_WRES_CIND; break; case TS_WACK_DREQ6: sp->i_state = TS_WCON_CREQ; break; case TS_WACK_DREQ7: sp->i_state = TS_WRES_CIND; break; case TS_WACK_DREQ9: sp->i_state = TS_DATA_XFER; break; case TS_WACK_DREQ10: sp->i_state = TS_WIND_ORDREL; break; case TS_WACK_DREQ11: sp->i_state = TS_WREQ_ORDREL; break; /* * Note: if we are not in a WACK state we simply do * not change state. This occurs normally when we * send TOUTSTATE or TNOTSUPPORT or are responding to * a T_OPTMGMT_REQ in other then TS_IDLE state. */ } putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * T_OK_ACK 19 - success acknowledgement * ----------------------------------------------------------------- */static int t_ok_ack(sctp_t *sp, ulong prim, ulong seq, ulong tok){ mblk_t *mp; struct T_ok_ack *p; if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = ((struct T_ok_ack *)mp->b_wptr)++; p->PRIM_type = T_OK_ACK; p->CORRECT_prim = prim; switch ( sp->i_state ) { case TS_WACK_CREQ: sp->i_state = TS_WCON_CREQ; break; case TS_WACK_UREQ: sp->i_state = TS_UNBND; break; case TS_WACK_CRES: { queue_t *aq = (queue_t *)tok; sctp_t *ap = (sctp_t *)aq->q_ptr; if ( ap ) { ap->i_state = TS_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 = TS_WRES_CIND; else sp->i_state = TS_IDLE; } break; } case TS_WACK_DREQ7: if ( seq ) bufq_unlink(&sp->conq, (mblk_t *)seq); case TS_WACK_DREQ6: case TS_WACK_DREQ9: case TS_WACK_DREQ10: case TS_WACK_DREQ11: if ( bufq_length(&sp->conq) ) sp->i_state = TS_WRES_CIND; else sp->i_state = TS_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 a T_OPTMGMT_REQ in other than * the TS_IDLE state. */ } putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * T_OPTMGMT_ACK 22 - options management acknowledgement * ----------------------------------------------------------------- */static int t_optmgmt_ack(sctp_t *sp, ulong flags, sctp_opts_t *ops){ mblk_t *mp; size_t opt_len = sctp_opts_size(flags, sp, ops); struct T_optmgmt_ack *p; if ( (mp = allocb(sizeof(*p)+opt_len, BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = ((struct T_optmgmt_ack *)mp->b_wptr)++; p->PRIM_type = T_OPTMGMT_ACK; p->OPT_length = opt_len; p->OPT_offset = opt_len?sizeof(*p):0; p->MGMT_flags = flags; sctp_build_opts(flags, sp, ops, &mp->b_wptr);#ifdef TS_WACK_OPTREQ if ( sp->i_state == TS_WACK_OPTREQ ) sp->i_state = TS_IDLE;#endif putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}/* * T_ORDREL_IND 23 - orderly release indication * ----------------------------------------------------------------- */static int t_ordrel_ind(sctp_t *sp){ mblk_t *mp; struct T_ordrel_ind *p; ensure( ((1<<sp->i_state) & ( TSF_DATA_XFER|TSF_WIND_ORDREL)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = ((struct T_ordrel_ind *)mp->b_wptr)++; p->PRIM_type = T_ORDREL_IND; switch ( sp->i_state ) { case TS_DATA_XFER: sp->i_state = TS_WREQ_ORDREL; break; case TS_WIND_ORDREL: sp->i_state = TS_IDLE; break; } putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * T_OPTDATA_IND 26 - data with options indication * ----------------------------------------------------------------- */static int t_optdata_ind(sctp_t *sp, uint32_t ppi, uint16_t sid, uint16_t ssn, uint32_t tsn, uint ord, uint more, mblk_t *dp){ mblk_t *mp; struct t_opthdr *oh; struct T_optdata_ind *p; size_t str_len = sizeof(*oh)+sizeof(t_scalar_t); size_t opt_len = 0; ensure( ((1<<sp->i_state) & (TSF_DATA_XFER|TSF_WREQ_ORDREL)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( sp->i_flags & TF_SCTP_RECVOPT ) opt_len = 4*str_len; if ( (mp = allocb(sizeof(*p)+opt_len, BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; mp->b_band = ord?0:1; /* expedite */ p = ((struct T_optdata_ind *)mp->b_wptr)++; p->PRIM_type = T_OPTDATA_IND; p->DATA_flag = (more?T_ODF_MORE:0)|(ord?0:T_ODF_EX); p->OPT_length = opt_len; p->OPT_offset = opt_len?sizeof(*p):0; /* indicate options */ if ( sp->i_flags & TF_SCTP_RECVOPT ) { oh = ((struct t_opthdr *)mp->b_wptr)++; oh->len = str_len; oh->level = T_INET_SCTP; oh->name = T_SCTP_PPI; oh->status = T_SUCCESS; *((t_uscalar_t *)mp->b_wptr)++ = ppi; oh = ((struct t_opthdr *)mp->b_wptr)++; oh->len = str_len; oh->level = T_INET_SCTP; oh->name = T_SCTP_SID; oh->status = T_SUCCESS; *((t_uscalar_t *)mp->b_wptr)++ = sid; oh = ((struct t_opthdr *)mp->b_wptr)++; oh->len = str_len; oh->level = T_INET_SCTP; oh->name = T_SCTP_SSN; oh->status = T_SUCCESS; *((t_uscalar_t *)mp->b_wptr)++ = ssn; oh = ((struct t_opthdr *)mp->b_wptr)++; oh->len = str_len; oh->level = T_INET_SCTP; oh->name = T_SCTP_TSN; oh->status = T_SUCCESS; *((t_uscalar_t *)mp->b_wptr)++ = tsn; } mp->b_cont = dp; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * T_ADDR_ACK 27 - address acknowledgement * ----------------------------------------------------------------- */static int t_addr_ack(sctp_t *sp){ mblk_t *mp; struct T_addr_ack *p; struct sctp_saddr *ss = sp->saddr; struct sctp_daddr *sd = sp->daddr; size_t loc_len = sp->sanum?sizeof(sp->sport)+sp->sanum*sizeof(ss->saddr):0; size_t rem_len = sp->danum?sizeof(sp->dport)+sp->danum*sizeof(sd->daddr):0; if ( (mp = allocb(sizeof(*p)+loc_len+rem_len, BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = ((struct T_addr_ack *)mp->b_wptr)++; p->PRIM_type = T_ADDR_ACK; p->LOCADDR_length = loc_len; p->LOCADDR_offset = loc_len?sizeof(*p):0; p->REMADDR_length = rem_len; p->REMADDR_offset = rem_len?sizeof(*p)+loc_len:0; if (ss) *((typeof(sp->sport) *)mp->b_wptr)++ = sp->sport; for ( ; ss; ss = ss->next ) *((typeof(ss->saddr) *)mp->b_wptr)++ = ss->saddr; if (sd) *((typeof(sp->dport) *)mp->b_wptr)++ = sp->dport; for ( ; sd; sd = sd->next ) *((typeof(sd->daddr) *)mp->b_wptr)++ = sd->daddr; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS);}#if 0/* * T_CAPABILITY_ACK ?? - protocol capability ack * ----------------------------------------------------------------- */static int t_capability_ack(sctp_t *sp, ulong caps){ mblk_t *mp; struct T_capability_ack *p; uint caps = (acceptor?TC1_ACCEPTOR:0)|(info?TC1_INFO:0); if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PCPROTO; p = ((struct T_capability_ack *)mp->b_wptr)++; p->PRIM_type = T_CAPABILITY_ACK; p->CAP_bits1 = caps; p->ACCEPTOR_id = (caps&TC1_ACCEPTOR)?(ulong)sp->rq:0; if ( caps & TC1_INFO ) { p->INFO_ack.PRIM_type = T_INFO_ACK; p->INFO_ack.TSDU_size = sp->tsdu; p->INFO_ack.ETSDU_size = sp->etsdu; p->INFO_ack.CDATA_size = sp->cdata; p->INFO_ack.DDATA_size = sp->ddata; p->INFO_ack.ADDR_size = sp->addlen; p->INFO_ack.OPT_size = sp->optlen; p->INFO_ack.TIDU_size = sp->tidu; p->INFO_ack.SERV_type = sp->stype; p->INFO_ack.CURRENT_state = sp->i_state; p->INFO_ack.PROVIDER_flag = sp->ptype; } else bzero(&p->INFO_ack, sizeof(p->INFO_ack)); putnext(sp->rq, mp); return(0); } return(-ENOBUFS);}#endif/* * NOTES:- TPI cannot do data acknowledgements, resets or retrieval. Data * acknowledgements and retrieval are different forms of the same service. * For data acknowledgement, use the NPI interface. For reset support (SCTP * Restart indication different from SCTP CDI), use the NPI interface. */static int sctp_conn_ind (sctp_t *sp, mblk_t *cp){//ptrace(("sp = %x, CONN_IND: seq = %x\n", (uint)sp, (uint)cp)); return t_conn_ind(sp, cp);}static int sctp_conn_con (sctp_t *sp){//ptrace(("sp = %x, CONN_CONF\n", (uint)sp)); return t_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 ( sp->i_flags & TF_SCTP_RECVOPT ) return t_optdata_ind(sp, ppi, sid, ssn, tsn, ord, more, dp); if ( ord ) return t_data_ind(sp, more, dp); else return t_exdata_ind(sp, more, dp);}static int sctp_discon_ind(sctp_t *sp, ulong orig, long reason, mblk_t *cp){//ptrace(("sp = %x, DISCON_IND\n", (uint)sp)); (void)orig; return t_discon_ind(sp, reason, cp);}static int sctp_ordrel_ind(sctp_t *sp){//ptrace(("sp = %x, ORDREL_IND\n", (uint)sp)); return t_ordrel_ind(sp);}static struct sctp_ifops t_ops ={ sctp_conn_ind, sctp_conn_con, sctp_data_ind, NULL, NULL, NULL, sctp_discon_ind, sctp_ordrel_ind, NULL, NULL};/* * ========================================================================= * * SCTP T-User --> T-Provider Primitives (Request and Response) * * ========================================================================= * These represent primitive requests and responses from the Transport Provider Interface * (TPI) transport user. Each of these requests or responses invoked a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -