📄 mtp_npi.c
字号:
*/static inline fastcall __unlikely intn_conn_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ int err; const N_conn_req_t *p = (typeof(p)) mp->b_rptr; struct mtp_addr *dst; struct mtp_opts opts; if (mtp_get_state(mtp) != NS_IDLE) goto outstate; if (mtp->prot.SERV_type == N_CLNS) goto notsupport; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto badprim; if (mp->b_wptr < mp->b_rptr + p->DEST_offset + p->DEST_length) goto badprim; if (mp->b_wptr < mp->b_rptr + p->QOS_offset + p->QOS_length) goto badprim; dst = (typeof(dst)) (mp->b_rptr + p->DEST_offset); if (!p->DEST_length) goto noaddr; if (p->DEST_length < sizeof(*dst)) goto badaddr; if (dst->family != AF_MTP) goto badaddr; if (dst->si == 0 && mtp->src.si == 0) goto noaddr; if (dst->si < 3 && mtp->src.si != 0) goto badaddr; if (dst->si < 3 && mtp->cred.cr_uid != 0) goto access; if (dst->si != mtp->src.si && mtp->src.si != 0) goto badaddr; if (n_parse_opts(mtp, &opts, mp->b_rptr + p->QOS_offset, p->QOS_length)) goto badqostype; /* TODO: set options first */ if (mp->b_cont) { putbq(q, mp->b_cont); /* hold back data */ mp->b_cont = NULL; /* abosrbed mp->b_cont */ } mtp->dst = *dst; mtp_set_state(mtp, NS_WCON_CREQ); return n_conn_con(mtp, q, mp, 0, &mtp->dst, NULL, NULL); access: err = NACCESS; mi_strlog(q, 0, SL_TRACE, "no permission"); goto error; badqostype: err = NBADQOSTYPE; mi_strlog(q, 0, SL_TRACE, "bad qos type"); goto error;#if 0 badqosparam: err = NBADQOSPARAM; mi_strlog(q, 0, SL_TRACE, "bad qos parameter"); goto error;#endif badaddr: err = NBADADDR; mi_strlog(q, 0, SL_TRACE, "bad destination address"); goto error; noaddr: err = NNOADDR; mi_strlog(q, 0, SL_TRACE, "couldn't allocate destination address"); goto error; badprim: err = -EMSGSIZE; mi_strlog(q, 0, SL_TRACE, "invalid primitive format"); goto error; outstate: err = NOUTSTATE; mi_strlog(q, 0, SL_TRACE, "would place i/f out of state"); goto error; notsupport: err = NNOTSUPPORT; mi_strlog(q, 0, SL_TRACE, "primitive not supported for N_CLNS"); goto error; error: return n_error_ack(mtp, q, mp, N_CONN_REQ, err);}/** * n_conn_res: - process N_CONN_RES primtive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_conn_res(struct mtp *mtp, queue_t *q, mblk_t *mp){ int err; const N_conn_res_t *p = (typeof(p)) mp->b_rptr; if (mtp->prot.SERV_type == N_CLNS) goto notsupport; if (mtp_get_state(mtp) != NS_WRES_CIND) goto outstate; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto badprim; /* We never give an N_CONN_IND, so there is no reason for a N_CONN_RES. We probably could do this (issue an N_CONN_IND on a listening stream when there is no other MTP user for the SI value and * send a UPU on an N_DISCON_REQ or just redirect all traffic for that user on a N_CONN_RES) but that is for later. */ goto eopnotsupp; eopnotsupp: err = -EOPNOTSUPP; mi_strlog(q, 0, SL_TRACE, "operation not supported"); goto error; badprim: err = -EMSGSIZE; mi_strlog(q, 0, SL_TRACE, "invalid primitive format"); goto error; outstate: err = NOUTSTATE; mi_strlog(q, 0, SL_TRACE, "would place i/f out of state"); goto error; notsupport: err = NNOTSUPPORT; mi_strlog(q, 0, SL_TRACE, "primitive not supported"); goto error; error: return n_error_ack(mtp, q, mp, N_CONN_RES, err);}/** * n_discon_req: - process N_DISCON_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_discon_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ int err; const N_discon_req_t *p = (typeof(p)) mp->b_rptr; if (mtp->prot.SERV_type == N_CLNS) goto notsupport; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto badprim; /* Currently there are only three states we can disconnect from. The first does not happen. Only the second one is normal. The third should occur during simulteneous diconnect only. */ switch (mtp_get_state(mtp)) { case NS_WCON_CREQ: mtp_set_state(mtp, NS_WACK_DREQ6); break; case NS_DATA_XFER: mtp_set_state(mtp, NS_WACK_DREQ9); break; case NS_IDLE: rare(); break; default: goto outstate; } /* change state and let mtp_ok_ack do all the work */ return mtp_discon_req(mtp, q, mp, NULL); badprim: err = -EMSGSIZE; mi_strlog(q, 0, SL_TRACE, "invalid primitive format"); goto error; outstate: err = NOUTSTATE; mi_strlog(q, 0, SL_TRACE, "would place i/f out of state"); goto error; notsupport: err = NNOTSUPPORT; mi_strlog(q, 0, SL_TRACE, "primitive not supported for N_CLNS"); goto error; error: return n_error_ack(mtp, q, mp, p->PRIM_type, err);}/** * n_data_req: - process N_DATA_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_data_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ const N_data_req_t *p = (typeof(p)) mp->b_rptr; size_t dlen = mp->b_cont ? msgdsize(mp) : 0; if (mtp->prot.SERV_type == N_CLNS) goto notsupport; if (mtp_get_state(mtp) == NS_IDLE) goto discard; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto einval; if (!mp->b_cont) goto einval; if ((1 << mtp_get_state(mtp)) & ~(NSF_DATA_XFER | NSF_WRES_RIND | NSF_WCON_RREQ)) goto outstate; if (dlen == 0 || dlen > mtp->prot.NSDU_size || dlen > mtp->prot.NIDU_size) goto baddata; if (p->DATA_xfer_flags) /* N_MORE_DATA_FLAG and N_RC_FLAG not supported yet. We could do N_MORE_DATA_FLAG pretty easily by accumulating the packet until the last data request is received, but this would be rather pointless for small MTP packet sizes. N_RC_FLAG cannot be supported until the DLPI link driver is done and zero-loss operation is completed. */ goto notsupport; return mtp_transfer_req(mtp, q, mp, &mtp->dst, mtp->options.mp, mtp->options.sls, mp->b_cont); baddata: mi_strlog(q, 0, SL_TRACE, "bad data size %lu", (ulong) dlen); goto error; outstate: mi_strlog(q, 0, SL_TRACE, "would place i/f out of state"); goto error; einval: mi_strlog(q, 0, SL_TRACE, "invalid primitive format"); goto error; discard: mi_strlog(q, 0, SL_TRACE, "ignore in idle state"); return (0); notsupport: mi_strlog(q, 0, SL_TRACE, "primitive not supported for N_CLNS"); goto error; error: return m_error(mtp, q, mp, EPROTO);}/** * n_exdata_req: - process N_EXDATA_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_exdata_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ (void) mp; return m_error(mtp, q, mp, EPROTO);}/** * n_info_req: - process N_INFO_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_info_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ return n_info_ack(mtp, q, mp);}/** * n_bind_req:- process N_BIND_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_bind_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ int err; const N_bind_req_t *p = (typeof(p)) mp->b_rptr; struct mtp_addr src; if (mtp_get_state(mtp) != NS_UNBND) goto outstate; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto badprim; if (mp->b_wptr < mp->b_rptr + p->ADDR_offset + p->ADDR_length) goto badprim; if (p->CONIND_number) goto notsupport; if (mp->b_wptr < mp->b_rptr + p->PROTOID_offset + p->PROTOID_length) goto badprim; if (p->PROTOID_length) goto badaddr; if (!p->ADDR_length) goto noaddr; if (p->ADDR_length < sizeof(src)) goto badaddr; bcopy(mp->b_rptr + p->ADDR_offset, &src, sizeof(src)); /* we don't allow wildcards yet. */ if (src.family != AF_MTP) goto badaddr; if (!src.si || !src.pc) goto noaddr; if (src.si < 3 && mtp->cred.cr_uid != 0) goto acces; mtp_set_state(mtp, NS_WACK_BREQ); return mtp_bind_req(mtp, q, mp, &src, 0); acces: err = NACCESS; mi_strlog(q, 0, SL_TRACE, "no priviledge for requested address"); goto error; noaddr: err = NNOADDR; mi_strlog(q, 0, SL_TRACE, "could not allocate address"); goto error; badaddr: err = NBADADDR; mi_strlog(q, 0, SL_TRACE, "requested address invalid"); goto error; notsupport: err = NNOTSUPPORT; mi_strlog(q, 0, SL_TRACE, "primitive not support for N_CLNS"); goto error; badprim: err = -EMSGSIZE; mi_strlog(q, 0, SL_TRACE, "invalid primitive format"); goto error; outstate: err = NOUTSTATE; mi_strlog(q, 0, SL_TRACE, "would place i/f out of state"); goto error; error: return n_error_ack(mtp, q, mp, p->PRIM_type, err);}/** * t_unbind_req: - process T_UNBIND_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_unbind_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ const N_unbind_req_t *p = (typeof(p)) mp->b_rptr; int err; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto badprim; if (mtp_get_state(mtp) != NS_IDLE) goto outstate; mtp_set_state(mtp, NS_WACK_UREQ); return mtp_unbind_req(mtp, q, mp); outstate: err = NOUTSTATE; mi_strlog(q, 0, SL_TRACE, "would place i/f out of state"); goto error; badprim: err = -EMSGSIZE; mi_strlog(q, 0, SL_TRACE, "invalid primitive format"); goto error; error: return n_error_ack(mtp, q, mp, p->PRIM_type, err);}/** * t_unitdata_req: - process T_UNITDATA_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_unitdata_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ const N_unitdata_req_t *p = (typeof(p)) mp->b_rptr; size_t dlen = mp->b_cont ? msgdsize(mp->b_cont) : 0; struct mtp_addr dst;#if 0 struct mtp_opts opts = { 0L, NULL, };#endif if (mtp->prot.SERV_type != N_CLNS) goto notsupport; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto badprim; if (mp->b_wptr < mp->b_rptr + p->DEST_offset + p->DEST_length) goto badprim; if (mtp_get_state(mtp) != NS_IDLE) goto outstate; if (dlen == 0) goto baddata; if (dlen > mtp->prot.NSDU_size || dlen > mtp->prot.NIDU_size) goto baddata; if (mp->b_wptr < mp->b_rptr + sizeof(*p) || mp->b_wptr < mp->b_rptr + p->DEST_offset + p->DEST_length) goto badprim; if (!p->DEST_length) goto noaddr; if (p->DEST_length < sizeof(dst)) goto badaddr; bcopy(mp->b_rptr + p->DEST_offset, &dst, sizeof(dst)); if (dst.family != AF_MTP) goto badaddr; if (!dst.si || !dst.pc) goto badaddr; if (dst.si < 3 && mtp->cred.cr_uid != 0) goto acces; if (dst.si != mtp->src.si) goto badaddr;#if 0 if (n_parse_opts(&opts, mp->b_rptr + p->QOS_offset, p->QOS_length)) goto badopt;#endif fixme(("Handle options correctly\n")); return mtp_transfer_req(mtp, q, mp, &dst, mtp->options.mp, mtp->options.sls, mp->b_cont);#if 0 badopt: mi_strlog(q, 0, SL_TRACE, "bad options"); goto error;#endif acces: mi_strlog(q, 0, SL_TRACE, "no permission to address"); goto error; badaddr: mi_strlog(q, 0, SL_TRACE, "requested address invalid"); goto error; noaddr: mi_strlog(q, 0, SL_TRACE, "could not allocate address"); goto error; baddata: mi_strlog(q, 0, SL_TRACE, "invalid amount of data"); goto error; outstate: mi_strlog(q, 0, SL_TRACE, "would place i/f out of state"); goto error; badprim: mi_strlog(q, 0, SL_TRACE, "invalid primitive format"); goto error; notsupport: mi_strlog(q, 0, SL_TRACE, "primitive type not supported"); goto error; error: return m_error(mtp, q, mp, EPROTO);}/** * t_optmgmt_req: - process T_OPTMGMT_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message */static inline fastcall __unlikely intn_optmgmt_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ int err = 0; const N_optmgmt_req_t *p = (typeof(p)) mp->b_rptr; union N_qos_mtp *qos = { 0L, }; if (mp->b_wptr < mp->b_rptr + sizeof(*p)) goto badprim; if (mp->b_wptr < mp->b_rptr + p->QOS_offset + p->QOS_length) goto badprim;#ifdef NS_WACK_OPTREQ if (mtp_get_state(mtp) == NS_IDLE) mtp_set_state(mtp, NS_WACK_OPTREQ);#endif if (p->OPTMGMT_flags) /* Can't support DEFAULT_RC_SEL yet */ goto badflags; qos = (typeof(qos)) (mp->b_rptr + p->QOS_offset); if (p->QOS_length < sizeof(qos->n_qos_data)) goto badqostype; if (qos->n_qos_type != N_QOS_SEL_DATA_MTP) goto badqostype; if (qos->n_qos_data.sls > 255 && qos->n_qos_data.sls != -1U) goto badqosparam; if (qos->n_qos_data.mp > 3 && qos->n_qos_data.mp != -1U) goto badqosparam; mtp->options.sls = qos->n_qos_data.sls; mtp->options.mp = qos->n_qos_data.mp; return n_ok_ack(mtp, q, mp, N_OPTMGMT_REQ); badqostype: err = NBADQOSTYPE; mi_strlog(q, 0, SL_TRACE, "invalid qos type"); goto error; badqosparam: err = NBADQOSPARAM; mi_strlog(q, 0, SL_TRACE, "invalid qos parameter"); goto error; badflags: err = NBADFLAG; mi_strlog(q, 0, SL_TRACE, "invalid flag"); goto error; badprim: err = -EMSGSIZE; mi_strlog(q, 0, SL_TRACE, "invalid primitive format"); goto error; error: return n_error_ack(mtp, q, mp, N_OPTMGMT_REQ, err);}/* * N_DATACK_REQ: * ------------------------------------------------------------------- */static inline fastcall __unlikely intn_datack_req(struct mtp *mtp, queue_t *q, mblk_t *mp){ (void) q; (void) mp; /* We don't support DATACK yet. With zero loss operation we will. */ rare(); return (0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -