📄 sctp_t.c
字号:
/* not supported yet */ } if ( ops->reuse ) { /* not supported yet */ } if ( ops->tos ) { if ( ops->tos->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->tos+1); sp->ip_tos = *val & 0xff; *val = sp->ip_tos; ops->flags |= TF_IP_TOS; } } if ( ops->ttl ) { if ( ops->ttl->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->ttl+1); sp->ip_ttl = *val & 0xff; *val = sp->ip_ttl; ops->flags |= TF_IP_TTL; } } if ( ops->nd ) { if ( ops->nd->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->nd+1); switch ( *val ) { case T_YES: sp->options &=~SCTP_OPTION_NAGLE; break; case T_NO: sp->options |= SCTP_OPTION_NAGLE; break; break; } *val = (sp->options & SCTP_OPTION_NAGLE)?T_NO:T_YES; ops->flags |= TF_SCTP_NODELAY; } } if ( ops->cork ) { if ( ops->cork->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->cork+1); switch ( *val ) { case T_YES: sp->options |= SCTP_OPTION_CORK; break; case T_NO: sp->options &=~SCTP_OPTION_CORK; break; } *val = (sp->options & SCTP_OPTION_CORK)?T_YES:T_NO; ops->flags |= TF_SCTP_CORK; } } if ( ops->ppi ) { if ( ops->ppi->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->ppi+1); sp->ppi = *val; *val = sp->ppi; ops->flags |= TF_SCTP_PPI; } } if ( ops->sid ) { if ( ops->sid->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->sid+1); sp->sid = *val; *val = sp->sid; ops->flags |= TF_SCTP_SID; } } if ( ops->ssn ) { /* not writeable */ } if ( ops->tsn ) { /* not writeable */ } if ( ops->ropt ) { if ( ops->ropt->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->ropt+1); switch ( *val ) { case T_YES: sp->i_flags |= TF_SCTP_RECVOPT; break; case T_NO: sp->i_flags &=~TF_SCTP_RECVOPT; break; } *val = (sp->i_flags & TF_SCTP_RECVOPT)?T_YES:T_NO; ops->flags |= TF_SCTP_RECVOPT; } } if ( ops->cklife ) { if ( ops->cklife->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->cklife+1); if ( *val < 10 ) *val = 10; sp->ck_life = (*val*HZ+999)/1000; *val = (sp->ck_life*1000+HZ-1)/HZ; ops->flags |= TF_SCTP_COOKIE_LIFE; } } if ( ops->sack ) { if ( ops->sack->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->sack+1); sp->max_sack = (*val*HZ+999)/1000; *val = (sp->max_sack*1000+HZ-1)/HZ; ops->flags |= TF_SCTP_SACK_DELAY; } } if ( ops->path ) { if ( ops->path->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->path+1); sp->rtx_path = *val; *val = sp->rtx_path; ops->flags |= TF_SCTP_PATH_MAX_RETRANS; } } if ( ops->assoc ) { if ( ops->assoc->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->assoc+1); sp->max_retrans = *val; *val = sp->max_retrans; ops->flags |= TF_SCTP_ASSOC_MAX_RETRANS; } } if ( ops->init ) { if ( ops->init->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->init+1); sp->max_inits = *val; *val = sp->max_inits; ops->flags |= TF_SCTP_MAX_INIT_RETRIES; } } if ( ops->hbitvl ) { if ( ops->hbitvl->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->hbitvl+1); sp->hb_itvl = (*val*HZ+999)/1000; *val = (sp->hb_itvl*1000+HZ-1)/HZ; ops->flags |= TF_SCTP_HEARTBEAT_ITVL; } } if ( ops->rtoinit ) { if ( ops->rtoinit->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->rtoinit+1); sp->rto_ini = (*val*HZ+999)/1000; *val = (sp->rto_ini*1000+HZ-1)/HZ; ops->flags |= TF_SCTP_RTO_INITIAL; } } if ( ops->rtomin ) { if ( ops->rtomin->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->rtomin+1); sp->rto_min = (*val*HZ+999)/1000; *val = (sp->rto_min*1000+HZ-1)/HZ; ops->flags |= TF_SCTP_RTO_MIN; } } if ( ops->rtomax ) { if ( ops->rtomax->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->rtomax+1); sp->rto_max = (*val*HZ+999)/1000; *val = (sp->rto_max*1000+HZ-1)/HZ; ops->flags |= TF_SCTP_RTO_MAX; } } if ( ops->ostr ) { if ( ops->ostr->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->ostr+1); sp->req_ostr = *val; *val = sp->req_ostr; ops->flags |= TF_SCTP_OSTREAMS; } } if ( ops->istr ) { if ( ops->istr->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->istr+1); sp->max_istr = *val; *val = sp->max_istr; ops->flags |= TF_SCTP_ISTREAMS; } } if ( ops->ckinc ) { if ( ops->ckinc->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->ckinc+1); sp->ck_inc = (*val*HZ+999)/1000; *val = (sp->ck_inc*1000+HZ-1)/HZ; ops->flags |= TF_SCTP_COOKIE_INC; } } if ( ops->titvl ) { if ( ops->titvl->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->titvl+1); sp->throttle = (*val*HZ+999)/1000; *val = (sp->throttle*1000+HZ-1)/HZ; ops->flags |= TF_SCTP_THROTTLE_ITVL; } } if ( ops->hmac ) { if ( ops->hmac->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->hmac+1); sp->hmac = *val; *val = sp->hmac; ops->flags |= TF_SCTP_MAC_TYPE; } } if ( ops->mseg ) { /* not writeable */ } if ( ops->debug ) { if ( ops->debug->len >= olen ) { t_scalar_t *val = (t_scalar_t *)(ops->debug+1); sp->options = *val; *val = sp->options; ops->flags |= TF_SCTP_DEBUG; } } if ( ops->hb ) { /* not support yet */ } if ( ops->rto ) { /* not support yet */ } if ( ops->status ) { /* not writeable */ } return;}/* * Check options * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */static void sctp_check_opts(sctp_t *sp, sctp_opts_t *ops){ if ( !ops ) return; ops->flags = TF_SCTP_ALLOPS; /* * FIXME: actually check some options. */ fixme(("Actually check some options.\n")); return;}/* * ========================================================================= * * SCTP T-Provider --> T-User Primitives (Indication, Confirmation and Ack) * * ========================================================================= * * T_CONN_IND 11 - connection indication * ----------------------------------------------------------------- * We get the connection indication information from the cookie received in the COOKIE ECHO * which invokes the indication. (We queue the COOKIE ECHO chunks themselves as * indications.) */static int t_conn_ind(sctp_t *sp, mblk_t *cp){ mblk_t *mp; struct T_conn_ind *p; struct t_opthdr *oh; struct sctp_cookie_echo *m = (struct sctp_cookie_echo *)cp->b_rptr; struct sctp_cookie *ck = (struct sctp_cookie *)m->cookie; size_t danum = ck->danum + 1; uint32_t *daptr = (uint32_t *)(((caddr_t)(ck+1)+ck->opt_len)); size_t src_len = danum?sizeof(uint16_t)+danum*sizeof(uint32_t):0; size_t str_len = sizeof(struct t_opthdr)+sizeof(t_scalar_t); size_t opt_len = 2*str_len; ensure( ((1<<sp->i_state) & (TSF_IDLE|TSF_WRES_CIND)), return(-EFAULT) ); if ( bufq_length(&sp->conq) < sp->conind ) { if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p)+src_len+opt_len, BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = ((struct T_conn_ind *)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; /* place address information from cookie */ if ( danum ) *((uint16_t *)mp->b_wptr)++ = ck->dport; if ( danum-- ) *((uint32_t *)mp->b_wptr)++ = ck->daddr; while ( danum-- ) *((uint32_t *)mp->b_wptr)++ = *daptr++; /* indicate options */ oh = ((struct t_opthdr *)mp->b_wptr)++; oh->len = str_len; oh->level = T_INET_SCTP; oh->name = T_SCTP_ISTREAMS; oh->status = T_SUCCESS; *((t_scalar_t *)mp->b_wptr)++ = ck->n_istr; /* indicate options */ oh = ((struct t_opthdr *)mp->b_wptr)++; oh->len = str_len; oh->level = T_INET_SCTP; oh->name = T_SCTP_OSTREAMS; oh->status = T_SUCCESS; *((t_scalar_t *)mp->b_wptr)++ = ck->n_ostr; bufq_queue(&sp->conq, cp); sp->i_state = TS_WRES_CIND; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY); } seldom(); return(-ERESTART);}/* * T_CONN_CON 12 - connection confirmation * ----------------------------------------------------------------- * The only options with end-to-end significance that are negotiated are the number of * inbound and outbound streams. */static int t_conn_con(sctp_t *sp){ mblk_t *mp; struct T_conn_con *p; struct t_opthdr *oh; struct sctp_daddr *sd = sp->daddr; size_t res_len = sp->danum?sizeof(uint16_t)+sp->danum*sizeof(sd->daddr):0; size_t str_len = sizeof(*oh)+sizeof(t_scalar_t); size_t opt_len = 2*str_len; ensure( (sp->i_state == TS_WCON_CREQ), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p)+res_len+opt_len, BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; mp->b_band = 1; /* expedite */ p = ((struct T_conn_con *)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; /* place destination (responding) address */ if ( sd ) *((uint16_t *)mp->b_wptr)++ = sp->dport; for ( ; sd; sd = sd->next ) *((uint32_t *)mp->b_wptr)++ = sd->daddr; /* indicate options */ oh = ((struct t_opthdr *)mp->b_wptr)++; oh->len = str_len; oh->level = T_INET_SCTP; oh->name = T_SCTP_ISTREAMS; oh->status = T_SUCCESS; *((t_scalar_t *)mp->b_wptr)++ = sp->n_istr; /* indicate options */ oh = ((struct t_opthdr *)mp->b_wptr)++; oh->len = str_len; oh->level = T_INET_SCTP; oh->name = T_SCTP_OSTREAMS; oh->status = T_SUCCESS; *((t_scalar_t *)mp->b_wptr)++ = sp->n_ostr; sp->i_state = TS_DATA_XFER; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * T_DISCON_IND 13 - disconnect indication * ----------------------------------------------------------------- * We use the address of the mblk that contains the COOKIE-ECHO chunk as a SEQ_number for * connect indications that are rejected with a disconnect indication as well. We can use * this to directly address the mblk in the connection indication bufq. * * If the caller provides disconnect data, the caller needs to set the current ord, ppi, * sid, and ssn fields so that the user can examine them with T_OPTMGMT_REQ T_CURRENT if it * has need to know them. */static int t_discon_ind(sctp_t *sp, long reason, mblk_t *seq){ mblk_t *mp; struct T_discon_ind *p; ensure( ((1<<sp->i_state) & (TSF_WCON_CREQ|TSF_WRES_CIND|TSF_DATA_XFER|TSF_WIND_ORDREL|TSF_WREQ_ORDREL)), return(-EFAULT) ); if ( canputnext(sp->rq) ) { if ( (mp = allocb(sizeof(*p), BPRI_MED)) ) { mp->b_datap->db_type = M_PROTO; p = ((struct T_discon_ind *)mp->b_wptr)++; p->PRIM_type = T_DISCON_IND; p->DISCON_reason = reason; p->SEQ_number = (ulong)seq; if ( seq ) { bufq_unlink(&sp->conq, seq); freemsg(seq); } if ( !bufq_length(&sp->conq) ) sp->i_state = TS_IDLE; else sp->i_state = TS_WRES_CIND; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * T_DATA_IND 14 - data indication * ----------------------------------------------------------------- * This indication is only useful for delivering data indications for the default stream. * The caller should check that ppi and sid match the default before using this indication. * Otherwise the caller should use the T_OPTDATA_IND. */static int t_data_ind(sctp_t *sp, ulong more, mblk_t *dp){ mblk_t *mp; struct T_data_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_data_ind *)mp->b_wptr)++; p->PRIM_type = T_DATA_IND; p->MORE_flag = more; mp->b_cont = dp; putnext(sp->rq, mp); return(0); } seldom(); return(-ENOBUFS); } seldom(); return(-EBUSY);}/* * T_EXDATA_IND 15 - expedited data indication * ----------------------------------------------------------------- * This indication is only useful for delivering data indications for the default stream. * The caller should check that ppi and ssn match the default before using this indication. * Otherwise the caller should use the T_OPTDATA_IND. */static int t_exdata_ind(sctp_t *sp, ulong more, mblk_t *dp){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -