📄 mtp_npi.c
字号:
return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/** * t_uderror_ind: - issue a T_UDERROR_IND primitive * @mtp: MTP private data * @q: active queue * @bp: message block to free upon success * @dst: destination address (or NULL) * @opt: options (or NULL) * @dp: user data * @etype: error type */static inline fastcall __unlikely intn_uderror_ind(struct mtp *mtp, queue_t *q, mblk_t *bp, struct mtp_addr *dst, mblk_t *dp, mtp_ulong etype){ N_uderror_ind_t *p; mblk_t *mp; size_t dst_len = n_addr_size(dst); size_t msg_len = sizeof(*p) + dst_len; if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { if (likely(bcanputnext(mtp->rq, 2))) { DB_TYPE(mp) = M_PROTO; mp->b_band = 2; /* XXX move ahead of data indications */ p = (typeof(p)) mp->b_wptr; p->PRIM_type = N_UDERROR_IND; p->DEST_length = dst_len; p->DEST_offset = dst_len ? sizeof(*p) : 0; p->ERROR_type = etype; mp->b_wptr += sizeof(*p); n_build_addr(dst, mp->b_wptr); mp->b_wptr += dst_len; mp->b_cont = dp; if (bp) freeb(bp); mi_strlog(q, STRLOGRX, SL_TRACE, "<- N_UDERROR_IND"); putnext(mtp->rq, mp); return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/** * n_datack_ind: - issue a N_DATACK_IND primitive * @mtp: MTP private data * @q: active queue * @msg: message to free upon success */static inline fastcall __unlikely intn_datack_ind(struct mtp *mtp, queue_t *q, mblk_t *msg){ N_datack_ind_t *p; mblk_t *mp; size_t msg_len = sizeof(*p); if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { if (likely(canputnext(mtp->rq))) { DB_TYPE(mp) = M_PROTO; p = (typeof(p)) mp->b_wptr; p->PRIM_type = N_DATACK_IND; mp->b_wptr += sizeof(*p); freemsg(msg); mi_strlog(q, STRLOGRX, SL_TRACE, "<- N_DATACK_IND"); putnext(mtp->rq, mp); return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/** * n_reset_ind: - issue a N_RESET_IND primitive * @mtp: MTP private data * @q: active queue * @msg: message to free upon success * @orig: origin of reset * @reason: reason for reset */static inline fastcall __unlikely intn_reset_ind(struct mtp *mtp, queue_t *q, mblk_t *msg, np_ulong orig, np_ulong reason){ N_reset_ind_t *p; mblk_t *mp; size_t msg_len = sizeof(*p); if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { if (likely(canputnext(mtp->rq))) { DB_TYPE(mp) = M_PROTO; p = (typeof(p)) mp->b_wptr; p->PRIM_type = N_RESET_IND; p->RESET_orig = orig; p->RESET_reason = reason; mp->b_wptr += sizeof(*p); freemsg(msg); mi_strlog(q, STRLOGRX, SL_TRACE, "<- N_RESET_IND"); putnext(mtp->rq, mp); return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/** * n_reset_con: - issue a N_RESET_CON primitive * @mtp: MTP private data * @q: active queue * @msg: message to free upon success */static inline fastcall __unlikely intn_reset_con(struct mtp *mtp, queue_t *q, mblk_t *msg){ N_reset_con_t *p; mblk_t *mp; size_t msg_len = sizeof(*p); if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { if (likely(canputnext(mtp->rq))) { DB_TYPE(mp) = M_PROTO; p = (typeof(p)) mp->b_wptr; p->PRIM_type = N_RESET_CON; mp->b_wptr += sizeof(*p); freemsg(msg); mi_strlog(q, STRLOGRX, SL_TRACE, "<- N_RESET_CON"); putnext(mtp->rq, mp); return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/* * ------------------------------------------------------------------------- * * Primitives sent downstream. * * ------------------------------------------------------------------------- *//** * mtp_bind_req: - issue a MTP_BIND_REQ primitive * @mtp: MTP private data * @q: active queue * @msg: message to free upon success * @add: address to which to bind (or NULL) * @flags: bind flags */static inline fastcall __unlikely intmtp_bind_req(struct mtp *mtp, queue_t *q, mblk_t *msg, struct mtp_addr *add, mtp_ulong flags){ struct MTP_bind_req *p; mblk_t *mp; size_t add_len = add ? sizeof(*add) : 0; size_t msg_len = sizeof(*p) + add_len; if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { DB_TYPE(mp) = M_PCPROTO; p = (typeof(p)) mp->b_wptr; p->mtp_primitive = MTP_BIND_REQ; p->mtp_addr_length = add_len; p->mtp_addr_offset = sizeof(*p); p->mtp_bind_flags = flags; mp->b_wptr += sizeof(*p); bcopy(add, mp->b_wptr, add_len); mp->b_wptr += add_len; freemsg(msg); mi_strlog(q, STRLOGTX, SL_TRACE, "MTP_BIND_REQ ->"); putnext(mtp->wq, mp); return (0); } return (-ENOBUFS);}/** * mtp_unbind_req: - issue a MTP_UNBIND_REQ primitive * @mtp: MTP private data * @q: active queue * @msg: message to free upon success */static inline fastcall __unlikely intmtp_unbind_req(struct mtp *mtp, queue_t *q, mblk_t *msg){ struct MTP_unbind_req *p; mblk_t *mp; size_t msg_len = sizeof(*p); if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { DB_TYPE(mp) = M_PCPROTO; p = (typeof(p)) mp->b_wptr; p->mtp_primitive = MTP_UNBIND_REQ; mp->b_wptr += sizeof(*p); freemsg(msg); mi_strlog(q, STRLOGTX, SL_TRACE, "MTP_UNBIND_REQ ->"); putnext(mtp->wq, mp); return (0); } return (-ENOBUFS);}/** * mtp_conn_req: - issue a MTP_CONN_REQ primitive * @mtp: MTP private data * @q: active queue * @bp: message block to free upon success * @add: address to which to connect (or NULL) * @flags: connect flags * @dp: user data */static inline fastcall __unlikely intmtp_conn_req(struct mtp *mtp, queue_t *q, mblk_t *bp, struct mtp_addr *add, mtp_ulong flags, mblk_t *dp){ struct MTP_conn_req *p; mblk_t *mp; size_t add_len = add ? sizeof(*add) : 0; size_t msg_len = sizeof(*p) + add_len; if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { if (likely(canputnext(mtp->wq))) { DB_TYPE(mp) = M_PROTO; p = (typeof(p)) mp->b_wptr; p->mtp_primitive = MTP_CONN_REQ; p->mtp_addr_length = add_len; p->mtp_addr_offset = add_len ? sizeof(*p) : 0; p->mtp_conn_flags = flags; mp->b_wptr += sizeof(*p); bcopy(add, mp->b_wptr, add_len); mp->b_wptr += add_len; mp->b_cont = dp; if (bp) freeb(bp); mi_strlog(q, STRLOGTX, SL_TRACE, "MTP_CONN_REQ ->"); putnext(mtp->wq, mp); return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/** * mtp_discon_req: - issue an MTP_DISCON_REQ primitive * @mtp: MTP private data * @q: active queue * @bp: message block to free upon success * @dp: user data */static inline fastcall __unlikely intmtp_discon_req(struct mtp *mtp, queue_t *q, mblk_t *bp, mblk_t *dp){ struct MTP_discon_req *p; mblk_t *mp; size_t msg_len = sizeof(*p); if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { if (likely(canputnext(mtp->wq))) { DB_TYPE(mp) = M_PROTO; p = (typeof(p)) mp->b_wptr; p->mtp_primitive = MTP_DISCON_REQ; mp->b_wptr += sizeof(*p); mp->b_cont = dp; if (bp) freeb(bp); mi_strlog(q, STRLOGTX, SL_TRACE, "MTP_DISCON_REQ ->"); putnext(mtp->wq, mp); return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/** * mtp_addr_request: - issue an MTP_ADDR_REQ primitive * @mtp: MTP private data * @q: active queue * @msg: message to free upon success */static inline fastcall __unlikely intmtp_addr_req(struct mtp *mtp, queue_t *q, mblk_t *msg){ struct MTP_addr_req *p; mblk_t *mp; size_t msg_len = sizeof(*p); if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { DB_TYPE(mp) = M_PCPROTO; p = (typeof(p)) mp->b_wptr; p->mtp_primitive = MTP_ADDR_REQ; mp->b_wptr += sizeof(*p); freemsg(msg); mi_strlog(q, STRLOGTX, SL_TRACE, "MTP_ADDR_REQ ->"); putnext(mtp->wq, mp); return (0); } return (-ENOBUFS);}/** * mtp_info_req: - issue an MTP_INFO_REQ primitive * @mtp: MTP private data * @q: active queue * @msg: message to free upon success */static inline fastcall __unlikely intmtp_info_req(struct mtp *mtp, queue_t *q, mblk_t *msg){ struct MTP_info_req *p; mblk_t *mp; size_t msg_len = sizeof(*p); if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { DB_TYPE(mp) = M_PCPROTO; p = (typeof(p)) mp->b_wptr; p->mtp_primitive = MTP_INFO_REQ; mp->b_wptr += sizeof(*p); freemsg(msg); mi_strlog(q, STRLOGTX, SL_TRACE, "MTP_INFO_REQ ->"); putnext(mtp->wq, mp); return (0); } return (-ENOBUFS);}/** * mtp_optmgmt_req: - issue an MTP_OPTMGMT_REQ primitive * @mtp: MTP private data * @q: active queue * @msg: message to free upon success * @opt: options (or NULL) * @flags: management flags */static inline fastcall __unlikely intmtp_optmgmt_req(struct mtp *mtp, queue_t *q, mblk_t *msg, union N_qos_mtp *opt, mtp_ulong flags){ struct MTP_optmgmt_req *p; mblk_t *mp; struct t_opthdr *oh; size_t opt_len = opt ? 2 * sizeof(*oh) + 2 * sizeof(t_scalar_t) : 0; size_t msg_len = sizeof(*p) + opt_len; if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { if (likely(canputnext(mtp->wq))) { DB_TYPE(mp) = M_PROTO; p = (typeof(p)) mp->b_wptr; p->mtp_primitive = MTP_OPTMGMT_REQ; p->mtp_opt_length = opt_len; p->mtp_opt_offset = sizeof(*p); p->mtp_mgmt_flags = flags; mp->b_wptr += sizeof(*p); if (opt_len) { oh = (typeof(oh)) mp->b_wptr; oh->level = T_SS7_MTP; oh->name = T_MTP_SLS; oh->len = sizeof(*oh) + sizeof(t_scalar_t); oh->status = T_SUCCESS; mp->b_wptr += sizeof(*oh); *(t_scalar_t *)mp->b_wptr = opt->n_qos_info.sls; mp->b_wptr += sizeof(t_scalar_t); oh = (typeof(oh)) mp->b_wptr; oh->level = T_SS7_MTP; oh->name = T_MTP_MP; oh->len = sizeof(*oh) + sizeof(t_scalar_t); oh->status = T_SUCCESS; mp->b_wptr += sizeof(*oh); *(t_scalar_t *)mp->b_wptr = opt->n_qos_info.mp; mp->b_wptr += sizeof(t_scalar_t); } freemsg(msg); mi_strlog(q, STRLOGTX, SL_TRACE, "MTP_OPTMGMT_REQ ->"); putnext(mtp->wq, mp); return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/** * mtp_transfer_req: - issue an MTP_TRANSFER_REQ primitive * @mtp: MTP private data * @q: active queue * @bp: message block to free upon success * @dst: destination address (or NULL) * @pri: message priority * @sls: signalling link selection * @dp: user data */static inline fastcall __unlikely intmtp_transfer_req(struct mtp *mtp, queue_t *q, mblk_t *bp, struct mtp_addr *dst, mtp_ulong pri, mtp_ulong sls, mblk_t *dp){ struct MTP_transfer_req *p; mblk_t *mp; size_t dst_len = dst ? sizeof(*dst) : 0; size_t msg_len = sizeof(*p) + dst_len; if (likely((mp = mi_allocb(q, msg_len, BPRI_MED)) != NULL)) { if (likely(bcanputnext(mtp->wq, dp->b_band))) { DB_TYPE(mp) = M_PROTO; mp->b_band = dp->b_band; p = (typeof(p)) mp->b_wptr; p->mtp_primitive = MTP_TRANSFER_REQ; p->mtp_dest_length = dst_len; p->mtp_dest_offset = dst_len ? sizeof(*p) : 0; p->mtp_mp = pri; p->mtp_sls = sls; mp->b_wptr += sizeof(*p); bcopy(dst, mp->b_wptr, dst_len); mp->b_wptr += dst_len; mp->b_cont = dp; if (bp) freeb(bp); mi_strlog(q, STRLOGDA, SL_TRACE, "MTP_TRANSFER_REQ ->"); putnext(mtp->wq, mp); return (0); } freeb(mp); return (-EBUSY); } return (-ENOBUFS);}/* * ------------------------------------------------------------------------- * * Primitives received from above. * * ------------------------------------------------------------------------- *//** * n_data: - process M_DATA message * @mtp: private structure * @q: active queue * @mp: the message * * To support pseudo-connectionless modes, when this message is sent for N_CLNS we should send the * data to the same adress and with the same options as the last N_UNITDATA_REQ primitive. */static inline fastcall __hot_read intn_data(struct mtp *mtp, queue_t *q, mblk_t *mp){ const size_t dlen = msgdsize(mp); if (mtp->prot.SERV_type == N_CLNS) goto notsupport; if (mtp_chk_state(mtp, (NSF_IDLE | NSF_WRES_RIND))) goto discard; if (mtp_get_state(mtp) != NS_DATA_XFER) goto outstate; if (dlen == 0 || dlen > mtp->prot.NSDU_size || dlen > mtp->prot.NIDU_size) goto baddata; return mtp_transfer_req(mtp, q, mp, &mtp->dst, mtp->options.mp, mtp->options.sls, mp); 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; discard: mi_strlog(q, 0, SL_TRACE, "ignore in idle state"); freemsg(mp); 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_conn_req: - process N_CONN_REQ primitive * @mtp: private structure * @q: active queue * @mp: the message * * As MTP is really a connectionless protocol, when we form a connection we simply remember the * destination address. Some interim MTPs had the abilitty to send a UPT (User Part Test) message. * If the protocol variant has this ability, we wait for the result of the User Part Test before * confirming the connection.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -