static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); unsigned short segnum; struct dn_skb_cb *cb = DN_SKB_CB(skb); int queued = 0; if (skb->len < 2) goto out; cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data); skb_pull(skb, 2); if (seq_next(scp->numoth_rcv, segnum)) { if (dn_queue_skb(sk, skb, SIGURG, &scp->other_receive_queue) == 0) { seq_add(&scp->numoth_rcv, 1); scp->other_report = 0; queued = 1; } } dn_nsp_send_oth_ack(sk); out: if (!queued) kfree_skb(skb); }
static void dn_nsp_data(struct sock *sk, struct sk_buff *skb) { int queued = 0; unsigned short segnum; struct dn_skb_cb *cb = DN_SKB_CB(skb); struct dn_scp *scp = DN_SK(sk); if (skb->len < 2) goto out; cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data); skb_pull(skb, 2); if (seq_next(scp->numdat_rcv, segnum)) { if (dn_queue_skb(sk, skb, SIGIO, &sk->sk_receive_queue) == 0) { seq_add(&scp->numdat_rcv, 1); queued = 1; } if ((scp->flowloc_sw == DN_SEND) && dn_congested(sk)) { scp->flowloc_sw = DN_DONTSEND; dn_nsp_send_link(sk, DN_DONTSEND, 0); } } dn_nsp_send_data_ack(sk); out: if (!queued) kfree_skb(skb); }
static __le16 *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); __le16 *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth); if (unlikely(oth)) { cb->segnum = scp->numoth; seq_add(&scp->numoth, 1); } else { cb->segnum = scp->numdat; seq_add(&scp->numdat, 1); } *(ptr++) = cpu_to_le16(cb->segnum); return ptr; }
static int RoErrorRequestAux (struct assocblk *acb, int invokeID, int error, PE params, int priority, struct RoSAPindication *roi) { PE pe, p; if ((acb -> acb_flags & ACB_INIT) && (acb -> acb_flags & ACB_ROS)) return rosaplose (roi, ROS_OPERATION, NULLCP, "not responder"); if (!(acb -> acb_flags & ACB_ACS)) { missingP (params); } if (acb -> acb_ready && !(acb -> acb_flags & ACB_TURN) && (*acb -> acb_ready) (acb, priority, roi) == NOTOK) return NOTOK; /* begin Error APDU */ if ((pe = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, APDU_ERROR)) == NULLPE || ((acb -> acb_flags & ACB_ACS) ? (p = pe, 0) : set_add (pe, p = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_CONS_SEQ)) == NOTOK) || seq_add (p, int2prim (invokeID), -1) == NOTOK || seq_add (p, int2prim (error), -1) == NOTOK || (params && seq_add (p, params, -1) == NOTOK)) { if (pe) { if (params) pe_extract (pe, params); pe_free (pe); } freeacblk (acb); return rosaplose (roi, ROS_CONGEST, NULLCP, "out of memory"); } /* end Error APDU */ return (*acb -> acb_putosdu) (acb, pe, params, priority, roi); }
int RoURejectRequestAux (struct assocblk *acb, int *invokeID, int reason, int id, int priority, struct RoSAPindication *roi) { PE pe, p; if (id == REJECT_COMPLETE) if (acb -> acb_flags & ACB_ACS) id = REJECT_INVOKE; else return rosaplose (roi, ROS_PARAMETER, NULLCP, "bad value for reason parameter"); if (acb -> acb_ready && !(acb -> acb_flags & ACB_TURN) && (*acb -> acb_ready) (acb, priority, roi) == NOTOK) return NOTOK; /* begin Reject APDU */ if ((pe = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, APDU_REJECT)) == NULLPE || ((acb -> acb_flags & ACB_ACS) ? (p = pe, 0) : set_add (pe, p = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_CONS_SEQ)) == NOTOK) || seq_add (p, invokeID ? int2prim (*invokeID) : pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL), -1) == NOTOK || seq_add (p, num2prim ((integer) reason, PE_CLASS_CONT, id), -1) == NOTOK) { if (pe) pe_free (pe); freeacblk (acb); return rosaplose (roi, ROS_CONGEST, NULLCP, "out of memory"); } /* end Reject APDU */ return (*acb -> acb_putosdu) (acb, pe, NULLPE, priority, roi); }
static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); unsigned short segnum; unsigned char lsflags; signed char fcval; int wake_up = 0; char *ptr = skb->data; unsigned char fctype = scp->services_rem & NSP_FC_MASK; if (skb->len != 4) goto out; segnum = le16_to_cpu(*(__le16 *)ptr); ptr += 2; lsflags = *(unsigned char *)ptr++; fcval = *ptr; /* * Here we ignore erronous packets which should really * should cause a connection abort. It is not critical * for now though. */ if (lsflags & 0xf8) goto out; if (seq_next(scp->numoth_rcv, segnum)) { seq_add(&scp->numoth_rcv, 1); switch(lsflags & 0x04) { /* FCVAL INT */ case 0x00: /* Normal Request */ switch(lsflags & 0x03) { /* FCVAL MOD */ case 0x00: /* Request count */ if (fcval < 0) { unsigned char p_fcval = -fcval; if ((scp->flowrem_dat > p_fcval) && (fctype == NSP_FC_SCMC)) { scp->flowrem_dat -= p_fcval; } } else if (fcval > 0) { scp->flowrem_dat += fcval; wake_up = 1; } break; case 0x01: /* Stop outgoing data */ scp->flowrem_sw = DN_DONTSEND; break; case 0x02: /* Ok to start again */ scp->flowrem_sw = DN_SEND; dn_nsp_output(sk); wake_up = 1; } break; case 0x04: /* Interrupt Request */ if (fcval > 0) { scp->flowrem_oth += fcval; wake_up = 1; } break; } if (wake_up && !sock_flag(sk, SOCK_DEAD)) sk->sk_state_change(sk); } dn_nsp_send_oth_ack(sk); out: kfree_skb(skb); }
static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb) { struct dn_scp *scp = DN_SK(sk); unsigned short segnum; unsigned char lsflags; signed char fcval; int wake_up = 0; char *ptr = skb->data; unsigned char fctype = scp->services_rem & NSP_FC_MASK; if (skb->len != 4) goto out; segnum = le16_to_cpu(*(__le16 *)ptr); ptr += 2; lsflags = *(unsigned char *)ptr++; fcval = *ptr; if (lsflags & 0xf8) goto out; if (seq_next(scp->numoth_rcv, segnum)) { seq_add(&scp->numoth_rcv, 1); switch(lsflags & 0x04) { case 0x00: switch(lsflags & 0x03) { case 0x00: if (fcval < 0) { unsigned char p_fcval = -fcval; if ((scp->flowrem_dat > p_fcval) && (fctype == NSP_FC_SCMC)) { scp->flowrem_dat -= p_fcval; } } else if (fcval > 0) { scp->flowrem_dat += fcval; wake_up = 1; } break; case 0x01: scp->flowrem_sw = DN_DONTSEND; break; case 0x02: scp->flowrem_sw = DN_SEND; dn_nsp_output(sk); wake_up = 1; } break; case 0x04: if (fcval > 0) { scp->flowrem_oth += fcval; wake_up = 1; } break; } if (wake_up && !sock_flag(sk, SOCK_DEAD)) sk->sk_state_change(sk); } dn_nsp_send_oth_ack(sk); out: kfree_skb(skb); }
static int RoResultRequestAux (struct assocblk *acb, int invokeID, int op, PE result, int priority, struct RoSAPindication *roi) { PE pe, p, q; if ((acb -> acb_flags & ACB_INIT) && (acb -> acb_flags & ACB_ROS)) return rosaplose (roi, ROS_OPERATION, NULLCP, "not responder"); if (!(acb -> acb_flags & ACB_ACS)) { missingP (result); } if (acb -> acb_ready && !(acb -> acb_flags & ACB_TURN) && (*acb -> acb_ready) (acb, priority, roi) == NOTOK) return NOTOK; #ifdef notyet if (!(acb -> acb_flags & ACB_ACS)) { /* want OPDU */ struct type_ROS_OPDU opdu; struct type_ROS_ReturnResult rrs; struct type_ROS_InvokeIDType idtyp; opdu.offset = type_ROS_OPDU_2; opdu.un.choice_ROS_9 = &rrs; rrs.invokeID = &idtyp; rrs.result = result; idtyp.parm = invokeID; if (encode_ROS_OPDU(&pe, 1, 0, NULL, &opdu) == NOTOK) { abort(); goto fail; } } else { struct type_ROS_ROSEapdus apdu; struct type_ROS_RORSapdu ras; struct type_ROS_InvokeIDType idtyp; struct element_ROS_1 el1; struct type_ROS_Operation ops; apdu.offset = type_ROS_ROSEapdus_rors__apdu; apdu.un.rors__apdu = &ras; idtyp.parm = invokeID; ras.invokeID = &idtyp; if (result) { ras.element_ROS_0 = &el1; el1.operation__value = &ops; ops.parm = op; el1.result = result; } else ras.element_ROS_0 = (struct element_ROS_1 *)0; if (encode_ROS_ROSEapdus(&pe, 1, 0, NULL, &apdu) == NOTOK) { fail: if (pe) { pe_extract (pe, result); pe_free (pe); } freeacblk (acb); return rosaplose (roi, ROS_CONGEST, NULLCP, "out of memory"); } } #endif /* begin Result APDU */ if ((pe = pe_alloc (PE_CLASS_CONT, PE_FORM_CONS, APDU_RESULT)) == NULLPE || ((acb -> acb_flags & ACB_ACS) ? (p = pe, 0) : set_add (pe, p = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_CONS_SEQ)) == NOTOK) || seq_add (p, int2prim (invokeID), -1) == NOTOK || ((acb -> acb_flags & ACB_ACS) ? (result && (seq_add (p, q = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_CONS_SEQ), -1) == NOTOK || seq_add (q, int2prim (op), -1) == NOTOK || seq_add (q, result, -1) == NOTOK)) : seq_add (p, result, -1) == NOTOK)) { if (pe) { pe_extract (pe, result); pe_free (pe); } freeacblk (acb); return rosaplose (roi, ROS_CONGEST, NULLCP, "out of memory"); } /* end Result APDU */ return (*acb -> acb_putosdu) (acb, pe, result, priority, roi); }