OpenSS7 SS7 for the Common Man |
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |
||||||||||||||||||||||||||
Home | Overview | Status | News | Documentation | Resources | About | |||||||||||||||||||||
File /code/strss7/drivers/m2ua2/m2ua_as.c#ident "@(#) $RCSfile: m2ua_as.c,v $ $Name: $($Revision: 0.8.2.4 $) $Date: 2003/06/16 09:03:54 $" static char const ident[] = "$RCSfile: m2ua_as.c,v $ $Name: $($Revision: 0.8.2.4 $) $Date: 2003/06/16 09:03:54 $"; /* * This is an M2UA Client Module */ #include <linux/config.H> #include <linux/version.h> #ifdef MODVERSIONS #include <linux/modversions.h> #endif #include <linux/module.h> #include <sys/stream.h> #include <sys/stropts.h> #include <sys/cmn_err.h> #include <sys/dki.h> #include <sys/npi.h> #include <sys/npi_sctp.h> #include <ss7/lmi.h> #include <ss7/lmi_ioctl.h> #include <ss7/sli.h> #include <ss7/sli_ioctl.h> #include "../debug.h" #define M2UA_DESCRIP "M2UA/SCTP SIGNALLING LINK (SL) STREAMS MODULE." #define M2UA_COPYRIGHT "Copyright (c) 1997-2002 OpenSS7 Corporation. All Rights Reserved." #define M2UA_DEVICE "Part of the OpenSS7 Stack for LiS STREAMS." #define M2UA_CONTACT "Brian Bidulock <bidulock@openss7.org>" #define M2UA_LICENSE "GPL" #define M2UA_BANNER M2UA_DESCRIP "\n" \ M2UA_COPYRIGHT "\n" \ M2UA_DEVICE "\n" \ M2UA_CONTACT "\n" MODULE_AUTHOR(M2UA_CONTACT); MODULE_DESCRIPTION(M2UA_DESCRIP); MODULE_SUPPORTED_DEVICE(M2UA_DEVICE); #ifdef MODULE_LICENSE MODULE_LICENSE(M2UA_LICENSE); #endif #ifndef INT #define INT void #endif typedef void (*bufcall_fnc_t) (long); /* * ========================================================================= * * STREAMS Definitions * * ========================================================================= */ static struct module_info sl_minfo = { 0, /* Module ID number */ "m2ua-sl", /* Module name */ 0, /* Min packet size accepted *//* FIXME */ INFPSZ, /* Max packet size accepted *//* FIXME */ 1 << 15, /* Hi water mark *//* FIXME */ 1 << 10 /* Lo water mark *//* FIXME */ }; static int sl_open(queue_t *, dev_t *, int, int, cred_t *); static int sl_close(queue_t *, int, cred_t *); static INT sl_rput(queue_t *, mblk_t *); static INT sl_wput(queue_t *, mblk_t *); static struct qinit sl_rinit = { sl_rput, /* Read put (msg from below) */ NULL, /* Read queue service */ sl_open, /* Each open */ sl_close, /* Last close */ NULL, /* Admin (not used) */ &sl_minfo, /* Information */ NULL /* Statistics */ }; static struct qinit sl_winit = { sl_wput, /* Write put (msg from above) */ NULL, /* Write queue service */ NULL, /* Each open */ NULL, /* Last close */ NULL, /* Admin (not used) */ &sl_minfo, /* Information */ NULL /* Statistics */ }; static struct streamtab sl_info = { &sl_rinit, /* Upper read queue */ &sl_winit, /* Upper write queue */ NULL, /* Lower read queue */ NULL /* Lower write queue */ }; /* * ========================================================================= * * M2UA-SL Private Structure * * ========================================================================= */ typedef struct sl { queue_t *rq; queue_t *wq; uint i_state; /* SL interface state */ uint state; /* link state */ } sl_t; /* * ========================================================================= * * M2UA PDU Message Definitions * * ========================================================================= */ /* * ========================================================================= * * OUTPUT Events * * ========================================================================= * ------------------------------------------------------------------------- * * SL Provider (M2UA) -> SL User Primitives * * ------------------------------------------------------------------------- * * LMI_INFO_ACK * --------------------------------------------- */ static int lmi_info_ack(sl_t * sl) { mblk_t *mp; lmi_info_ack_t *p; if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PCPROTO; p = ((lmi_info_ack_t *) mp->b_wptr)++; p->lmi_primitive = LMI_INFO_ACK; p->lmi_version = 1; p->lmi_state = sl->i_state; p->lmi_max_sdu = -1; p->lmi_min_sdu = 0; p->lmi_header_len = 0; p->lmi_ppa_style = LMI_STYLE1; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } /* * LMI_OK_ACK * --------------------------------------------- */ static int lmi_ok_ack(sl_t * sl, long prim, mblk_t * mp) { lmi_ok_ack_t *p; mp->b_datap->db_type = M_PCPROTO; mp->b_wptr = mp->b_rptr = mp->b_datap->db_base; p = ((typeof(p)) mp->b_wptr)++; p->lmi_primitive = LMI_OK_ACK; p->lmi_correct_primitive = prim; switch (sl->i_state) { case LMI_ATTACH_PENDING: sl->i_state = LMI_DISABLED; break; case LMI_DETACH_PENDING: sl->i_state = LMI_UNATTACHED; break; /* default is don't change state */ } p->lmi_state = sl->i_state; putnext(sl->rq, mp); return (1); } /* * LMI_ERROR_ACK * --------------------------------------------- */ static int lmi_error_ack(sl_t * sl, long prim, long err, mblk_t * mp) { lmi_error_ack_t *p; mp->b_datap->db_type = M_PCPROTO; mp->b_wptr = mp->b_rptr = mp->b_datap->db_base; p = ((typeof(p)) mp->b_wptr)++; p->lmi_primitive = LMI_ERROR_ACK; p->lmi_errno = err < 0 ? -err : 0; p->lmi_reason = err < 0 ? LMI_SYSERR : err; p->lmi_error_primitive = prim; switch (sl->i_state) { case LMI_ATTACH_PENDING: sl->i_state = LMI_UNATTACHED; break; case LMI_DETACH_PENDING: sl->i_state = LMI_DISABLED; break; case LMI_ENABLE_PENDING: sl->i_state = LMI_DISABLED; break; case LMI_DISABLE_PENDING: sl->i_state = LMI_ENABLED; break; /* * Default is not to change state. */ } p->lmi_state = sl->i_state; putnext(sl->rq, mp); return (1); } /* * LMI_ENABLE_CON * --------------------------------------------- */ static int lmi_enable_con(sl_t * sl) { mblk_t *mp; lmi_enable_con_t *p; ensure(sl->i_state == LMI_ENABLE_PENDING, return (-EFAULT)); if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((lmi_enable_con_t *) mp->b_wptr)++; p->lmi_primitive = LMI_ENABLE_CON; p->lmi_state = sl->i_state = LMI_ENABLED; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } rare(); return (-EBUSY); } /* * LMI_DISABLE_CON * --------------------------------------------- */ static int lmi_disable_con(sl_t * sl) { mblk_t *mp; lmi_disable_con_t *p; ensure(sl->i_state == LMI_DISABLE_PENDING, return (-EFAULT)); if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((lmi_disable_con_t *) mp->b_wptr)++; p->lmi_primitive = LMI_DISABLE_CON; p->lmi_state = sl->i_state = LMI_DISABLED; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } rare(); return (-EBUSY); } /* * LMI_OPTMGMT_ACK * --------------------------------------------- */ static int lmi_optmgmt_ack(sl_t * sl, ulong flags, void *opt_ptr, size_t opt_len) { mblk_t *mp; lmi_optmgmt_ack_t *p; if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PCPROTO; p = ((lmi_optmgmt_ack_t *) mp->b_wptr)++; p->lmi_primitive = LMI_OPTMGMT_ACK; p->lmi_opt_length = opt_len; p->lmi_opt_offset = opt_len ? sizeof(*p) : 0; p->lmi_mgmt_flags = flags; bcopy(opt_ptr, mp->b_wptr, opt_len); mp->b_wptr += opt_len; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } /* * LMI_ERROR_IND * --------------------------------------------- */ static int lmi_error_ind(sl_t * sl, long err) { mblk_t *mp; lmi_error_ind_t *p; if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PCPROTO; p = ((lmi_error_ind_t *) mp->b_wptr)++; p->lmi_primitive = LMI_ERROR_IND; p->lmi_errno = err < 0 ? -err : 0; p->lmi_reason = err < 0 ? LMI_SYSERR : err; p->lmi_state = sl->i_state; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } /* * LMI_STATS_IND * --------------------------------------------- */ static int lmi_stats_ind(sl_t * sl, ulong interval, ulong timestamp) { mblk_t *mp; lmi_stats_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((lmi_stats_ind_t *) mp->b_wptr)++; p->lmi_primitive = LMI_STATS_IND; p->lmi_interval = interval; p->lmi_timestamp = timestamp; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * LMI_EVENT_IND * --------------------------------------------- */ static int lmi_event_ind(sl_t * sl, ulong oid, ulong severity, void *inf_ptr, size_t inf_len) { mblk_t *mp; lmi_event_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p) + inf_len, BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((lmi_event_ind_t *) mp->b_wptr)++; p->lmi_primitive = LMI_EVENT_IND; p->lmi_objectid = oid; p->lmi_timestamp = jiffies; p->lmi_severity = severity; bcopy(mp->b_wptr, inf_ptr, inf_len); mp->b_wptr += inf_len; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_PDU_IND * --------------------------------------------- */ static int sl_pdu_ind(sl_t * sl, mblk_t * dp) { mblk_t *mp; sl_pdu_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_pdu_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_PDU_IND; mp->b_cont = dp; ptrace(("Delivering mp = %u\n", (uint) mp)); putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_LINK_CONGESTED_IND * --------------------------------------------- */ static int sl_link_congested_ind(sl_t * sl, ulong cong, ulong disc) { mblk_t *mp; sl_link_cong_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_link_cong_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_LINK_CONGESTED_IND; p->sl_timestamp = jiffies; p->sl_cong_status = cong; p->sl_disc_status = disc; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_LINK_CONGESTION_CEASED_IND * --------------------------------------------- */ static int sl_link_congestion_ceased_ind(sl_t * sl, ulong cong, ulong disc) { mblk_t *mp; sl_link_cong_ceased_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_link_cong_ceased_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_LINK_CONGESTION_CEASED_IND; p->sl_timestamp = jiffies; p->sl_cong_status = cong; p->sl_disc_status = disc; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_RETRIEVED_MESSAGE_IND * --------------------------------------------- */ static int sl_retrieved_message_ind(sl_t * sl, mblk_t * dp) { mblk_t *mp; sl_retrieved_msg_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_retrieved_msg_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_RETRIEVED_MESSAGE_IND; mp->b_cont = dp; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_RETRIEVAL_COMPLETE_IND * --------------------------------------------- */ static int sl_retrieval_complete_ind(sl_t * sl) { mblk_t *mp; sl_retrieval_comp_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_retrieval_comp_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_RETRIEVAL_COMPLETE_IND; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_RB_CLEARED_IND * --------------------------------------------- */ static int sl_rb_cleared_ind(sl_t * sl) { mblk_t *mp; sl_rb_cleared_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_rb_cleared_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_RB_CLEARED_IND; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_BSNT_IND * --------------------------------------------- */ static int sl_bsnt_ind(sl_t * sl, ulong bsnt) { mblk_t *mp; sl_bsnt_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_bsnt_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_BSNT_IND; p->sl_bsnt = bsnt; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_IN_SERVICE_IND * --------------------------------------------- */ static int sl_in_service_ind(sl_t * sl) { mblk_t *mp; sl_in_service_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_in_service_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_IN_SERVICE_IND; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_OUT_OF_SERVICE_IND * --------------------------------------------- */ static int sl_out_of_service_ind(sl_t * sl, ulong reason) { mblk_t *mp; sl_out_of_service_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_out_of_service_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_OUT_OF_SERVICE_IND; p->sl_timestamp = jiffies; p->sl_reason = reason; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_REMOTE_PROCESSOR_OUTAGE_IND * --------------------------------------------- */ static int sl_remote_processor_outage_ind(sl_t * sl) { mblk_t *mp; sl_rem_proc_out_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_rem_proc_out_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_REMOTE_PROCESSOR_OUTAGE_IND; p->sl_timestamp = jiffies; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_REMOTE_PROCESSOR_RECOVERED_IND * --------------------------------------------- */ static int sl_remote_processor_recovered_ind(sl_t * sl) { mblk_t *mp; sl_rem_proc_recovered_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_rem_proc_recovered_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_REMOTE_PROCESSOR_RECOVERED_IND; p->sl_timestamp = jiffies; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_RTB_CLEARED_IND * --------------------------------------------- */ static int sl_rtb_cleared_ind(sl_t * sl) { mblk_t *mp; sl_rtb_cleared_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_rtb_cleared_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_RTB_CLEARED_IND; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_RETRIEVAL_NOT_POSSIBLE_IND * --------------------------------------------- */ static int sl_retrieval_not_possible_ind(sl_t * sl) { mblk_t *mp; sl_retrieval_not_poss_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_retrieval_not_poss_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_RETRIEVAL_NOT_POSSIBLE_IND; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * SL_BSNT_NOT_RETRIEVABLE_IND * --------------------------------------------- */ static int sl_bsnt_not_retrievable_ind(sl_t * sl, ulong bsnt) { mblk_t *mp; sl_bsnt_not_retr_ind_t *p; if (canputnext(sl->rq)) { if ((mp = allocb(sizeof(*p), BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((sl_bsnt_not_retr_ind_t *) mp->b_wptr)++; p->sl_primitive = SL_BSNT_NOT_RETRIEVABLE_IND; p->sl_bsnt = bsnt; putnext(sl->rq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * ------------------------------------------------------------------------- * * NPI User (M2UA) -> NPI Provider (SCTP) Primitives * * ------------------------------------------------------------------------- * * N_DATA_REQ * --------------------------------------------- */ static int n_data_req(sl_t * sl, ulong flags, void *qos_ptr, size_t qos_len, mblk_t * dp) { mblk_t *mp; N_data_req_t *p; if (canputnext(sl->wq)) { if ((mp = allocb(sizeof(*p) + qos_len, BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((N_data_req_t *) mp->b_wptr)++; p->PRIM_type = N_DATA_REQ; p->DATA_xfer_flags = flags; bcopy(qos_ptr, mp->b_wptr, qos_len); mp->b_wptr += qos_len; mp->b_cont = dp; putnext(sl->wq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * N_EXDATA_REQ * --------------------------------------------- */ static int n_exdata_req(sl_t * sl, void *qos_ptr, size_t qos_len, mblk_t * dp) { mblk_t *mp; N_exdata_req_t *p; if (bcanputnext(sl->wq, 1)) { if ((mp = allocb(sizeof(*p) + qos_len, BPRI_MED))) { mp->b_datap->db_type = M_PROTO; p = ((N_exdata_req_t *) mp->b_wptr)++; p->PRIM_type = N_EXDATA_REQ; bcopy(qos_ptr, mp->b_wptr, qos_len); mp->b_wptr += qos_len; mp->b_cont = dp; putnext(sl->wq, mp); return (0); } rare(); return (-ENOBUFS); } seldom(); return (-EBUSY); } /* * ------------------------------------------------------------------------- * * SL Peer (M2UA) -> SL Peer Sent Messages * * ------------------------------------------------------------------------- * * M2UA SEND PROVING * --------------------------------------------- */ static int sl_send_proving(sl_t * sl, size_t plen) { int err; mblk_t *mp; N_qos_sel_data_sctp_t qos = { N_QOS_SEL_DATA_SCTP, M2UA_PPI, M2UA_DATA_STREAM, }; if ((mp = allocb(2 * sizeof(uint32_t) + plen, BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = M2UA_PROVING_MESSAGE; *((uint32_t *) mp->b_wptr)++ = __constant_htonl(2 * sizeof(uint32_t) + plen); fixme(("We should include a test pattern.\n")); bzero(mp->b_wptr, plen); mp->b_wptr += plen; if (!(err = n_data_req(sl, 0, &qos, sizeof(qos), mp))) return (0); freeb(mp); return (err); } return (-ENOBUFS); } /* * M2UA SEND STATUS * --------------------------------------------- */ static int sl_send_status(sl_t * sl, uint32_t status) { int err; mblk_t *mp; N_qos_sel_data_sctp_t qos = { N_QOS_SEL_DATA_SCTP, M2UA_PPI, M2UA_STATUS_STREAM, }; if ((mp = allocb(3 * sizeof(uint32_t), BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = M2UA_STATUS_MESSAGE; *((uint32_t *) mp->b_wptr)++ = __constant_htonl(3 * sizeof(uint32_t)); *((uint32_t *) mp->b_wptr)++ = status; if (!(err = n_data_req(sl, 0, &qos, sizeof(qos), mp))) return (0); assert(mp->b_datap->db_ref); freeb(mp); return (err); } return (-ENOBUFS); } /* * M2UA SEND ACK * --------------------------------------------- */ static int sl_send_ack(sl_t * sl, ulong count) { int err; mblk_t *mp; N_qos_sel_data_sctp_t qos = { N_QOS_SEL_DATA_SCTP, M2UA_PPI, M2UA_DATA_STREAM, }; if ((mp = allocb(3 * sizeof(uint32_t), BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = M2UA_ACK_MESSAGE; *((uint32_t *) mp->b_wptr)++ = __constant_htonl(3 * sizeof(uint32_t)); *((uint32_t *) mp->b_wptr)++ = htonl(count); if ((err = n_exdata_req(sl, &qos, sizeof(qos), mp))) { assert(mp->b_datap->db_ref); freeb(mp); return (err); } return (0); } return (-ENOBUFS); } /* * M2UA SEND DATA * --------------------------------------------- */ static int sl_send_data(sl_t * sl, mblk_t * dp) { int err; mblk_t *mp, *db; ulong rcpt = sl->version < M2UA_VERSION_DRAFT4 ? N_RC_FLAG : 0; size_t dlen = msgdsize(dp); N_qos_sel_data_sctp_t qos = { N_QOS_SEL_DATA_SCTP, M2UA_PPI, M2UA_DATA_STREAM, }; if (!(db = dupmsg(dp))) return (-ENOBUFS); if ((mp = allocb(2 * sizeof(uint32_t), BPRI_MED))) { mp->b_datap->db_type = M_DATA; *((uint32_t *) mp->b_wptr)++ = M2UA_DATA_MESSAGE; *((uint32_t *) mp->b_wptr)++ = __constant_htonl(dlen + 2 * sizeof(uint32_t)); mp->b_cont = db; pullupmsg(mp, -1); if ((err = n_data_req(sl, rcpt, &qos, sizeof(qos), mp))) { assert(mp->b_datap->db_ref); freemsg(mp); return (err); } return (0); } freemsg(db); return (-ENOBUFS); } /* * ========================================================================= * * M2UA State Machines * * ========================================================================= */ /* * ========================================================================= * * INPUT Events * * ========================================================================= */ /* * ------------------------------------------------------------------------- * * SL Peer -> SL Peer (M2UA) Received Messages * * ------------------------------------------------------------------------- */ static int m2ua_attach_req(sl_t * sl, mblk_t * mp) { } static int m2ua_clear_buffers(sl_t * sl, mblk_t * mp) { } static int m2ua_clear_rtb(sl_t * sl, mblk_t * mp) { } static int m2ua_congestion_accept(sl_t * sl, mblk_t * mp) { } static int m2ua_congestion_discard(sl_t * sl, mblk_t * mp) { } static int m2ua_detach_req(sl_t * sl, mblk_t * mp) { } static int m2ua_disable(sl_t * sl, mblk_t * mp) { } static int m2ua_emergency_ceases(sl_t * sl, mblk_t * mp) { } static int m2ua_emergency(sl_t * sl, mblk_t * mp) { } static int m2ua_enable(sl_t * sl, mblk_t * mp) { } static int m2ua_local_processor_outage(sl_t * sl, mblk_t * mp) { } static int m2ua_no_congestion(sl_t * sl, mblk_t * mp) { } static int m2ua_power_on(sl_t * sl, mblk_t * mp) { } static int m2ua_recv_msg(sl_t * sl, mblk_t * mp) { } static int m2ua_recv_msg(sl_t * sl, mblk_t * mp) { } static int m2ua_resume(sl_t * sl, mblk_t * mp) { } static int m2ua_retrieval_request_and_fsnc(sl_t * sl, mblk_t * mp, ulong fsnc) { } static int m2ua_retrieve_bsnt(sl_t * sl, mblk_t * mp) { } static int m2ua_send_msg(sl_t * sl, mblk_t * mp) { } static int m2ua_start(sl_t * sl, mblk_t * mp) { } static int m2ua_stop(sl_t * sl, mblk_t * mp) { } /* * ========================================================================= */ /* * ------------------------------------------------------------------------- * * SL User -> SL Provider (M2UA) Primitives * * ------------------------------------------------------------------------- * * LMI_INFO_REQ * --------------------------------------------- */ static int lmi_info_req(sl_t * sl, mblk_t * mp) { (void) mp; return lmi_info_ack(sl); } /* * LMI_ATTACH_REQ * --------------------------------------------- */ static int lmi_attach_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; lmi_attach_req_t *p = (lmi_attach_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { if (sl->i_state == LMI_UNATTACHED) { sl->i_state = LMI_ATTACH_PENDING; return m2ua_attach_req(sl, mp); } seldom(); err = LMI_OUTSTATE; break; /* would place interface out of state */ } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return lmi_error_ack(sl, LMI_ATTACH_REQ, err, mp); } /* * LMI_DETACH_REQ * --------------------------------------------- */ static int lmi_detach_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; lmi_detach_req_t *p = (lmi_detach_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { if (sl->i_state == LMI_DISABLED) { sl->i_state = LMI_DETACH_PENDING; return m2ua_detach_req(sl, mp); } seldom(); err = LMI_OUTSTATE; break; /* would place interface out of state */ } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return lmi_error_ack(sl, LMI_DETACH_REQ, err, mp); } /* * LMI_ENABLE_REQ * --------------------------------------------- */ static int lmi_enable_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; lmi_enable_req_t *p = (lmi_enable_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { if (sl->i_state == LMI_DISABLED) { sl->i_state = LMI_ENABLE_PENDING; return m2ua_enable(sl, mp); } seldom(); err = LMI_OUTSTATE; break; /* would place interface out of state */ } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return lmi_error_ack(sl, LMI_ENABLE_REQ, err, mp); } /* * LMI_DISABLE_REQ * --------------------------------------------- */ static int lmi_disable_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; lmi_disable_req_t *p = (lmi_disable_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { if (sl->i_state == LMI_ENABLE_PENDING) { sl->i_state = LMI_DISABLED; return lmi_disable_con(sl, mp); } if (sl->i_state == LMI_ENABLED) { sl->i_state = LMI_DISABLE_PENDING; return m2ua_disable(sl, mp); } seldom(); err = LMI_OUTSTATE; break; /* would place interface out of state */ } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return lmi_error_ack(sl, LMI_DISABLE_REQ, err, mp); } /* * LMI_OPTMGMT_REQ * --------------------------------------------- */ static int lmi_optmgmt_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; lmi_optmgmt_req_t *p = (lmi_optmgmt_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { lmi_error_ack(sl, LMI_OPTMGMT_REQ, LMI_NOTSUPP, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return lmi_error_ack(sl, LMI_OPTMGMT_REQ, err, mp); } /* * SL_PDU_REQ * --------------------------------------------- */ #ifndef abs #define abs(x) ((x)<0 ? -(x):(x)) #endif static int m_error_reply(sl_t * sl, int err, mblk_t * mp) { mp->b_datap->db_type = M_ERROR; mp->b_wptr = mp->b_rptr; *(mp->b_wptr)++ = abs(err); *(mp->b_wptr)++ = abs(err); putnext(sl->rq, mp); return (1); } static int sl_pdu_req(sl_t * sl, mblk_t * mp) { int err; mblk_t *dp; size_t mlen = mp->b_wptr - mp->b_rptr; sl_pdu_req_t *p = (sl_pdu_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { if ((dp = mp->b_cont)) { if ((err = m2pa_send_msg(sl, dp))) return (err); mp->b_cont = NULL; /* data absorbed */ return (0); } seldom(); err = LMI_BADPRIM; break; /* No M_DATA block */ } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_EMERGENCY_REQ * --------------------------------------------- */ static int sl_emergency_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_emergency_req_t *p = (sl_emergency_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_emergency(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_EMERGENCY_CEASES_REQ * --------------------------------------------- */ static int sl_emergency_ceases_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_emergency_ceases_req_t *p = (sl_emergency_ceases_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_emergency_ceases(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_START_REQ * --------------------------------------------- */ static int sl_start_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_start_req_t *p = (sl_start_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_start(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_STOP_REQ * --------------------------------------------- */ static int sl_stop_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_stop_req_t *p = (sl_stop_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_stop(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_RETRIEVE_BSNT_REQ * --------------------------------------------- */ static int sl_retrieve_bsnt_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_retrieve_bsnt_req_t *p = (sl_retrieve_bsnt_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_retrieve_bsnt(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_RETRIEVAL_REQUEST_AND_FSNC_REQ * --------------------------------------------- */ static int sl_retrieval_request_and_fsnc_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_retrieval_req_and_fsnc_t *p = (sl_retrieval_req_and_fsnc_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_retrieval_request_and_fsnc(sl, mp, p->sl_fsnc); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_RESUME_REQ * --------------------------------------------- */ static int sl_resume_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_resume_req_t *p = (sl_resume_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_resume(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_CLEAR_BUFFERS_REQ * --------------------------------------------- */ static int sl_clear_buffers_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_clear_buffers_req_t *p = (sl_clear_buffers_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_clear_buffers(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_CLEAR_RTB_REQ * --------------------------------------------- */ static int sl_clear_rtb_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_clear_rtb_req_t *p = (sl_clear_rtb_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_clear_rtb(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_LOCAL_PROCESSOR_OUTAGE_REQ * --------------------------------------------- */ static int sl_local_processor_outage_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_local_proc_outage_req_t *p = (sl_local_proc_outage_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_local_processor_outage(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_CONGESTION_DISCARD_REQ * --------------------------------------------- */ static int sl_congestion_discard_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_cong_discard_req_t *p = (sl_cong_discard_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_congestion_discard(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_CONGESTION_ACCEPT_REQ * --------------------------------------------- */ static int sl_congestion_accept_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_cong_accept_req_t *p = (sl_cong_accept_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_congestion_accept(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_NO_CONGESTION_REQ * --------------------------------------------- */ static int sl_no_congestion_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_no_cong_req_t *p = (sl_no_cong_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_no_congestion(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * SL_POWER_ON_REQ * --------------------------------------------- */ static int sl_power_on_req(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; sl_power_on_req_t *p = (sl_power_on_req_t *) mp->b_rptr; do { if (mlen >= sizeof(*p)) { return m2ua_power_on(sl, mp); } seldom(); err = LMI_PROTOSHORT; break; /* M_PROTO block too short */ } while (0); seldom(); return m_error_reply(sl, err, mp); } /* * ------------------------------------------------------------------------- * * NPI Provider -> NPI User (M2UA) Primitives * * ------------------------------------------------------------------------- * * N_DATA_IND * --------------------------------------------- */ static int n_data_ind(sl_t * sl, mblk_t * mp) { int err; mblk_t *dp; size_t mlen = mp->b_wptr - mp->b_rptr; N_data_ind_t *p = (N_data_ind_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); if ((dp = mp->b_cont)) { if (sl->i_state == LMI_ENABLED) { if ((err = m2ua_recv_msg(sl, dp))) return (err); mp->b_cont = NULL; /* absorbed data */ return (0); } rare(); return (-EPROTO); /* ignore data in other states */ } rare(); return (-EFAULT); } /* * N_EXDATA_IND * --------------------------------------------- */ static int n_exdata_ind(sl_t * sl, mblk_t * mp) { int err; mblk_t *dp; size_t mlen = mp->b_wptr - mp->b_rptr; N_exdata_ind_t *p = (N_exdata_ind_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); if ((dp = mp->b_cont)) { if (sl->i_state == LMI_ENABLED) { if ((err = m2ua_recv_msg(sl, dp))) return (err); mp->b_cont = NULL; /* absorbed data */ return (0); } rare(); return (-EPROTO); /* ignore data in other states */ } rare(); return (-EFAULT); } /* * N_DATACK_IND * --------------------------------------------- */ static int n_datack_ind(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; N_datack_ind_t *p = (N_datack_ind_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); return (0); rare(); return (-EFAULT); /* shouldn't be getting these */ } /* * N_DISCON_IND * --------------------------------------------- */ static int n_discon_ind(sl_t * sl, mblk_t * mp) { int err; size_t mlen = mp->b_wptr - mp->b_rptr; N_discon_ind_t *p = (N_discon_ind_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); if ((err = sl_lsc_out_of_service(sl, SL_FAIL_SUERM_EIM))) return (err); if (sl->notify.events & SL_EVT_FAIL_SUERM_EIM) if ((err = lmi_event_ind(sl, SL_EVT_FAIL_SUERM_EIM, 0, NULL, 0))) return (err); ptrace(("Link failed: SUERM/EIM\n")); fixme(("Do something here... send a HANGUP or something...\n")); return (0); } /* * N_RESET_IND * --------------------------------------------- */ static int n_reset_ind(sl_t * sl, mblk_t * mp) { size_t mlen = mp->b_wptr - mp->b_rptr; N_reset_ind_t *p = (N_reset_ind_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); fixme(("Do something here...\n")); return (-EFAULT); } /* * N_CONN_IND * --------------------------------------------- */ static int n_conn_ind(sl_t * sl, mblk_t * mp) { size_t mlen = mp->b_wptr - mp->b_rptr; N_conn_ind_t *p = (N_conn_ind_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); fixme(("Do something here...\n")); return (-EFAULT); } /* * N_CONN_RES * --------------------------------------------- */ static int n_conn_req(sl_t * sl, mblk_t * mp) { size_t mlen = mp->b_wptr - mp->b_rptr; N_conn_req_t *p = (N_conn_req_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); fixme(("Do something here...\n")); return (-EFAULT); } /* * N_INFO_ACK * --------------------------------------------- */ static int n_info_ack(sl_t * sl, mblk_t * mp) { size_t mlen = mp->b_wptr - mp->b_rptr; N_info_ack_t *p = (N_info_ack_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); fixme(("Do something here...\n")); return (-EFAULT); } /* * N_BIND_ACK * --------------------------------------------- */ static int n_bind_ack(sl_t * sl, mblk_t * mp) { size_t mlen = mp->b_wptr - mp->b_rptr; N_bind_ack_t *p = (N_bind_ack_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); fixme(("Do something here...\n")); return (-EFAULT); } /* * N_OK_ACK * --------------------------------------------- */ static int n_ok_ack(sl_t * sl, mblk_t * mp) { size_t mlen = mp->b_wptr - mp->b_rptr; N_ok_ack_t *p = (N_ok_ack_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); fixme(("Do something here...\n")); return (-EFAULT); } /* * N_ERROR_ACK * --------------------------------------------- */ static int n_error_ack(sl_t * sl, mblk_t * mp) { size_t mlen = mp->b_wptr - mp->b_rptr; N_error_ack_t *p = (N_error_ack_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); fixme(("Do something here...\n")); return (-EFAULT); } /* * N_RESET_CON * --------------------------------------------- */ static int n_reset_con(sl_t * sl, mblk_t * mp) { size_t mlen = mp->b_wptr - mp->b_rptr; N_other_ind_t *p = (N_other_ind_t *) mp->b_rptr; ensure(mlen >= sizeof(*p), return (-EFAULT)); fixme(("Do something here...\n")); return (-EFAULT); } /* * ========================================================================= * * STREAMS Message Handling * * ========================================================================= */ /* * ------------------------------------------------------------------------- * * M_IOCDATA Handling * * ------------------------------------------------------------------------- */ static sl_w_iocdata(queue_t * q, mblk_t * mp) { (void) q; (void) mp; return (4); } /* * ------------------------------------------------------------------------- * * M_IOCTL Handling * * ------------------------------------------------------------------------- */ static int sl_w_ioctl(queue_t * q, mblk_t * mp) { sl_t *sl = (sl_t *) q->q_ptr; struct iocblk *iocp = (struct iocblk *) mp->b_rptr; switch (_IOC_TYPE(iocp->ioc_cmd)) { default: return (4); case __SID: case SL_IOC_MAGIC: case SDT_IOC_MAGIC: case SDL_IOC_MAGIC: case DEV_IOC_MAGIC: break; } mp->b_datap->db_type = M_IOCNAK; iocp->ioc_error = EOPNOTSUPP; iocp->ioc_rval = -1; qreply(q, mp); return (1); } /* * ------------------------------------------------------------------------- * * M_PROTO, M_PCPROTO Handling * * ------------------------------------------------------------------------- */ static int sl_w_proto(queue_t * q, mblk_t * mp) { int rtn; sl_t *sl = (sl_t *) q->q_ptr; ulong oldstate = sl->i_state; switch (*((ulong *) mp->b_rptr)) { case LMI_INFO_REQ: rtn = lmi_info_req(sl, mp); break; case LMI_ATTACH_REQ: rtn = lmi_attach_req(sl, mp); break; case LMI_DETACH_REQ: rtn = lmi_detach_req(sl, mp); break; case LMI_ENABLE_REQ: rtn = lmi_enable_req(sl, mp); break; case LMI_DISABLE_REQ: rtn = lmi_disable_req(sl, mp); break; case LMI_OPTMGMT_REQ: rtn = lmi_optmgmt_req(sl, mp); break; case SL_PDU_REQ: rtn = sl_pdu_req(sl, mp); break; case SL_EMERGENCY_REQ: rtn = sl_emergency_req(sl, mp); break; case SL_EMERGENCY_CEASES_REQ: rtn = sl_emergency_ceases_req(sl, mp); break; case SL_START_REQ: rtn = sl_start_req(sl, mp); break; case SL_STOP_REQ: rtn = sl_stop_req(sl, mp); break; case SL_RETRIEVE_BSNT_REQ: rtn = sl_retrieve_bsnt_req(sl, mp); break; case SL_RETRIEVAL_REQUEST_AND_FSNC_REQ: rtn = sl_retrieval_request_and_fsnc_req(sl, mp); break; case SL_RESUME_REQ: rtn = sl_resume_req(sl, mp); break; case SL_CLEAR_BUFFERS_REQ: rtn = sl_clear_buffers_req(sl, mp); break; case SL_CLEAR_RTB_REQ: rtn = sl_clear_rtb_req(sl, mp); break; case SL_LOCAL_PROCESSOR_OUTAGE_REQ: rtn = sl_local_processor_outage_req(sl, mp); break; case SL_CONGESTION_DISCARD_REQ: rtn = sl_congestion_discard_req(sl, mp); break; case SL_CONGESTION_ACCEPT_REQ: rtn = sl_congestion_accept_req(sl, mp); break; case SL_NO_CONGESTION_REQ: rtn = sl_no_congestion_req(sl, mp); break; case SL_POWER_ON_REQ: rtn = sl_power_on_req(sl, mp); break; default: rtn = -EOPNOTSUPP; break; } if (rtn < 0) { seldom(); sl->i_state = oldstate; } return (rtn); } static int sl_r_proto(queue_t * q, mblk_t * mp) { int rtn; sl_t *sl = (sl_t *) q->q_ptr; switch (*((ulong *) mp->b_rptr)) { case N_DATA_IND: rtn = n_data_ind(sl, mp); break; case N_EXDATA_IND: rtn = n_exdata_ind(sl, mp); break; case N_DATACK_IND: rtn = n_datack_ind(sl, mp); break; case N_DISCON_IND: rtn = n_discon_ind(sl, mp); break; case N_RESET_IND: rtn = n_reset_ind(sl, mp); break; case N_CONN_IND: rtn = n_conn_ind(sl, mp); break; case N_CONN_RES: rtn = n_conn_req(sl, mp); break; case N_INFO_ACK: rtn = n_info_ack(sl, mp); break; case N_BIND_ACK: rtn = n_bind_ack(sl, mp); break; case N_OK_ACK: rtn = n_ok_ack(sl, mp); break; case N_ERROR_ACK: rtn = n_error_ack(sl, mp); break; case N_RESET_CON: rtn = n_reset_con(sl, mp); break; default: rtn = -EOPNOTSUPP; break; } if (rtn < 0) { seldom(); } return (rtn); } /* * ------------------------------------------------------------------------- * * M_DATA Handling * * ------------------------------------------------------------------------- */ static int sl_w_data(queue_t * q, mblk_t * mp) { sl_t *sl = (sl_t *) q->q_ptr; return m2ua_send_msg(sl, mp); } static int sl_r_data(queue_t * q, mblk_t * mp) { sl_t *sl = (sl_t *) q->q_ptr; return m2ua_recv_msg(sl, mp); } /* * ------------------------------------------------------------------------- * * M_CTL Handling (Events) * * ------------------------------------------------------------------------- */ static int sl_r_ctl(queue_t * q, mblk_t * mp) { (void) q; (void) mp; return (4); } /* * ------------------------------------------------------------------------- * * M_ERROR Handling * * ------------------------------------------------------------------------- */ static int sl_r_error(queue_t * q, mblk_t * mp) { (void) q; (void) mp; return (4); } /* * ------------------------------------------------------------------------- * * M_HANGUP Handling * * ------------------------------------------------------------------------- */ static int sl_r_hangup(queue_t * q, mblk_t * mp) { (void) q; (void) mp; return (0); } /* * ------------------------------------------------------------------------- * * M_FLUSH Handling * * ------------------------------------------------------------------------- */ static int sl_w_flush(queue_t * q, mblk_t * mp) { (void) q; (void) mp; return (3); } static int sl_r_flush(queue_t * q, mblk_t * mp) { (void) q; (void) mp; return (3); } /* * ------------------------------------------------------------------------- * * Other messages (e.g. M_IOCACK) * * ------------------------------------------------------------------------- */ static int sl_w_other(queue_t * q, mblk_t * mp) { (void) q; (void) mp; return (4); } static int sl_r_other(queue_t * q, mblk_t * mp) { (void) q; (void) mp; return (4); } /* * ========================================================================= * * PUT and SRV * * ========================================================================= */ static INT sl_wput(queue_t * q, mblk_t * mp) { int rtn; sl_t *sl = (sl_t *) q->q_ptr; ensure(q, return ((INT) (-EFAULT))); ensure(sl, return ((INT) (-EFAULT))); ensure(mp, return ((INT) (-EFAULT))); switch (mp->b_datap->db_type) { case M_DATA: rtn = sl_w_data(q, mp); break; case M_PROTO: case M_PCPROTO: rtn = sl_w_proto(q, mp); break; case M_FLUSH: rtn = sl_w_flush(q, mp); break; case M_IOCTL: rtn = sl_w_ioctl(q, mp); break; case M_IOCDATA: rtn = sl_w_iocdata(q, mp); break; default: rtn = sl_w_other(q, mp); break; } switch (rtn) { case 0: freemsg(mp); case 1: break; case 2: freeb(mp); break; case 3: case 4: putnext(q, mp); break; default: ptrace(("Error = %d\n", rtn)); freemsg(mp); return (INT) (rtn); } return (INT) (0); } static INT sl_rput(queue_t * q, mblk_t * mp) { int rtn = 0; sl_t *sl = (sl_t *) q->q_ptr; ensure(q, return ((INT) (-EFAULT))); ensure(sl, return ((INT) (-EFAULT))); ensure(mp, return ((INT) (-EFAULT))); switch (mp->b_datap->db_type) { case M_DATA: rtn = sl_r_data(q, mp); break; case M_PROTO: case M_PCPROTO: rtn = sl_r_proto(q, mp); break; case M_CTL: rtn = sl_r_ctl(q, mp); break; case M_ERROR: rtn = sl_r_error(q, mp); break; case M_FLUSH: rtn = sl_r_flush(q, mp); break; case M_HANGUP: rtn = sl_r_hangup(q, mp); break; default: rtn = sl_r_other(q, mp); break; } switch (rtn) { case 0: freemsg(mp); case 1: break; case 2: freeb(mp); break; case 3: case 4: putnext(q, mp); break; default: ptrace(("Error = %d\n", rtn)); freemsg(mp); return (INT) (rtn); } return (INT) (0); } /* * ========================================================================= * * Private Structure allocation, deallocation and cache * * ========================================================================= */ kmem_cache_t *sl_cachep = NULL; static void sl_init_caches(void) { if (!sl_cachep && !(sl_cachep = kmem_cache_create("sl_cachep", sizeof(sl_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL))) panic("%s:Cannot alloc sl_cachep.\n", __FUNCTION__); return; } static void sl_term_caches(void) { if (sl_cachep) if (kmem_cache_destroy(sl_cachep)) cmn_err(CE_PANIC, "m2ua: couldn't destroy sl_cachep\n"); return; } static sl_t *sl_alloc_priv(queue_t * q) { sl_t *sl; if ((sl = kmem_cache_alloc(sl_cachep, SLAB_ATOMIC))) { bzero(sl, sizeof(*sl)); RD(q)->q_ptr = WR(q)->q_ptr = sl; sl->rq = RD(q); sl->wq = WR(q); sl->i_state = LMI_DISABLED; } return (sl); } static void sl_free_priv(queue_t * q) { sl_t *sl = (sl_t *) q->q_ptr; kmem_cache_free(sl_cachep, sl); return; } /* * ========================================================================= * * OPEN and CLOSE * * ========================================================================= */ static int sl_open(queue_t * q, dev_t * devp, int flag, int sflag, cred_t * crp) { (void) crp; /* for now */ if (q->q_ptr != NULL) /* already open */ return (0); if (sflag == MODOPEN || WR(q)->q_next != NULL) { fixme(("Check module we are being pushed over.\n")); if (!(sl_alloc_priv(q))) return ENOMEM; return (0); } return EIO; } static int sl_close(queue_t * q, int flag, cred_t * crp) { (void) flag; (void) crp; sl_free_priv(q); return (0); } /* * ========================================================================= * * Lis Module Initialization * * ========================================================================= */ void sl_init(void) { int modnum; unless(sl_minfo.mi_idnum, return); cmn_err(CE_NOTE, M2UA_BANNER); /* console splash */ sl_init_caches(); if (!(modnum = lis_register_strmod(&sl_info, sl_minfo.mi_idname))) { sl_minfo.mi_idnum = 0; rare(); cmn_err(CE_NOTE, "m2ua: couldn't register as module\n"); return; } sl_minfo.mi_idnum = modnum; return; } void sl_terminate(void) { ensure(sl_minfo.mi_idnum, return); if ((sl_minfo.mi_idnum = lis_unregister_strmod(&sl_info))) cmn_err(CE_WARN, "m2ua: couldn't unregister as module!\n"); sl_term_caches(); return; } /* * ========================================================================= * * Kernel Module Initialization * * ========================================================================= */ int init_module(void) { sl_init(); return (0); } void cleanup_module(void) { sl_terminate(); return; }
|
|||||||||||||||||||||||||||
OpenSS7 SS7 for the Common Man |
Home | Overview | Status | News | Documentation | Resources | About | ||||||||||||||||||||
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |