X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/3202a7cd0f16263e991b468d8e20f954bc7f91d9..bdf41b09562d15429e47a80b800ba2ae5e710088:/usr/src/sys/netiso/tp_subr2.c diff --git a/usr/src/sys/netiso/tp_subr2.c b/usr/src/sys/netiso/tp_subr2.c index 356e357443..5c7bde9530 100644 --- a/usr/src/sys/netiso/tp_subr2.c +++ b/usr/src/sys/netiso/tp_subr2.c @@ -1,3 +1,12 @@ +/*- + * 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 @@ -31,25 +40,20 @@ SOFTWARE. * $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" @@ -60,20 +64,30 @@ static char *rcsid = "$Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $"; #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() @@ -184,26 +198,44 @@ tp_indicate(ind, tpcb, error) { 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; } @@ -241,7 +273,8 @@ struct tp_pcb *tpcb; 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); + } /* @@ -263,8 +296,8 @@ void 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); @@ -304,17 +337,17 @@ tp_quench( tpcb, cmd ) { 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; @@ -339,24 +372,38 @@ tp_netcmd( tpcb, cmd ) 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: @@ -396,7 +443,7 @@ copyQOSparms(src, dst) /* 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; @@ -432,18 +479,18 @@ int 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) @@ -452,20 +499,73 @@ tp_route_to( m, tpcb, channel) 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); @@ -474,7 +574,9 @@ tp_route_to( m, tpcb, channel) } /* 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; } @@ -482,7 +584,7 @@ tp_route_to( m, tpcb, channel) 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], @@ -499,77 +601,22 @@ tp_route_to( m, tpcb, channel) } 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); @@ -588,6 +635,73 @@ done: 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: @@ -607,32 +721,26 @@ tp_setup_perf(tpcb) { 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; } @@ -644,16 +752,56 @@ dump_addr (addr) { 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