+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ * @(#)tp_subr2.c 7.14 (Berkeley) %G%
+ */
+
/***********************************************************
Copyright IBM Corporation 1987
* $Source: /usr/argo/sys/netiso/RCS/tp_subr2.c,v $
*
* Some auxiliary routines:
- * tp_protocol_error: required by xebec- called when a combo of state,
- * event, predicate isn't covered for by the transition file.
- * tp_indicate: gives indications(signals) to the user process
- * tp_getoptions: initializes variables that are affected by the options
- * chosen.
+ * tp_protocol_error: required by xebec- called when a combo of state,
+ * event, predicate isn't covered for by the transition file.
+ * tp_indicate: gives indications(signals) to the user process
+ * tp_getoptions: initializes variables that are affected by the options
+ * chosen.
*/
-#ifndef lint
-static char *rcsid = "$Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $";
-#endif lint
-
-#include "argoxtwentyfive.h"
-
/* this def'n is to cause the expansion of this macro in the
* routine tp_local_credit :
*/
#define LOCAL_CREDIT_EXPAND
#include "param.h"
+#include "systm.h"
#include "mbuf.h"
#include "socket.h"
#include "socketvar.h"
#include "time.h"
#include "kernel.h"
#undef MNULL
-#include "../netiso/tp_ip.h"
-#include "../netiso/tp_param.h"
-#include "../netiso/tp_timer.h"
-#include "../netiso/tp_stat.h"
-#include "../netiso/argo_debug.h"
-#include "../netiso/tp_tpdu.h"
-#include "../netiso/iso.h"
-#include "../netiso/iso_errno.h"
-#include "../netiso/tp_pcb.h"
-#include "../netiso/tp_seq.h"
-#include "../netiso/tp_trace.h"
-#include "../netiso/iso_pcb.h"
-#include "../netiso/tp_user.h"
-#include "../netiso/cons.h"
+#include "argo_debug.h"
+#include "tp_param.h"
+#include "tp_ip.h"
+#include "iso.h"
+#include "iso_errno.h"
+#include "iso_pcb.h"
+#include "tp_timer.h"
+#include "tp_stat.h"
+#include "tp_tpdu.h"
+#include "tp_pcb.h"
+#include "tp_seq.h"
+#include "tp_trace.h"
+#include "tp_user.h"
+#include "cons.h"
+
+#include "../net/if.h"
+#include "../net/if_types.h"
+#ifdef TRUE
+#undef FALSE
+#undef TRUE
+#endif
+#include "../netccitt/x25.h"
+#include "../netccitt/pk.h"
+#include "../netccitt/pk_var.h"
/*
* NAME: tp_local_credit()
{
register struct socket *so = tpcb->tp_sock;
IFTRACE(D_INDICATION)
- tptraceTPCB(TPPTindicate, ind, *(int *)(tpcb->tp_lsuffix),
- *(int *)(tpcb->tp_fsuffix), error,so->so_pgrp);
+ tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix),
+ *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid);
ENDTRACE
IFDEBUG(D_INDICATION)
- u_char *ls, *fs;
+ char *ls, *fs;
ls = tpcb->tp_lsuffix,
fs = tpcb->tp_fsuffix,
printf(
-"indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x prgp 0x%x noind 0x%x ref 0x%x\n",
+"indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n",
ind,
*ls, *(ls+1), *fs, *(fs+1),
- error,so->so_pgrp,
+ error, /*so->so_pgrp,*/
tpcb->tp_no_disc_indications,
tpcb->tp_lref);
ENDDEBUG
+ if (ind == ER_TPDU) {
+ register struct mbuf *m;
+ struct tp_disc_reason x;
+
+ if ((so->so_state & SS_CANTRCVMORE) == 0 &&
+ (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) {
+
+ x.dr_hdr.cmsg_len = m->m_len = sizeof(x);
+ x.dr_hdr.cmsg_level = SOL_TRANSPORT;
+ x.dr_hdr.cmsg_type= TPOPT_DISC_REASON;
+ x.dr_reason = error;
+ *mtod(m, struct tp_disc_reason *) = x;
+ sbappendrecord(&tpcb->tp_Xrcv, m);
+ error = 0;
+ } else
+ error = ECONNRESET;
+ }
so->so_error = error;
if (ind == T_DISCONNECT) {
+ so->so_error = ENOTCONN;
if ( tpcb->tp_no_disc_indications )
return;
}
tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
tpcb->tp_dt_ticks =
MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2));
-
+ (void) tp_rsyset(tpcb);
+
}
/*
tp_recycle_tsuffix(tpcb)
struct tp_pcb *tpcb;
{
- bzero( tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix));
- bzero( tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix));
+ bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix));
+ bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix));
tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0;
(tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb);
{
IFDEBUG(D_QUENCH)
printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n",
- tpcb, tpcb->tp_lref, *(int *)(tpcb->tp_lsuffix));
+ tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix));
printf("cong_win 0x%x decbit 0x%x \n",
tpcb->tp_cong_win, tpcb->tp_decbit);
ENDDEBUG
switch(cmd) {
case PRC_QUENCH:
- tpcb->tp_cong_win = 1;
+ tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
IncStat(ts_quench);
break;
case PRC_QUENCH2:
- tpcb->tp_cong_win = 1; /* might as well quench source also */
+ tpcb->tp_cong_win = tpcb->tp_l_tpdusize; /* might as well quench source also */
tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
IncStat(ts_rcvdecbit);
break;
struct tp_pcb *tpcb;
int cmd;
{
-#if NARGOXTWENTYFIVE > 0
+#ifdef TPCONS
+ struct isopcb *isop;
+ struct pklcd *lcp;
+
+ if (tpcb->tp_netservice != ISO_CONS)
+ return;
+ isop = (struct isopcb *)tpcb->tp_npcb;
+ lcp = (struct pklcd *)isop->isop_chan;
switch (cmd) {
case CONN_CLOSE:
case CONN_REFUSE:
- cons_netcmd( cmd, tpcb->tp_npcb, 0, tpcb->tp_class == TP_CLASS_4);
- /* TODO: can this last param be replaced by
- * tpcb->tp_netserv != ISO_CONS?)
- */
+ if (isop->isop_refcnt == 1) {
+ /* This is really superfluous, since it would happen
+ anyway in iso_pcbdetach, although it is a courtesy
+ to free up the x.25 channel before the refwait timer
+ expires. */
+ lcp->lcd_upper = 0;
+ lcp->lcd_upnext = 0;
+ pk_disconnect(lcp);
+ isop->isop_chan = 0;
+ isop->isop_refcnt = 0;
+ }
break;
default:
printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd);
break;
}
-#else NARGOXTWENTYFIVE
+#else TPCONS
printf("tp_netcmd(): X25 NOT CONFIGURED!!\n");
-#endif NARGOXTWENTYFIVE > 0
+#endif
}
/*
* CALLED FROM:
/* copy all but the bits stuff at the end */
#define COPYSIZE (12 * sizeof(short))
- bcopy( src, dst, COPYSIZE);
+ bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE);
dst->p_tpdusize = src->p_tpdusize;
dst->p_ack_strat = src->p_ack_strat;
dst->p_rx_strat = src->p_rx_strat;
tp_route_to( m, tpcb, channel)
struct mbuf *m;
register struct tp_pcb *tpcb;
- u_int channel;
+ caddr_t channel;
{
register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */
extern struct tp_conn_param tp_conn_param[];
- int error = 0;
- int vc_to_kill = 0; /* kludge */
+ int error = 0, save_netservice = tpcb->tp_netservice;
+ register struct rtentry *rt = 0;
siso = mtod(m, struct sockaddr_iso *);
IFTRACE(D_CONN)
tptraceTPCB(TPPTmisc,
"route_to: so afi netservice class",
- tpcb->tp_sock, siso->siso_addr.isoa_afi, tpcb->tp_netservice,
+ tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice,
tpcb->tp_class);
ENDTRACE
IFDEBUG(D_CONN)
printf("m->mlen x%x, m->m_data:\n", m->m_len);
dump_buf(mtod(m, caddr_t), m->m_len);
ENDDEBUG
- if( siso->siso_family != tpcb->tp_domain ) {
- error = EAFNOSUPPORT;
- goto done;
+ if (channel) {
+#ifdef TPCONS
+ struct pklcd *lcp = (struct pklcd *)channel;
+ struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext,
+ *isop_new = (struct isopcb *)tpcb->tp_npcb;
+ /* The next 2 lines believe that you haven't
+ set any network level options or done a pcbconnect
+ and XXXXXXX'edly apply to both inpcb's and isopcb's */
+ remque(isop_new);
+ free(isop_new, M_PCB);
+ tpcb->tp_npcb = (caddr_t)isop;
+ tpcb->tp_netservice = ISO_CONS;
+ tpcb->tp_nlproto = nl_protosw + ISO_CONS;
+ isop->isop_socket = tpcb->tp_sock;
+ if (isop->isop_refcnt == 0)
+ iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL);
+ else
+ /* there are already connections sharing this */;
+ isop->isop_refcnt++;
+#endif
+ } else {
+ switch (siso->siso_family) {
+ default:
+ error = EAFNOSUPPORT;
+ goto done;
+#ifdef ISO
+ case AF_ISO:
+ tpcb->tp_netservice = ISO_CLNS;
+ if (rt = rtalloc1((struct sockaddr *)siso, 0)) {
+ rt->rt_refcnt--;
+ if (rt->rt_flags & RTF_PROTO1)
+ tpcb->tp_netservice = ISO_CONS;
+ }
+ break;
+#endif
+#ifdef INET
+ case AF_INET:
+ tpcb->tp_netservice = IN_CLNS;
+ }
+#endif
+ if (tpcb->tp_nlproto->nlp_afamily != siso->siso_family) {
+ IFDEBUG(D_CONN)
+ printf("tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
+ save_netservice, tpcb->tp_netservice);
+ ENDDEBUG
+ if (error = tp_set_npcb(tpcb))
+ goto done;
+ }
+ IFDEBUG(D_CONN)
+ printf("tp_route_to calling nlp_pcbconn, netserv %d\n",
+ tpcb->tp_netservice);
+ ENDDEBUG
+ tpcb->tp_nlproto = nl_protosw + tpcb->tp_netservice;
+ error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_npcb, m);
}
- {
- register int save_netservice = tpcb->tp_netservice;
+ if( error )
+ goto done;
+ {
switch(tpcb->tp_netservice) {
case ISO_COSNS:
case ISO_CLNS:
/* This is a kludge but seems necessary so the passive end
* can get long enough timers. sigh.
+ if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET )
*/
- if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) {
+ if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_X25) {
if( tpcb->tp_dont_change_params == 0) {
copyQOSparms( &tp_conn_param[ISO_COSNS],
&tpcb->_tp_param);
}
/* drop through to IN_CLNS*/
case IN_CLNS:
- if( (tpcb->tp_class & TP_CLASS_4)==0 ) {
+ if (iso_localifa(siso))
+ tpcb->tp_flags |= TPF_PEER_ON_SAMENET;
+ if((tpcb->tp_class & TP_CLASS_4) == 0) {
error = EPROTOTYPE;
break;
}
break;
case ISO_CONS:
-#if NARGOXTWENTYFIVE > 0
+#ifdef TPCONS
tpcb->tp_flags |= TPF_NLQOS_PDN;
if( tpcb->tp_dont_change_params == 0 ) {
copyQOSparms( &tp_conn_param[ISO_CONS],
}
tpcb->tp_rx_strat = TPRX_USE_CW;
- if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) {
- /* if the listener was restricting us to clns,
- * ( we never get here if the listener isn't af_iso )
- * refuse the connection :
- * but we don't have a way to restrict thus - it's
- * utterly permissive.
- if(channel) {
- (void) cons_netcmd(CONN_REFUSE, tpcb->tp_npcb,
- channel, tpcb->tp_class == TP_CLASS_4);
- error = EPFNOSUPPORT;
- goto done;
- }
- */
- IFDEBUG(D_CONN)
- printf(
- "tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
- tpcb->tp_nlproto , &nl_protosw[ISO_CONS]);
- ENDDEBUG
- tpcb->tp_nlproto = &nl_protosw[ISO_CONS];
- }
- /* Now we've got the right nl_protosw.
- * If we already have a channel (we were called from tp_input())
- * tell cons that we'll hang onto this channel.
- * If we don't already have one (we were called from usrreq())
- * -and if it's TP0 open a net connection and wait for it to finish.
- */
- if( channel ) {
- error = cons_netcmd( CONN_CONFIRM, tpcb->tp_npcb,
- channel, tpcb->tp_class == TP_CLASS_4);
- vc_to_kill ++;
- } else if( tpcb->tp_class != TP_CLASS_4 /* class 4 only */) {
- /* better open vc if any possibility of ending up
- * in non-multiplexing class
- */
- error = cons_openvc(tpcb->tp_npcb, siso, tpcb->tp_sock);
- vc_to_kill ++;
- }
/* class 4 doesn't need to open a vc now - may use one already
* opened or may open one only when it sends a pkt.
*/
-#else NARGOXTWENTYFIVE > 0
+#else TPCONS
error = ECONNREFUSED;
-#endif NARGOXTWENTYFIVE > 0
+#endif TPCONS
break;
default:
error = EPROTOTYPE;
}
- ASSERT( save_netservice == tpcb->tp_netservice);
}
- if( error )
- goto done;
- IFDEBUG(D_CONN)
- printf("tp_route_to calling nlp_pcbconn, netserv %d\n",
- tpcb->tp_netservice);
- ENDDEBUG
- error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m);
-
- if( error && vc_to_kill ) {
+ if (error) {
tp_netcmd( tpcb, CONN_CLOSE);
goto done;
}
-
- /* PHASE 2: replace iso_netmatch with iso_on_localnet(foreign addr) */
- if( iso_netmatch(
- &(((struct isopcb *)(tpcb->tp_sock->so_pcb))->isop_laddr),
- &(((struct isopcb *)(tpcb->tp_sock->so_pcb))->isop_faddr)
- )) {
- tpcb->tp_flags |= TPF_PEER_ON_SAMENET;
- }
-
{ /* start with the global rtt, rtv stats */
register int i =
(int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN);
return error;
}
+
+/* class zero version */
+void
+tp0_stash( tpcb, e )
+ register struct tp_pcb *tpcb;
+ register struct tp_event *e;
+{
+#ifndef lint
+#define E e->ATTR(DT_TPDU)
+#else lint
+#define E e->ev_union.EV_DT_TPDU
+#endif lint
+
+ register struct sockbuf *sb = &tpcb->tp_sock->so_rcv;
+ register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb;
+
+ IFPERF(tpcb)
+ PStat(tpcb, Nb_from_ll) += E.e_datalen;
+ tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,
+ E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen);
+ ENDPERF
+
+ IFDEBUG(D_STASH)
+ printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x",
+ E.e_seq, E.e_datalen, E.e_eot);
+ ENDDEBUG
+
+ IFTRACE(D_STASH)
+ tptraceTPCB(TPPTmisc, "stash EQ: seq len eot",
+ E.e_seq, E.e_datalen, E.e_eot, 0);
+ ENDTRACE
+
+ if ( E.e_eot ) {
+ register struct mbuf *n = E.e_data;
+ n->m_flags |= M_EOR;
+ n->m_act = MNULL; /* set on tp_input */
+ }
+ sbappend(sb, E.e_data);
+ IFDEBUG(D_STASH)
+ dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending");
+ ENDDEBUG
+ if (tpcb->tp_netservice != ISO_CONS)
+ printf("tp0_stash: tp running over something wierd\n");
+ else {
+ register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
+ pk_flowcontrol(lcp, sbspace(sb) <= 0, 1);
+ }
+}
+
+void
+tp0_openflow(tpcb)
+register struct tp_pcb *tpcb;
+{
+ register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb;
+ if (tpcb->tp_netservice != ISO_CONS)
+ printf("tp0_openflow: tp running over something wierd\n");
+ else {
+ register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
+ if (lcp->lcd_rxrnr_condition)
+ pk_flowcontrol(lcp, 0, 0);
+ }
+}
+#ifndef TPCONS
+static
+pk_flowcontrol() {}
+#endif
+
#ifdef TP_PERF_MEAS
/*
* CALLED FROM:
{
register struct mbuf *q;
- if( tpcb->tp_p_meas == (struct tp_pmeas *)0 ) {
-
- /* allocate a cluster for all the stats */
- MGET(q, M_DONTWAIT, TPMT_PERF); /* something we don't otherwise use */
+ if( tpcb->tp_p_meas == 0 ) {
+ MGET(q, M_WAITOK, MT_PCB);
if (q == 0)
return ENOBUFS;
- q->m_act = MNULL;
- MCLGET(q); /* for the tp_pmeas struct */
- if(q->m_len == 0) {
- m_free(q);
+ MCLGET(q, M_WAITOK);
+ if ((q->m_flags & M_EXT) == 0) {
+ (void) m_free(q);
return ENOBUFS;
- } else {
- /* point into the cluster */
- tpcb->tp_p_meas = mtod(q, struct tp_pmeas *);
- /* get rid of the original little mbuf */
- q->m_off = 0; q->m_len = 0;
- m_free(q);
- bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) );
- IFDEBUG(D_PERF_MEAS)
- printf(
- "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
- tpcb, tpcb->tp_sock, tpcb->tp_lref,
- tpcb->tp_p_meas, tpcb->tp_perf_on);
- ENDDEBUG
- tpcb->tp_perf_on = 1;
}
+ q->m_len = sizeof (struct tp_pmeas);
+ tpcb->tp_p_mbuf = q;
+ tpcb->tp_p_meas = mtod(q, struct tp_pmeas *);
+ bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) );
+ IFDEBUG(D_PERF_MEAS)
+ printf(
+ "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
+ tpcb, tpcb->tp_sock, tpcb->tp_lref,
+ tpcb->tp_p_meas, tpcb->tp_perf_on);
+ ENDDEBUG
+ tpcb->tp_perf_on = 1;
}
return 0;
}
{
switch( addr->sa_family ) {
case AF_INET:
- dump_inaddr(addr);
+ dump_inaddr((struct sockaddr_in *)addr);
break;
+#ifdef ISO
case AF_ISO:
- dump_isoaddr(addr);
+ dump_isoaddr((struct sockaddr_iso *)addr);
break;
+#endif ISO
default:
printf("BAD AF: 0x%x\n", addr->sa_family);
break;
}
}
+#define MAX_COLUMNS 8
+/*
+ * Dump the buffer to the screen in a readable format. Format is:
+ *
+ * hex/dec where hex is the hex format, dec is the decimal format.
+ * columns of hex/dec numbers will be printed, followed by the
+ * character representations (if printable).
+ */
+Dump_buf(buf, len)
+caddr_t buf;
+int len;
+{
+ int i,j;
+#define Buf ((u_char *)buf)
+ printf("Dump buf 0x%x len 0x%x\n", buf, len);
+ for (i = 0; i < len; i += MAX_COLUMNS) {
+ printf("+%d:\t", i);
+ for (j = 0; j < MAX_COLUMNS; j++) {
+ if (i + j < len) {
+ printf("%x/%d\t", Buf[i+j], Buf[i+j]);
+ } else {
+ printf(" ");
+ }
+ }
+
+ for (j = 0; j < MAX_COLUMNS; j++) {
+ if (i + j < len) {
+ if (((Buf[i+j]) > 31) && ((Buf[i+j]) < 128))
+ printf("%c", Buf[i+j]);
+ else
+ printf(".");
+ }
+ }
+ printf("\n");
+ }
+}
+
+
#endif ARGO_DEBUG