Kill netccitt. The code is ancient, nobody wants to maintain it, and it
doesn't compile cleanly.
This commit is contained in:
parent
8df32b19de
commit
1df738d453
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
*
|
||||
* @(#)README.hdlc 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* X.25 HDLC DATA LINK LEVEL:
|
||||
*
|
||||
*
|
||||
* This module implements the Link Level of the Open Systems Interconnect
|
||||
* Model. The implementation is based on the ISO High-Level Data Link
|
||||
* Control (HDLC). These procedures subscribe to the principles of the
|
||||
* ISO-Class of Procedures for point-to-point. These procedures implement
|
||||
* two-way asynchronous balanced mode (LAPB) as recommented by the CCITT.
|
||||
*
|
||||
* The HDLC protocol layer interface consists of the following procedures:
|
||||
* Hd_init (pr_init)
|
||||
* Hd_ouput (pr_output)
|
||||
* Hd_input (pr_input)
|
||||
* Hd_timer (pr_slowtimo)
|
||||
*
|
||||
* Note: Supervisory commands RR, RNR and REJ are not transmitted by this
|
||||
* station.
|
||||
*
|
||||
* This station never enters a busy (RNR) condition.
|
||||
*
|
||||
* The "Generate_rr" variable can be set to FALSE. This means that
|
||||
* we NEVER send an RR. This works just fine if the network level
|
||||
* is X.25 packet protocol -- which it is.
|
||||
*
|
||||
* Currently, this is only a DTE implementation.
|
||||
*
|
||||
* Think about:
|
||||
* If the remote is busy, no iframes are sent. The remote sends a RR
|
||||
* to clear this condition. However, this RR may be damaged, causing
|
||||
* a possible deadlock. A solution is to poll with iframe (P(S)==P(R)
|
||||
* of RNR) indefinitly.
|
||||
*
|
||||
*
|
||||
* Date: February 1984
|
||||
*
|
||||
* Author: Gerald W. Neufeld
|
||||
*
|
||||
* Installation: Department of Computer Science
|
||||
* University of British Columbia
|
||||
* Vancouver, BC, CANADA.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
*
|
||||
*/
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* @(#)README.packet 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* X.25 NETWORK PACKET LEVEL:
|
||||
*
|
||||
* This implementation is based on Recommentation X.25 as agreed at the
|
||||
* March 1976 and the February 1980 meetings of CCITT Study Group VII.
|
||||
* However, not all aspects are implemented. The following is a list of
|
||||
* features which are not yet or may never be implemented:
|
||||
*
|
||||
* 1. D bit
|
||||
* 2. PVC
|
||||
* 3. fast select
|
||||
*
|
||||
*
|
||||
* Note: This implementation is for DTEs only.
|
||||
*
|
||||
* Currently, only the 1976 verison is implemented.
|
||||
*
|
||||
*
|
||||
* Date: February, 1984
|
||||
*
|
||||
* Author: Gerald W. Neufeld
|
||||
*
|
||||
* Installation: Department of Computer Science
|
||||
* University of British Columbia
|
||||
* Vancouver, BC, CANADA
|
||||
*
|
||||
* To Do: Find some reasonable heuristic for piggybacking packet
|
||||
* level acks.
|
||||
*
|
||||
* Bugs: Clear might be sent before data is all out.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
*/
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ccitt_proto.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: ccitt_proto.c,v 1.2 1994/08/02 07:46:54 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/domain.h>
|
||||
|
||||
#include <netccitt/x25.h>
|
||||
|
||||
#include <net/radix.h>
|
||||
|
||||
/*
|
||||
* Definitions of protocols supported in the CCITT domain.
|
||||
*/
|
||||
|
||||
extern struct domain ccittdomain;
|
||||
#define DOMAIN &ccittdomain
|
||||
|
||||
#ifdef LLC
|
||||
int llc_output();
|
||||
void llc_ctlinput(), llc_init(), llc_timer();
|
||||
#endif
|
||||
#ifdef HDLC
|
||||
int hd_output();
|
||||
void hd_ctlinput(), hd_init(), hd_timer();
|
||||
#endif
|
||||
int pk_usrreq(), pk_ctloutput();
|
||||
void pk_timer(), pk_init(), pk_input(), pk_ctlinput();
|
||||
|
||||
struct protosw ccittsw[] = {
|
||||
#ifdef LLC
|
||||
{ 0, DOMAIN, IEEEPROTO_802LLC,0,
|
||||
0, llc_output, llc_ctlinput, 0,
|
||||
0,
|
||||
llc_init, 0, llc_timer, 0,
|
||||
},
|
||||
#endif
|
||||
#ifdef HDLC
|
||||
{ 0, DOMAIN, CCITTPROTO_HDLC,0,
|
||||
0, hd_output, hd_ctlinput, 0,
|
||||
0,
|
||||
hd_init, 0, hd_timer, 0,
|
||||
},
|
||||
#endif
|
||||
{ SOCK_STREAM, DOMAIN, CCITTPROTO_X25, PR_CONNREQUIRED|PR_ATOMIC|PR_WANTRCVD,
|
||||
pk_input, 0, pk_ctlinput, pk_ctloutput,
|
||||
pk_usrreq,
|
||||
pk_init, 0, pk_timer, 0,
|
||||
}
|
||||
};
|
||||
|
||||
struct domain ccittdomain =
|
||||
{ AF_CCITT, "ccitt", 0, 0, 0, ccittsw,
|
||||
&ccittsw[sizeof(ccittsw)/sizeof(ccittsw[0])], 0,
|
||||
rn_inithead, 32, sizeof (struct sockaddr_x25) };
|
||||
|
||||
DOMAIN_SET(ccitt);
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Dirk Husemann, Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)dll.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: dll.h,v 1.3 1994/08/21 05:44:06 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_DLL_H_
|
||||
#define _NETCCITT_DLL_H_
|
||||
|
||||
/*
|
||||
* We define the additional PRC_* codes in here
|
||||
*/
|
||||
#ifdef KERNEL
|
||||
#ifndef PRC_IFUP
|
||||
#define PRC_IFUP 3
|
||||
#endif
|
||||
#define PRC_CONNECT_INDICATION 8
|
||||
#define PRC_CONNECT_REQUEST 9
|
||||
#define PRC_DISCONNECT_REQUEST 10
|
||||
#define PRC_DISCONNECT_INDICATION 11
|
||||
#define PRC_RESET_REQUEST 12
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Data link layer configuration --- basically a copy of the relevant parts
|
||||
* of x25config, implemented to become a little bit more network
|
||||
* layer independent. (Probably only used for casting et al.)
|
||||
*/
|
||||
struct dllconfig {
|
||||
u_short dllcfg_unused0:4,
|
||||
dllcfg_unused1:4,
|
||||
dllcfg_trace:1, /* link level tracing flag */
|
||||
dllcfg_window:7; /* link level window size */
|
||||
u_short dllcfg_xchxid:1, /* exchange XID (not yet) */
|
||||
dllcfg_unused2:7; /* here be dragons */
|
||||
};
|
||||
|
||||
struct dll_ctlinfo {
|
||||
union {
|
||||
struct {
|
||||
struct dllconfig *dctli_up_cfg;
|
||||
u_char dctli_up_lsap;
|
||||
} CTLI_UP;
|
||||
struct {
|
||||
caddr_t dctli_down_pcb;
|
||||
struct rtentry *dctli_down_rt;
|
||||
struct dllconfig *dctli_down_llconf;
|
||||
} CTLI_DOWN;
|
||||
} CTLIun;
|
||||
};
|
||||
#define dlcti_cfg CTLIun.CTLI_UP.dctli_up_cfg
|
||||
#define dlcti_lsap CTLIun.CTLI_UP.dctli_up_lsap
|
||||
#define dlcti_pcb CTLIun.CTLI_DOWN.dctli_down_pcb
|
||||
#define dlcti_rt CTLIun.CTLI_DOWN.dctli_down_rt
|
||||
#define dlcti_conf CTLIun.CTLI_DOWN.dctli_down_llconf
|
||||
|
||||
#endif
|
@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)hd_debug.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: hd_debug.c,v 1.3 1995/02/15 06:29:42 jkh Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/hdlc.h>
|
||||
#include <netccitt/hd_var.h>
|
||||
#include <netccitt/x25.h>
|
||||
|
||||
#ifdef HDLCDEBUG
|
||||
#define NTRACE 32
|
||||
|
||||
struct hdlctrace {
|
||||
struct hdcb *ht_hdp;
|
||||
short ht_dir;
|
||||
struct mbuf *ht_frame;
|
||||
struct timeval ht_time;
|
||||
} hdtrace[NTRACE];
|
||||
|
||||
int lasttracelogged, freezetrace;
|
||||
#endif
|
||||
|
||||
void
|
||||
hd_trace (hdp, direction, frame)
|
||||
struct hdcb *hdp;
|
||||
int direction;
|
||||
register struct Hdlc_frame *frame;
|
||||
{
|
||||
register char *s;
|
||||
register int nr, pf, ns, i;
|
||||
struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame;
|
||||
|
||||
#ifdef HDLCDEBUG
|
||||
hd_savetrace (hdp, direction, frame);
|
||||
#endif
|
||||
if (hdp -> hd_xcp -> xc_ltrace) {
|
||||
if (direction == RX)
|
||||
printf ("F-In: ");
|
||||
else if (direction == 2)
|
||||
printf ("F-Xmt: ");
|
||||
else
|
||||
printf ("F-Out: ");
|
||||
|
||||
nr = iframe -> nr;
|
||||
pf = iframe -> pf;
|
||||
ns = iframe -> ns;
|
||||
|
||||
switch (hd_decode (hdp, frame)) {
|
||||
case SABM:
|
||||
printf ("SABM : PF=%d\n", pf);
|
||||
break;
|
||||
|
||||
case DISC:
|
||||
printf ("DISC : PF=%d\n", pf);
|
||||
break;
|
||||
|
||||
case DM:
|
||||
printf ("DM : PF=%d\n", pf);
|
||||
break;
|
||||
|
||||
case FRMR:
|
||||
{
|
||||
register struct Frmr_frame *f = (struct Frmr_frame *)frame;
|
||||
|
||||
printf ("FRMR : PF=%d, TEXT=", pf);
|
||||
for (s = (char *) frame, i = 0; i < 5; ++i, ++s)
|
||||
printf ("%x ", (int) * s & 0xff);
|
||||
printf ("\n");
|
||||
printf ("control=%x v(s)=%d v(r)=%d w%d x%d y%d z%d\n",
|
||||
f->frmr_control, f->frmr_ns, f->frmr_nr,
|
||||
f->frmr_w, f->frmr_x, f->frmr_y, f->frmr_z);
|
||||
break;
|
||||
}
|
||||
|
||||
case UA:
|
||||
printf ("UA : PF=%d\n", pf);
|
||||
break;
|
||||
|
||||
case RR:
|
||||
printf ("RR : N(R)=%d, PF=%d\n", nr, pf);
|
||||
break;
|
||||
|
||||
case RNR:
|
||||
printf ("RNR : N(R)=%d, PF=%d\n", nr, pf);
|
||||
break;
|
||||
|
||||
case REJ:
|
||||
printf ("REJ : N(R)=%d, PF=%d\n", nr, pf);
|
||||
break;
|
||||
|
||||
case IFRAME:
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register int len = 0;
|
||||
|
||||
for(m = dtom (frame); m; m = m -> m_next)
|
||||
len += m -> m_len;
|
||||
len -= HDHEADERLN;
|
||||
printf ("IFRAME : N(R)=%d, PF=%d, N(S)=%d, DATA(%d)=",
|
||||
nr, pf, ns, len);
|
||||
for (s = (char *)iframe->i_field, i = 0; i < 3; ++i, ++s)
|
||||
printf ("%x ", (int) *s & 0xff);
|
||||
printf ("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printf ("ILLEGAL: ");
|
||||
for (s = (char *) frame, i = 0; i < 5; ++i, ++s)
|
||||
printf ("%x ", (int) *s & 0xff);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HDLCDEBUG
|
||||
static
|
||||
hd_savetrace (hdp, dir, frame)
|
||||
struct hdcb *hdp;
|
||||
struct Hdlc_frame *frame;
|
||||
{
|
||||
register struct hdlctrace *htp;
|
||||
register struct mbuf *m;
|
||||
|
||||
if (freezetrace)
|
||||
return;
|
||||
htp = &hdtrace[lasttracelogged];
|
||||
lasttracelogged = (lasttracelogged + 1) % NTRACE;
|
||||
if (m = htp->ht_frame)
|
||||
m_freem (m);
|
||||
m = dtom (frame);
|
||||
htp->ht_frame = m_copy (m, 0, m->m_len);
|
||||
htp->ht_hdp = hdp;
|
||||
htp->ht_dir = dir;
|
||||
htp->ht_time = time;
|
||||
}
|
||||
|
||||
hd_dumptrace (hdp)
|
||||
struct hdcb *hdp;
|
||||
{
|
||||
register int i, ltrace;
|
||||
register struct hdlctrace *htp;
|
||||
|
||||
freezetrace = 1;
|
||||
hd_status (hdp);
|
||||
printf ("retransmit queue:");
|
||||
for (i = 0; i < 8; i++)
|
||||
printf (" %x", hdp -> hd_retxq[i]);
|
||||
printf ("\n");
|
||||
ltrace = hdp -> hd_xcp -> xc_ltrace;
|
||||
hdp -> hd_xcp -> xc_ltrace = 1;
|
||||
for (i = 0; i < NTRACE; i++) {
|
||||
htp = &hdtrace[(lasttracelogged + i) % NTRACE];
|
||||
if (htp->ht_hdp != hdp || htp->ht_frame == 0)
|
||||
continue;
|
||||
printf ("%d/%d ", htp->ht_time.tv_sec & 0xff,
|
||||
htp->ht_time.tv_usec / 10000);
|
||||
hd_trace (htp->ht_hdp, htp->ht_dir,
|
||||
mtod (htp->ht_frame, struct Hdlc_frame *));
|
||||
m_freem (htp->ht_frame);
|
||||
htp->ht_frame = 0;
|
||||
}
|
||||
hdp -> hd_xcp -> xc_ltrace = ltrace;
|
||||
freezetrace = 0;
|
||||
}
|
||||
#endif
|
@ -1,678 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)hd_input.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: hd_input.c,v 1.4 1995/05/11 19:26:39 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/hdlc.h>
|
||||
#include <netccitt/hd_var.h>
|
||||
#include <netccitt/x25.h>
|
||||
|
||||
static void frame_reject();
|
||||
static void rej_routine();
|
||||
static void free_iframes();
|
||||
void process_sframe ();
|
||||
|
||||
/*
|
||||
* HDLC INPUT INTERFACE
|
||||
*
|
||||
* This routine is called when the HDLC physical device has
|
||||
* completed reading a frame.
|
||||
*/
|
||||
|
||||
void
|
||||
hdintr ()
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register struct hdcb *hdp;
|
||||
register struct ifnet *ifp;
|
||||
register int s;
|
||||
static struct ifnet *lastifp;
|
||||
static struct hdcb *lasthdp;
|
||||
|
||||
for (;;) {
|
||||
s = splimp ();
|
||||
IF_DEQUEUE (&hdintrq, m);
|
||||
splx (s);
|
||||
if (m == 0)
|
||||
break;
|
||||
if (m->m_len < HDHEADERLN) {
|
||||
printf ("hdintr: packet too short (len=%d)\n",
|
||||
m->m_len);
|
||||
m_freem (m);
|
||||
continue;
|
||||
}
|
||||
if ((m->m_flags & M_PKTHDR) == 0)
|
||||
panic("hdintr");
|
||||
ifp = m->m_pkthdr.rcvif;
|
||||
|
||||
/*
|
||||
* look up the appropriate hdlc control block
|
||||
*/
|
||||
|
||||
if (ifp == lastifp)
|
||||
hdp = lasthdp;
|
||||
else {
|
||||
for (hdp = hdcbhead; hdp; hdp = hdp->hd_next)
|
||||
if (hdp->hd_ifp == ifp)
|
||||
break;
|
||||
if (hdp == 0) {
|
||||
printf ("hdintr: unknown interface %p\n", ifp);
|
||||
m_freem (m);
|
||||
continue;
|
||||
}
|
||||
lastifp = ifp;
|
||||
lasthdp = hdp;
|
||||
}
|
||||
|
||||
/* Process_rxframe returns FALSE if the frame was NOT queued
|
||||
for the next higher layers. */
|
||||
if (process_rxframe (hdp, m) == FALSE)
|
||||
m_freem (m);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
process_rxframe (hdp, fbuf)
|
||||
register struct hdcb *hdp;
|
||||
register struct mbuf *fbuf;
|
||||
{
|
||||
register int queued = FALSE, frametype, pf;
|
||||
register struct Hdlc_frame *frame;
|
||||
|
||||
frame = mtod (fbuf, struct Hdlc_frame *);
|
||||
pf = ((struct Hdlc_iframe *) frame) -> pf;
|
||||
|
||||
hd_trace (hdp, RX, frame);
|
||||
if (frame -> address != ADDRESS_A && frame -> address != ADDRESS_B)
|
||||
return (queued);
|
||||
|
||||
switch ((frametype = hd_decode (hdp, frame)) + hdp->hd_state) {
|
||||
case DM + DISC_SENT:
|
||||
case UA + DISC_SENT:
|
||||
/*
|
||||
* Link now closed. Leave timer running
|
||||
* so hd_timer() can periodically check the
|
||||
* status of interface driver flag bit IFF_UP.
|
||||
*/
|
||||
hdp->hd_state = DISCONNECTED;
|
||||
break;
|
||||
|
||||
case DM + INIT:
|
||||
case UA + INIT:
|
||||
/*
|
||||
* This is a non-standard state change needed for DCEs
|
||||
* that do dynamic link selection. We can't go into the
|
||||
* usual "SEND DM" state because a DM is a SARM in LAP.
|
||||
*/
|
||||
hd_writeinternal (hdp, SABM, POLLOFF);
|
||||
hdp->hd_state = SABM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case SABM + DM_SENT:
|
||||
case SABM + WAIT_SABM:
|
||||
hd_writeinternal (hdp, UA, pf);
|
||||
case UA + SABM_SENT:
|
||||
case UA + WAIT_UA:
|
||||
KILL_TIMER (hdp);
|
||||
hd_initvars (hdp);
|
||||
hdp->hd_state = ABM;
|
||||
hd_message (hdp, "Link level operational");
|
||||
/* Notify the packet level - to send RESTART. */
|
||||
(void) pk_ctlinput (PRC_LINKUP, hdp->hd_pkp);
|
||||
break;
|
||||
|
||||
case SABM + SABM_SENT:
|
||||
/* Got a SABM collision. Acknowledge the remote's SABM
|
||||
via UA but still wait for UA. */
|
||||
hd_writeinternal (hdp, UA, pf);
|
||||
break;
|
||||
|
||||
case SABM + ABM:
|
||||
/* Request to reset the link from the remote. */
|
||||
KILL_TIMER (hdp);
|
||||
hd_message (hdp, "Link reset");
|
||||
#ifdef HDLCDEBUG
|
||||
hd_dumptrace (hdp);
|
||||
#endif
|
||||
hd_flush (hdp->hd_ifp);
|
||||
hd_writeinternal (hdp, UA, pf);
|
||||
hd_initvars (hdp);
|
||||
(void) pk_ctlinput (PRC_LINKRESET, hdp->hd_pkp);
|
||||
hdp->hd_resets++;
|
||||
break;
|
||||
|
||||
case SABM + WAIT_UA:
|
||||
hd_writeinternal (hdp, UA, pf);
|
||||
break;
|
||||
|
||||
case DM + ABM:
|
||||
hd_message (hdp, "DM received: link down");
|
||||
#ifdef HDLCDEBUG
|
||||
hd_dumptrace (hdp);
|
||||
#endif
|
||||
(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
|
||||
hd_flush (hdp->hd_ifp);
|
||||
case DM + DM_SENT:
|
||||
case DM + WAIT_SABM:
|
||||
case DM + WAIT_UA:
|
||||
hd_writeinternal (hdp, SABM, pf);
|
||||
hdp->hd_state = SABM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case DISC + INIT:
|
||||
case DISC + DM_SENT:
|
||||
case DISC + SABM_SENT:
|
||||
/* Note: This is a non-standard state change. */
|
||||
hd_writeinternal (hdp, UA, pf);
|
||||
hd_writeinternal (hdp, SABM, POLLOFF);
|
||||
hdp->hd_state = SABM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case DISC + WAIT_UA:
|
||||
hd_writeinternal (hdp, DM, pf);
|
||||
SET_TIMER (hdp);
|
||||
hdp->hd_state = DM_SENT;
|
||||
break;
|
||||
|
||||
case DISC + ABM:
|
||||
hd_message (hdp, "DISC received: link down");
|
||||
(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
|
||||
case DISC + WAIT_SABM:
|
||||
hd_writeinternal (hdp, UA, pf);
|
||||
hdp->hd_state = DM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case UA + ABM:
|
||||
hd_message (hdp, "UA received: link down");
|
||||
(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
|
||||
case UA + WAIT_SABM:
|
||||
hd_writeinternal (hdp, DM, pf);
|
||||
hdp->hd_state = DM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case FRMR + DM_SENT:
|
||||
hd_writeinternal (hdp, SABM, pf);
|
||||
hdp->hd_state = SABM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case FRMR + WAIT_SABM:
|
||||
hd_writeinternal (hdp, DM, pf);
|
||||
hdp->hd_state = DM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case FRMR + ABM:
|
||||
hd_message (hdp, "FRMR received: link down");
|
||||
(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
|
||||
#ifdef HDLCDEBUG
|
||||
hd_dumptrace (hdp);
|
||||
#endif
|
||||
hd_flush (hdp->hd_ifp);
|
||||
hd_writeinternal (hdp, SABM, pf);
|
||||
hdp->hd_state = WAIT_UA;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case RR + ABM:
|
||||
case RNR + ABM:
|
||||
case REJ + ABM:
|
||||
process_sframe (hdp, (struct Hdlc_sframe *)frame, frametype);
|
||||
break;
|
||||
|
||||
case IFRAME + ABM:
|
||||
queued = process_iframe (hdp, fbuf, (struct Hdlc_iframe *)frame);
|
||||
break;
|
||||
|
||||
case IFRAME + SABM_SENT:
|
||||
case RR + SABM_SENT:
|
||||
case RNR + SABM_SENT:
|
||||
case REJ + SABM_SENT:
|
||||
hd_writeinternal (hdp, DM, POLLON);
|
||||
hdp->hd_state = DM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case IFRAME + WAIT_SABM:
|
||||
case RR + WAIT_SABM:
|
||||
case RNR + WAIT_SABM:
|
||||
case REJ + WAIT_SABM:
|
||||
hd_writeinternal (hdp, FRMR, POLLOFF);
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case ILLEGAL + SABM_SENT:
|
||||
hdp->hd_unknown++;
|
||||
hd_writeinternal (hdp, DM, POLLOFF);
|
||||
hdp->hd_state = DM_SENT;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case ILLEGAL + ABM:
|
||||
hd_message (hdp, "Unknown frame received: link down");
|
||||
(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
|
||||
case ILLEGAL + WAIT_SABM:
|
||||
hdp->hd_unknown++;
|
||||
#ifdef HDLCDEBUG
|
||||
hd_dumptrace (hdp);
|
||||
#endif
|
||||
hd_writeinternal (hdp, FRMR, POLLOFF);
|
||||
hdp->hd_state = WAIT_SABM;
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
}
|
||||
|
||||
return (queued);
|
||||
}
|
||||
|
||||
int
|
||||
process_iframe (hdp, fbuf, frame)
|
||||
register struct hdcb *hdp;
|
||||
struct mbuf *fbuf;
|
||||
register struct Hdlc_iframe *frame;
|
||||
{
|
||||
register int nr = frame -> nr,
|
||||
ns = frame -> ns,
|
||||
pf = frame -> pf;
|
||||
register int queued = FALSE;
|
||||
|
||||
/*
|
||||
* Validate the iframe's N(R) value. It's N(R) value must be in
|
||||
* sync with our V(S) value and our "last received nr".
|
||||
*/
|
||||
|
||||
if (valid_nr (hdp, nr, FALSE) == FALSE) {
|
||||
frame_reject (hdp, Z, frame);
|
||||
return (queued);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This section tests the IFRAME for proper sequence. That is, it's
|
||||
* sequence number N(S) MUST be equal to V(S).
|
||||
*/
|
||||
|
||||
if (ns != hdp->hd_vr) {
|
||||
hdp->hd_invalid_ns++;
|
||||
if (pf || (hdp->hd_condition & REJ_CONDITION) == 0) {
|
||||
hdp->hd_condition |= REJ_CONDITION;
|
||||
/*
|
||||
* Flush the transmit queue. This is ugly but we
|
||||
* have no choice. A reject response must be
|
||||
* immediately sent to the DCE. Failure to do so
|
||||
* may result in another out of sequence iframe
|
||||
* arriving (and thus sending another reject)
|
||||
* before the first reject is transmitted. This
|
||||
* will cause the DCE to receive two or more
|
||||
* rejects back to back, which must never happen.
|
||||
*/
|
||||
hd_flush (hdp->hd_ifp);
|
||||
hd_writeinternal (hdp, REJ, pf);
|
||||
}
|
||||
return (queued);
|
||||
}
|
||||
hdp->hd_condition &= ~REJ_CONDITION;
|
||||
|
||||
/*
|
||||
* This section finally tests the IFRAME's sequence number against
|
||||
* the window size (K) and the sequence number of the last frame
|
||||
* we have acknowledged. If the IFRAME is completely correct then
|
||||
* it is queued for the packet level.
|
||||
*/
|
||||
|
||||
if (ns != (hdp -> hd_lasttxnr + hdp -> hd_xcp -> xc_lwsize) % MODULUS) {
|
||||
hdp -> hd_vr = (hdp -> hd_vr + 1) % MODULUS;
|
||||
if (pf == 1) {
|
||||
/* Must generate a RR or RNR with final bit on. */
|
||||
hd_writeinternal (hdp, RR, POLLON);
|
||||
} else
|
||||
/*
|
||||
* Hopefully we can piggyback the RR, if not we will generate
|
||||
* a RR when T3 timer expires.
|
||||
*/
|
||||
if (hdp -> hd_rrtimer == 0)
|
||||
hdp->hd_rrtimer = hd_t3;
|
||||
|
||||
/* Forward iframe to packet level of X.25. */
|
||||
fbuf -> m_data += HDHEADERLN;
|
||||
fbuf -> m_len -= HDHEADERLN;
|
||||
fbuf -> m_pkthdr.len -= HDHEADERLN;
|
||||
fbuf -> m_pkthdr.rcvif = (struct ifnet *)hdp -> hd_pkp;
|
||||
#ifdef BSD4_3
|
||||
fbuf->m_act = 0; /* probably not necessary */
|
||||
#else
|
||||
{
|
||||
register struct mbuf *m;
|
||||
|
||||
for (m = fbuf; m -> m_next; m = m -> m_next)
|
||||
m -> m_act = (struct mbuf *) 0;
|
||||
m -> m_act = (struct mbuf *) 1;
|
||||
}
|
||||
#endif
|
||||
pk_input (fbuf);
|
||||
queued = TRUE;
|
||||
hd_start (hdp);
|
||||
} else {
|
||||
/*
|
||||
* Here if the remote station has transmitted more iframes then
|
||||
* the number which have been acknowledged plus K.
|
||||
*/
|
||||
hdp->hd_invalid_ns++;
|
||||
frame_reject (hdp, W, frame);
|
||||
}
|
||||
return (queued);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is used to determine if a value (the middle parameter)
|
||||
* is between two other values. The low value is the first parameter
|
||||
* the high value is the last parameter. The routine checks the middle
|
||||
* value to see if it is within the range of the first and last values.
|
||||
* The reason we need this routine is the values are modulo some base
|
||||
* hence a simple test for greater or less than is not sufficient.
|
||||
*/
|
||||
|
||||
bool
|
||||
range_check (rear, value, front)
|
||||
int rear,
|
||||
value,
|
||||
front;
|
||||
{
|
||||
register bool result = FALSE;
|
||||
|
||||
if (front > rear)
|
||||
result = (rear <= value) && (value <= front);
|
||||
else
|
||||
result = (rear <= value) || (value <= front);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine handles all the frame reject conditions which can
|
||||
* arise as a result of secondary processing. The frame reject
|
||||
* condition Y (frame length error) are handled elsewhere.
|
||||
*/
|
||||
|
||||
static void
|
||||
frame_reject (hdp, rejectcode, frame)
|
||||
struct hdcb *hdp;
|
||||
int rejectcode;
|
||||
struct Hdlc_iframe *frame;
|
||||
{
|
||||
register struct Frmr_frame *frmr = &hd_frmr;
|
||||
|
||||
frmr -> frmr_control = ((struct Hdlc_frame *) frame) -> control;
|
||||
|
||||
frmr -> frmr_ns = frame -> ns;
|
||||
frmr -> frmr_f1_0 = 0;
|
||||
frmr -> frmr_nr = frame -> nr;
|
||||
frmr -> frmr_f2_0 = 0;
|
||||
|
||||
frmr -> frmr_0000 = 0;
|
||||
frmr -> frmr_w = frmr -> frmr_x = frmr -> frmr_y =
|
||||
frmr -> frmr_z = 0;
|
||||
switch (rejectcode) {
|
||||
case Z:
|
||||
frmr -> frmr_z = 1;/* invalid N(R). */
|
||||
break;
|
||||
|
||||
case Y:
|
||||
frmr -> frmr_y = 1;/* iframe length error. */
|
||||
break;
|
||||
|
||||
case X:
|
||||
frmr -> frmr_x = 1;/* invalid information field. */
|
||||
frmr -> frmr_w = 1;
|
||||
break;
|
||||
|
||||
case W:
|
||||
frmr -> frmr_w = 1;/* invalid N(S). */
|
||||
}
|
||||
|
||||
hd_writeinternal (hdp, FRMR, POLLOFF);
|
||||
|
||||
hdp->hd_state = WAIT_SABM;
|
||||
SET_TIMER (hdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure is invoked when ever we receive a supervisor
|
||||
* frame such as RR, RNR and REJ. All processing for these
|
||||
* frames is done here.
|
||||
*/
|
||||
|
||||
void
|
||||
process_sframe (hdp, frame, frametype)
|
||||
register struct hdcb *hdp;
|
||||
register struct Hdlc_sframe *frame;
|
||||
int frametype;
|
||||
{
|
||||
register int nr = frame -> nr, pf = frame -> pf, pollbit = 0;
|
||||
|
||||
if (valid_nr (hdp, nr, pf) == TRUE) {
|
||||
switch (frametype) {
|
||||
case RR:
|
||||
hdp->hd_condition &= ~REMOTE_RNR_CONDITION;
|
||||
break;
|
||||
|
||||
case RNR:
|
||||
hdp->hd_condition |= REMOTE_RNR_CONDITION;
|
||||
hdp->hd_retxcnt = 0;
|
||||
break;
|
||||
|
||||
case REJ:
|
||||
hdp->hd_condition &= ~REMOTE_RNR_CONDITION;
|
||||
rej_routine (hdp, nr);
|
||||
}
|
||||
|
||||
if (pf == 1) {
|
||||
hdp->hd_retxcnt = 0;
|
||||
hdp->hd_condition &= ~TIMER_RECOVERY_CONDITION;
|
||||
|
||||
if (frametype == RR && hdp->hd_lastrxnr == hdp->hd_vs
|
||||
&& hdp->hd_timer == 0 && hdp->hd_txq.head == 0)
|
||||
hd_writeinternal(hdp, RR, pf);
|
||||
else
|
||||
/* If any iframes have been queued because of the
|
||||
timer condition, transmit then now. */
|
||||
if (hdp->hd_condition & REMOTE_RNR_CONDITION) {
|
||||
/* Remote is busy or timer condition, so only
|
||||
send one. */
|
||||
if (hdp->hd_vs != hdp->hd_retxqi)
|
||||
hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], pollbit);
|
||||
}
|
||||
else /* Flush the retransmit list first. */
|
||||
while (hdp->hd_vs != hdp->hd_retxqi)
|
||||
hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF);
|
||||
}
|
||||
|
||||
hd_start (hdp);
|
||||
} else
|
||||
frame_reject (hdp, Z, (struct Hdlc_iframe *)frame); /* Invalid N(R). */
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine tests the validity of the N(R) which we have received.
|
||||
* If it is ok, then all the iframes which it acknowledges (if any)
|
||||
* will be freed.
|
||||
*/
|
||||
|
||||
bool
|
||||
valid_nr (hdp, nr, finalbit)
|
||||
register struct hdcb *hdp;
|
||||
int nr;
|
||||
register int finalbit;
|
||||
{
|
||||
/* Make sure it really does acknowledge something. */
|
||||
if (hdp->hd_lastrxnr == nr)
|
||||
return (TRUE);
|
||||
|
||||
/*
|
||||
* This section validates the frame's N(R) value. It's N(R) value
|
||||
* must be in syncronization with our V(S) value and our "last
|
||||
* received nr" variable. If it is correct then we are able to send
|
||||
* more IFRAME's, else frame reject condition is entered.
|
||||
*/
|
||||
|
||||
if (range_check (hdp->hd_lastrxnr, nr, hdp->hd_vs) == FALSE) {
|
||||
if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) &&
|
||||
range_check (hdp->hd_vs, nr, hdp->hd_xx) == TRUE)
|
||||
hdp->hd_vs = nr;
|
||||
|
||||
else {
|
||||
hdp->hd_invalid_nr++;
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get to here, we do have a valid frame but it might be out
|
||||
* of sequence. However, we should still accept the receive state
|
||||
* number N(R) since it has already passed our previous test and it
|
||||
* does acknowledge frames which we are sending.
|
||||
*/
|
||||
|
||||
KILL_TIMER (hdp);
|
||||
free_iframes (hdp, &nr, finalbit);/* Free all acknowledged iframes */
|
||||
if (nr != hdp->hd_vs)
|
||||
SET_TIMER (hdp);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine determines how many iframes need to be retransmitted.
|
||||
* It then resets the Send State Variable V(S) to accomplish this.
|
||||
*/
|
||||
|
||||
static void
|
||||
rej_routine (hdp, rejnr)
|
||||
register struct hdcb *hdp;
|
||||
register int rejnr;
|
||||
{
|
||||
register int anchor;
|
||||
|
||||
/*
|
||||
* Flush the output queue. Any iframes queued for
|
||||
* transmission will be out of sequence.
|
||||
*/
|
||||
|
||||
hd_flush (hdp->hd_ifp);
|
||||
|
||||
/*
|
||||
* Determine how many frames should be re-transmitted. In the case
|
||||
* of a normal REJ this should be 1 to K. In the case of a timer
|
||||
* recovery REJ (ie. a REJ with the Final Bit on) this could be 0.
|
||||
*/
|
||||
|
||||
anchor = hdp->hd_vs;
|
||||
if (hdp->hd_condition & TIMER_RECOVERY_CONDITION)
|
||||
anchor = hdp->hd_xx;
|
||||
|
||||
anchor = (anchor - rejnr + 8) % MODULUS;
|
||||
|
||||
if (anchor > 0) {
|
||||
|
||||
/* There is at least one iframe to retransmit. */
|
||||
KILL_TIMER (hdp);
|
||||
hdp->hd_vs = rejnr;
|
||||
|
||||
while (hdp->hd_vs != hdp->hd_retxqi)
|
||||
hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF);
|
||||
|
||||
}
|
||||
hd_start (hdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine frees iframes from the retransmit queue. It is called
|
||||
* when a previously written iframe is acknowledged.
|
||||
*/
|
||||
|
||||
static void
|
||||
free_iframes (hdp, nr, finalbit)
|
||||
register struct hdcb *hdp;
|
||||
int *nr;
|
||||
register int finalbit;
|
||||
|
||||
{
|
||||
register int i, k;
|
||||
|
||||
/*
|
||||
* We need to do the following because of a funny quirk in the
|
||||
* protocol. This case occures when in Timer recovery condition
|
||||
* we get a N(R) which acknowledges all the outstanding iframes
|
||||
* but with the Final Bit off. In this case we need to save the last
|
||||
* iframe for possible retransmission even though it has already been
|
||||
* acknowledged!
|
||||
*/
|
||||
|
||||
if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) && *nr == hdp->hd_xx && finalbit == 0) {
|
||||
*nr = (*nr - 1 + 8) % MODULUS;
|
||||
/* printf ("QUIRK\n"); */
|
||||
}
|
||||
|
||||
k = (*nr - hdp->hd_lastrxnr + 8) % MODULUS;
|
||||
|
||||
/* Loop here freeing all acknowledged iframes. */
|
||||
for (i = 0; i < k; ++i) {
|
||||
m_freem (hdp->hd_retxq[hdp->hd_lastrxnr]);
|
||||
hdp->hd_retxq[hdp->hd_lastrxnr] = 0;
|
||||
hdp->hd_lastrxnr = (hdp->hd_lastrxnr + 1) % MODULUS;
|
||||
}
|
||||
|
||||
}
|
@ -1,253 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)hd_output.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: hd_output.c,v 1.3 1995/02/15 06:29:44 jkh Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/hdlc.h>
|
||||
#include <netccitt/hd_var.h>
|
||||
#include <netccitt/x25.h>
|
||||
|
||||
/*
|
||||
* HDLC OUTPUT INTERFACE
|
||||
*
|
||||
* This routine is called when the X.25 packet layer output routine
|
||||
* has a information frame (iframe) to write. It is also called
|
||||
* by the input and control routines of the HDLC layer.
|
||||
*/
|
||||
|
||||
void
|
||||
hd_start (hdp)
|
||||
register struct hdcb *hdp;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
|
||||
/*
|
||||
* The iframe is only transmitted if all these conditions are FALSE.
|
||||
* The iframe remains queued (hdp->hd_txq) however and will be
|
||||
* transmitted as soon as these conditions are cleared.
|
||||
*/
|
||||
|
||||
while (!(hdp->hd_condition & (TIMER_RECOVERY_CONDITION | REMOTE_RNR_CONDITION | REJ_CONDITION))) {
|
||||
if (hdp->hd_vs == (hdp->hd_lastrxnr + hdp->hd_xcp->xc_lwsize) % MODULUS) {
|
||||
|
||||
/* We have now exceeded the maximum number of
|
||||
outstanding iframes. Therefore, we must wait
|
||||
until at least one is acknowledged if this
|
||||
condition is not turned off before we are
|
||||
requested to write another iframe. */
|
||||
hdp->hd_window_condition++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* hd_remove top iframe from transmit queue. */
|
||||
if ((m = hd_remove (&hdp->hd_txq)) == NULL)
|
||||
break;
|
||||
|
||||
hd_send_iframe (hdp, m, POLLOFF);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hd_output (hdp, m0)
|
||||
register struct hdcb *hdp;
|
||||
struct mbuf *m0;
|
||||
{
|
||||
struct x25config *xcp;
|
||||
register struct mbuf *m = m0;
|
||||
int len;
|
||||
|
||||
if (m == NULL)
|
||||
panic ("hd_output");
|
||||
if ((m->m_flags & M_PKTHDR) == 0)
|
||||
panic ("hd_output 2");
|
||||
|
||||
if (hdp->hd_state != ABM) {
|
||||
m_freem (m);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make room for the hdlc header either by prepending
|
||||
* another mbuf, or by adjusting the offset and length
|
||||
* of the first mbuf in the mbuf chain.
|
||||
*/
|
||||
|
||||
M_PREPEND(m, HDHEADERLN, M_DONTWAIT);
|
||||
if (m == NULL)
|
||||
return;
|
||||
for (len = 0; m; m = m->m_next)
|
||||
len += m->m_len;
|
||||
m = m0;
|
||||
m->m_pkthdr.len = len;
|
||||
|
||||
hd_append (&hdp->hd_txq, m);
|
||||
hd_start (hdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure is passed a buffer descriptor for an iframe. It builds
|
||||
* the rest of the control part of the frame and then writes it out. It
|
||||
* also starts the acknowledgement timer and keeps the iframe in the
|
||||
* Retransmit queue (Retxq) just in case we have to do this again.
|
||||
*
|
||||
* Note: This routine is also called from hd_input.c when retransmission
|
||||
* of old frames is required.
|
||||
*/
|
||||
|
||||
void
|
||||
hd_send_iframe (hdp, buf, poll_bit)
|
||||
register struct hdcb *hdp;
|
||||
register struct mbuf *buf;
|
||||
int poll_bit;
|
||||
{
|
||||
register struct Hdlc_iframe *iframe;
|
||||
struct mbuf *m;
|
||||
|
||||
KILL_TIMER (hdp);
|
||||
|
||||
if (buf == 0) {
|
||||
printf ("hd_send_iframe: zero arg\n");
|
||||
#ifdef HDLCDEBUG
|
||||
hd_status (hdp);
|
||||
hd_dumptrace (hdp);
|
||||
#endif
|
||||
hdp->hd_vs = (hdp->hd_vs + 7) % MODULUS;
|
||||
return;
|
||||
}
|
||||
iframe = mtod (buf, struct Hdlc_iframe *);
|
||||
|
||||
iframe -> hdlc_0 = 0;
|
||||
iframe -> nr = hdp->hd_vr;
|
||||
iframe -> pf = poll_bit;
|
||||
iframe -> ns = hdp->hd_vs;
|
||||
iframe -> address = ADDRESS_B;
|
||||
hdp->hd_lasttxnr = hdp->hd_vr;
|
||||
hdp->hd_rrtimer = 0;
|
||||
|
||||
if (hdp->hd_vs == hdp->hd_retxqi) {
|
||||
/* Check for retransmissions. */
|
||||
/* Put iframe only once in the Retransmission queue. */
|
||||
hdp->hd_retxq[hdp->hd_retxqi] = buf;
|
||||
hdp->hd_retxqi = (hdp->hd_retxqi + 1) % MODULUS;
|
||||
hdp->hd_iframes_out++;
|
||||
}
|
||||
|
||||
hdp->hd_vs = (hdp->hd_vs + 1) % MODULUS;
|
||||
|
||||
hd_trace (hdp, TX, (struct Hdlc_frame *)iframe);
|
||||
|
||||
/* Write buffer on device. */
|
||||
m = hdp->hd_dontcopy ? buf : m_copy(buf, 0, (int)M_COPYALL);
|
||||
if (m == 0) {
|
||||
printf("hdlc: out of mbufs\n");
|
||||
return;
|
||||
}
|
||||
(*hdp->hd_output)(hdp, m);
|
||||
SET_TIMER (hdp);
|
||||
}
|
||||
|
||||
void
|
||||
hd_ifoutput(hdp, m)
|
||||
register struct mbuf *m;
|
||||
register struct hdcb *hdp;
|
||||
{
|
||||
/*
|
||||
* Queue message on interface, and start output if interface
|
||||
* not yet active.
|
||||
*/
|
||||
register struct ifnet *ifp = hdp->hd_ifp;
|
||||
int s = splimp();
|
||||
|
||||
if (IF_QFULL(&ifp->if_snd)) {
|
||||
IF_DROP(&ifp->if_snd);
|
||||
/* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
|
||||
ifp->if_name, ifp->if_unit);*/
|
||||
m_freem(m);
|
||||
} else {
|
||||
IF_ENQUEUE(&ifp->if_snd, m);
|
||||
if ((ifp->if_flags & IFF_OACTIVE) == 0)
|
||||
(*ifp->if_start)(ifp);
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine gets control when the timer expires because we have not
|
||||
* received an acknowledgement for a iframe.
|
||||
*/
|
||||
|
||||
void
|
||||
hd_resend_iframe (hdp)
|
||||
register struct hdcb *hdp;
|
||||
{
|
||||
|
||||
if (hdp->hd_retxcnt++ < hd_n2) {
|
||||
if (!(hdp->hd_condition & TIMER_RECOVERY_CONDITION)) {
|
||||
hdp->hd_xx = hdp->hd_vs;
|
||||
hdp->hd_condition |= TIMER_RECOVERY_CONDITION;
|
||||
}
|
||||
|
||||
hdp->hd_vs = hdp->hd_lastrxnr;
|
||||
hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLON);
|
||||
} else {
|
||||
/* At this point we have not received a RR even after N2
|
||||
retries - attempt to reset link. */
|
||||
|
||||
hd_initvars (hdp);
|
||||
hd_writeinternal (hdp, SABM, POLLOFF);
|
||||
hdp->hd_state = WAIT_UA;
|
||||
SET_TIMER (hdp);
|
||||
hd_message (hdp, "Timer recovery failed: link down");
|
||||
(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
|
||||
}
|
||||
}
|
@ -1,413 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)hd_subr.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: hd_subr.c,v 1.4 1995/05/30 08:08:43 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/hdlc.h>
|
||||
#include <netccitt/hd_var.h>
|
||||
#include <netccitt/x25.h>
|
||||
#include <netccitt/pk_var.h>
|
||||
|
||||
struct hdcb *hdcbhead;
|
||||
struct Frmr_frame hd_frmr;
|
||||
struct ifqueue hdintrq;
|
||||
|
||||
int hd_t1;
|
||||
int hd_t3;
|
||||
int hd_n2;
|
||||
|
||||
void
|
||||
hd_init ()
|
||||
{
|
||||
|
||||
hdintrq.ifq_maxlen = IFQ_MAXLEN;
|
||||
}
|
||||
|
||||
int
|
||||
hd_ctlinput (prc, addr)
|
||||
int prc;
|
||||
struct sockaddr *addr;
|
||||
{
|
||||
register struct x25config *xcp = (struct x25config *)addr;
|
||||
register struct hdcb *hdp;
|
||||
register struct ifaddr *ifa;
|
||||
struct ifnet *ifp;
|
||||
caddr_t pk_newlink();
|
||||
void hd_writeinternal();
|
||||
void hd_message();
|
||||
|
||||
if (addr->sa_family != AF_CCITT)
|
||||
return (EAFNOSUPPORT);
|
||||
if (xcp->xc_lptype != HDLCPROTO_LAPB)
|
||||
return (EPROTONOSUPPORT);
|
||||
ifa = ifa_ifwithaddr(addr);
|
||||
if (ifa == 0 || ifa->ifa_addr->sa_family != AF_CCITT ||
|
||||
(ifp = ifa->ifa_ifp) == 0)
|
||||
panic ("hd_ctlinput");
|
||||
for (hdp = hdcbhead; hdp; hdp = hdp->hd_next)
|
||||
if (hdp->hd_ifp == ifp)
|
||||
break;
|
||||
|
||||
if (hdp == 0) { /* new interface */
|
||||
int error, hd_ifoutput(), hd_output();
|
||||
|
||||
/* an hdcb is now too big to fit in an mbuf */
|
||||
MALLOC(hdp, struct hdcb *, sizeof (*hdp), M_PCB, M_DONTWAIT);
|
||||
if (hdp == 0)
|
||||
return (ENOBUFS);
|
||||
bzero((caddr_t)hdp, sizeof(*hdp));
|
||||
hdp->hd_pkp =
|
||||
(caddr_t) pk_newlink ((struct x25_ifaddr *) ifa,
|
||||
(caddr_t) hdp);
|
||||
((struct x25_ifaddr *)ifa)->ia_pkcb =
|
||||
(struct pkcb *) hdp->hd_pkp;
|
||||
if (hdp -> hd_pkp == 0) {
|
||||
free(hdp, M_PCB);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
hdp->hd_ifp = ifp;
|
||||
hdp->hd_ifa = ifa;
|
||||
hdp->hd_xcp = xcp;
|
||||
hdp->hd_state = INIT;
|
||||
hdp->hd_output = hd_ifoutput;
|
||||
hdp->hd_next = hdcbhead;
|
||||
hdcbhead = hdp;
|
||||
} else if (hdp->hd_pkp == 0) { /* interface got reconfigured */
|
||||
hdp->hd_pkp =
|
||||
(caddr_t) pk_newlink ((struct x25_ifaddr *) ifa,
|
||||
(caddr_t) hdp);
|
||||
((struct x25_ifaddr *)ifa)->ia_pkcb =
|
||||
(struct pkcb *) hdp->hd_pkp;
|
||||
if (hdp -> hd_pkp == 0) {
|
||||
free(hdp, M_PCB);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
}
|
||||
|
||||
switch (prc) {
|
||||
case PRC_IFUP:
|
||||
if (xcp->xc_lwsize == 0 ||
|
||||
xcp->xc_lwsize > MAX_WINDOW_SIZE)
|
||||
xcp->xc_lwsize = MAX_WINDOW_SIZE;
|
||||
if (hdp->hd_state == INIT)
|
||||
SET_TIMER (hdp);
|
||||
break;
|
||||
|
||||
case PRC_IFDOWN:
|
||||
if (hdp->hd_state == ABM)
|
||||
hd_message (hdp, "Operator shutdown: link closed");
|
||||
(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
|
||||
|
||||
/* fall thru to ... */
|
||||
|
||||
case PRC_DISCONNECT_REQUEST:
|
||||
/* drop reference to pkcb --- it's dead meat */
|
||||
hdp->hd_pkp = (caddr_t) 0;
|
||||
((struct x25_ifaddr *)ifa)->ia_pkcb = (struct pkcb *) 0;
|
||||
|
||||
hd_writeinternal (hdp, DISC, POLLON);
|
||||
hdp->hd_state = DISC_SENT;
|
||||
SET_TIMER (hdp);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
hd_initvars (hdp)
|
||||
register struct hdcb *hdp;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register int i;
|
||||
|
||||
/* Clear Transmit queue. */
|
||||
while ((m = hd_remove (&hdp->hd_txq)) != NULL)
|
||||
m_freem (m);
|
||||
|
||||
/* Clear Retransmit queue. */
|
||||
i = hdp->hd_lastrxnr;
|
||||
while (i != hdp->hd_retxqi) {
|
||||
m_freem (hdp->hd_retxq[i]);
|
||||
i = (i + 1) % MODULUS;
|
||||
}
|
||||
hdp->hd_retxqi = 0;
|
||||
|
||||
hdp->hd_vs = hdp->hd_vr = 0;
|
||||
hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0;
|
||||
hdp->hd_rrtimer = 0;
|
||||
KILL_TIMER(hdp);
|
||||
hdp->hd_retxcnt = 0;
|
||||
hdp->hd_condition = 0;
|
||||
}
|
||||
|
||||
int
|
||||
hd_decode (hdp, frame)
|
||||
register struct hdcb *hdp;
|
||||
struct Hdlc_frame *frame;
|
||||
{
|
||||
register int frametype = ILLEGAL;
|
||||
register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame;
|
||||
register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame;
|
||||
register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame;
|
||||
|
||||
if (iframe -> hdlc_0 == 0) {
|
||||
frametype = IFRAME;
|
||||
hdp->hd_iframes_in++;
|
||||
}
|
||||
|
||||
else if (sframe -> hdlc_01 == 1) {
|
||||
/* Supervisory format. */
|
||||
switch (sframe -> s2) {
|
||||
case 0:
|
||||
frametype = RR;
|
||||
hdp->hd_rrs_in++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
frametype = RNR;
|
||||
hdp->hd_rnrs_in++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
frametype = REJ;
|
||||
hdp->hd_rejs_in++;
|
||||
}
|
||||
}
|
||||
else if (uframe -> hdlc_11 == 3) {
|
||||
/* Unnumbered format. */
|
||||
switch (uframe -> m3) {
|
||||
case 0:
|
||||
frametype = DM;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
frametype = SABM;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
frametype = DISC;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
frametype = UA;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
frametype = FRMR;
|
||||
hdp->hd_frmrs_in++;
|
||||
}
|
||||
}
|
||||
return (frametype);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called when the HDLC layer internally generates a
|
||||
* command or response for the remote machine ( eg. RR, UA etc. ).
|
||||
* Only supervisory or unnumbered frames are processed.
|
||||
*/
|
||||
|
||||
void
|
||||
hd_writeinternal (hdp, frametype, pf)
|
||||
register struct hdcb *hdp;
|
||||
register int frametype, pf;
|
||||
{
|
||||
register struct mbuf *buf;
|
||||
struct Hdlc_frame *frame;
|
||||
register struct Hdlc_sframe *sframe;
|
||||
register struct Hdlc_uframe *uframe;
|
||||
void hd_flush();
|
||||
|
||||
MGETHDR (buf, M_DONTWAIT, MT_HEADER);
|
||||
if (buf == 0)
|
||||
return;
|
||||
frame = mtod (buf, struct Hdlc_frame *);
|
||||
sframe = mtod (buf, struct Hdlc_sframe *);
|
||||
uframe = mtod (buf, struct Hdlc_uframe *);
|
||||
|
||||
/* Assume a response - address structure for DTE */
|
||||
frame -> address = ADDRESS_A;
|
||||
buf -> m_len = 2;
|
||||
buf -> m_act = buf -> m_next = NULL;
|
||||
|
||||
switch (frametype) {
|
||||
case RR:
|
||||
frame -> control = RR_CONTROL;
|
||||
hdp->hd_rrs_out++;
|
||||
break;
|
||||
|
||||
case RNR:
|
||||
frame -> control = RNR_CONTROL;
|
||||
hdp->hd_rnrs_out++;
|
||||
break;
|
||||
|
||||
case REJ:
|
||||
frame -> control = REJ_CONTROL;
|
||||
hdp->hd_rejs_out++;
|
||||
break;
|
||||
|
||||
case SABM:
|
||||
frame -> control = SABM_CONTROL;
|
||||
frame -> address = ADDRESS_B;
|
||||
break;
|
||||
|
||||
case DISC:
|
||||
if ((hdp->hd_ifp->if_flags & IFF_UP) == 0) {
|
||||
hdp->hd_state = DISCONNECTED;
|
||||
(void) m_freem (buf);
|
||||
hd_flush (hdp->hd_ifp);
|
||||
return;
|
||||
}
|
||||
frame -> control = DISC_CONTROL;
|
||||
frame -> address = ADDRESS_B;
|
||||
break;
|
||||
|
||||
case DM:
|
||||
frame -> control = DM_CONTROL;
|
||||
break;
|
||||
|
||||
case UA:
|
||||
frame -> control = UA_CONTROL;
|
||||
break;
|
||||
|
||||
case FRMR:
|
||||
frame -> control = FRMR_CONTROL;
|
||||
bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3);
|
||||
buf -> m_len = 5;
|
||||
hdp->hd_frmrs_out++;
|
||||
|
||||
}
|
||||
|
||||
if (sframe -> hdlc_01 == 1) {
|
||||
/* Supervisory format - RR, REJ, or RNR. */
|
||||
sframe -> nr = hdp->hd_vr;
|
||||
sframe -> pf = pf;
|
||||
hdp->hd_lasttxnr = hdp->hd_vr;
|
||||
hdp->hd_rrtimer = 0;
|
||||
}
|
||||
else
|
||||
uframe -> pf = pf;
|
||||
|
||||
hd_trace (hdp, TX, frame);
|
||||
buf -> m_pkthdr.len = buf -> m_len;
|
||||
(*hdp->hd_output) (hdp, buf);
|
||||
}
|
||||
|
||||
struct mbuf *
|
||||
hd_remove (q)
|
||||
struct hdtxq *q;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
|
||||
m = q -> head;
|
||||
if (m) {
|
||||
if ((q -> head = m -> m_act) == NULL)
|
||||
q -> tail = NULL;
|
||||
m -> m_act = 0;
|
||||
}
|
||||
return (m);
|
||||
}
|
||||
|
||||
void
|
||||
hd_append (q, m)
|
||||
register struct hdtxq *q;
|
||||
register struct mbuf *m;
|
||||
{
|
||||
|
||||
m -> m_act = NULL;
|
||||
if (q -> tail == NULL)
|
||||
q -> head = m;
|
||||
else
|
||||
q -> tail -> m_act = m;
|
||||
q -> tail = m;
|
||||
}
|
||||
|
||||
void
|
||||
hd_flush (ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register int s;
|
||||
|
||||
while (1) {
|
||||
s = splimp ();
|
||||
IF_DEQUEUE (&ifp->if_snd, m);
|
||||
splx (s);
|
||||
if (m == 0)
|
||||
break;
|
||||
m_freem (m);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hd_message (hdp, msg)
|
||||
struct hdcb *hdp;
|
||||
char *msg;
|
||||
{
|
||||
char *format_ntn ();
|
||||
|
||||
if (hdcbhead -> hd_next)
|
||||
printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg);
|
||||
else
|
||||
printf ("HDLC: %s\n", msg);
|
||||
}
|
||||
|
||||
#ifdef HDLCDEBUG
|
||||
void
|
||||
hd_status (hdp)
|
||||
struct hdcb *hdp;
|
||||
{
|
||||
printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n",
|
||||
hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi);
|
||||
|
||||
printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n",
|
||||
hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx);
|
||||
}
|
||||
#endif
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)hd_timer.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: hd_timer.c,v 1.3 1995/02/15 06:29:46 jkh Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/hdlc.h>
|
||||
#include <netccitt/hd_var.h>
|
||||
#include <netccitt/x25.h>
|
||||
|
||||
/*
|
||||
* these can be patched with adb if the
|
||||
* default values are inappropriate
|
||||
*/
|
||||
|
||||
/*
|
||||
* HDLC TIMER
|
||||
*
|
||||
* This routine is called every 500ms by the kernel. Decrement timer by this
|
||||
* amount - if expired then process the event.
|
||||
*/
|
||||
|
||||
void
|
||||
hd_timer ()
|
||||
{
|
||||
register struct hdcb *hdp;
|
||||
register int s = splimp ();
|
||||
|
||||
for (hdp = hdcbhead; hdp; hdp = hdp->hd_next) {
|
||||
if (hdp->hd_rrtimer && (--hdp->hd_rrtimer == 0)) {
|
||||
if (hdp->hd_lasttxnr != hdp->hd_vr)
|
||||
hd_writeinternal (hdp, RR, POLLOFF);
|
||||
}
|
||||
|
||||
if (!(hdp->hd_timer && --hdp->hd_timer == 0))
|
||||
continue;
|
||||
|
||||
switch (hdp->hd_state) {
|
||||
case INIT:
|
||||
case DISC_SENT:
|
||||
hd_writeinternal (hdp, DISC, POLLON);
|
||||
break;
|
||||
|
||||
case ABM:
|
||||
if (hdp->hd_lastrxnr != hdp->hd_vs) { /* XXX */
|
||||
hdp->hd_timeouts++;
|
||||
hd_resend_iframe (hdp);
|
||||
}
|
||||
break;
|
||||
|
||||
case WAIT_SABM:
|
||||
hd_writeinternal (hdp, FRMR, POLLOFF);
|
||||
if (++hdp->hd_retxcnt == hd_n2) {
|
||||
hdp->hd_retxcnt = 0;
|
||||
hd_writeinternal (hdp, SABM, POLLOFF);
|
||||
hdp->hd_state = WAIT_UA;
|
||||
}
|
||||
break;
|
||||
|
||||
case DM_SENT:
|
||||
if (++hdp->hd_retxcnt == hd_n2) {
|
||||
/* Notify the packet level. */
|
||||
(void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
|
||||
hdp->hd_retxcnt = 0;
|
||||
hdp->hd_state = SABM_SENT;
|
||||
hd_writeinternal (hdp, SABM, POLLOFF);
|
||||
} else
|
||||
hd_writeinternal (hdp, DM, POLLOFF);
|
||||
break;
|
||||
|
||||
case WAIT_UA:
|
||||
if (++hdp->hd_retxcnt == hd_n2) {
|
||||
hdp->hd_retxcnt = 0;
|
||||
hd_writeinternal (hdp, DM, POLLOFF);
|
||||
hdp->hd_state = DM_SENT;
|
||||
} else
|
||||
hd_writeinternal (hdp, SABM, POLLOFF);
|
||||
break;
|
||||
|
||||
case SABM_SENT:
|
||||
/* Do this indefinitely. */
|
||||
hd_writeinternal (hdp, SABM, POLLON);
|
||||
break;
|
||||
|
||||
case DISCONNECTED:
|
||||
/*
|
||||
* Poll the interface driver flags waiting
|
||||
* for the IFF_UP bit to come on.
|
||||
*/
|
||||
if (hdp->hd_ifp->if_flags & IFF_UP)
|
||||
hdp->hd_state = INIT;
|
||||
|
||||
}
|
||||
SET_TIMER (hdp);
|
||||
}
|
||||
|
||||
splx (s);
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)hd_var.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: hd_var.h,v 1.3 1994/08/21 05:44:06 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_HD_VAR_H_
|
||||
#define _NETCCITT_HD_VAR_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* hdlc control block
|
||||
*
|
||||
*/
|
||||
|
||||
struct hdtxq {
|
||||
struct mbuf *head;
|
||||
struct mbuf *tail;
|
||||
};
|
||||
|
||||
struct hdcb {
|
||||
struct hdcb *hd_next; /* pointer to next hdlc control block */
|
||||
char hd_state; /* link state */
|
||||
char hd_vs; /* send state variable */
|
||||
char hd_vr; /* receive state variable */
|
||||
char hd_lastrxnr; /* last received N(R) */
|
||||
char hd_lasttxnr; /* last transmitted N(R) */
|
||||
char hd_condition;
|
||||
#define TIMER_RECOVERY_CONDITION 0x01
|
||||
#define REJ_CONDITION 0x02
|
||||
#define REMOTE_RNR_CONDITION 0X04
|
||||
char hd_retxcnt;
|
||||
char hd_xx;
|
||||
struct hdtxq hd_txq;
|
||||
struct mbuf *hd_retxq[MODULUS];
|
||||
char hd_retxqi;
|
||||
char hd_rrtimer;
|
||||
char hd_timer;
|
||||
#define SET_TIMER(hdp) hdp->hd_timer = hd_t1
|
||||
#define KILL_TIMER(hdp) hdp->hd_timer = 0
|
||||
char hd_dontcopy; /* if-driver doesn't free I-frames */
|
||||
struct ifnet *hd_ifp; /* device's network visible interface */
|
||||
struct ifaddr *hd_ifa; /* device's X.25 network address */
|
||||
struct x25config *hd_xcp;
|
||||
caddr_t hd_pkp; /* Level III junk */
|
||||
int (*hd_output)(); /* separate entry for HDLC direct output */
|
||||
|
||||
/* link statistics */
|
||||
|
||||
long hd_iframes_in;
|
||||
long hd_iframes_out;
|
||||
long hd_rrs_in;
|
||||
long hd_rrs_out;
|
||||
short hd_rejs_in;
|
||||
short hd_rejs_out;
|
||||
long hd_window_condition;
|
||||
short hd_invalid_ns;
|
||||
short hd_invalid_nr;
|
||||
short hd_timeouts;
|
||||
short hd_resets;
|
||||
short hd_unknown;
|
||||
short hd_frmrs_in;
|
||||
short hd_frmrs_out;
|
||||
short hd_rnrs_in;
|
||||
short hd_rnrs_out;
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
extern struct hdcb *hdcbhead; /* head of linked list of hdcb's */
|
||||
extern struct Frmr_frame hd_frmr; /* rejected frame diagnostic info */
|
||||
extern struct ifqueue hdintrq; /* hdlc packet input queue */
|
||||
|
||||
extern int hd_t1; /* timer T1 value */
|
||||
extern int hd_t3; /* RR send timer */
|
||||
extern int hd_n2; /* frame retransmission limit */
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,162 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by the
|
||||
* Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)hdlc.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: hdlc.h,v 1.2 1994/08/02 07:47:12 davidg Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_HDLC_H_
|
||||
#define _NETCCITT_HDLC_H_
|
||||
|
||||
#ifndef ORDER4
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
typedef u_char octet;
|
||||
typedef char bool;
|
||||
|
||||
/*
|
||||
* HDLC Packet format definitions
|
||||
* This will eventually have to be rewritten without reference
|
||||
* to bit fields, to be compliant with ANSI C and alignment safe.
|
||||
*/
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define ORDER4(a, b, c, d) a , b , c , d
|
||||
#define ORDER5(a, b, c, d, e) a , b , c , d , e
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define ORDER4(a, b, c, d) d , c , b , a
|
||||
#define ORDER5(a, b, c, d, e) e , d , c , b , a
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_INFO_LEN 4096+3+4
|
||||
#define ADDRESS_A 3 /* B'00000011' */
|
||||
#define ADDRESS_B 1 /* B'00000001' */
|
||||
|
||||
struct Hdlc_iframe {
|
||||
octet address;
|
||||
octet ORDER4(nr:3, pf:1, ns:3, hdlc_0:1);
|
||||
octet i_field[MAX_INFO_LEN];
|
||||
};
|
||||
|
||||
struct Hdlc_sframe {
|
||||
octet address;
|
||||
octet ORDER4(nr:3, pf:1, s2:2, hdlc_01:2);
|
||||
};
|
||||
|
||||
struct Hdlc_uframe {
|
||||
octet address;
|
||||
octet ORDER4(m3:3, pf:1, m2:2, hdlc_11:2);
|
||||
};
|
||||
|
||||
struct Frmr_frame {
|
||||
octet address;
|
||||
octet control;
|
||||
octet frmr_control;
|
||||
octet ORDER4(frmr_nr:3, frmr_f1_0:1, frmr_ns:3, frmr_f2_0:1);
|
||||
octet ORDER5(frmr_0000:4, frmr_z:1, frmr_y:1, frmr_x:1, frmr_w:1);
|
||||
};
|
||||
|
||||
#define HDHEADERLN 2
|
||||
#define MINFRLN 2 /* Minimum frame length. */
|
||||
|
||||
struct Hdlc_frame {
|
||||
octet address;
|
||||
octet control;
|
||||
octet info[3]; /* min for FRMR */
|
||||
};
|
||||
|
||||
#define SABM_CONTROL 057 /* B'00101111' */
|
||||
#define UA_CONTROL 0143 /* B'01100011' */
|
||||
#define DISC_CONTROL 0103 /* B'01000011' */
|
||||
#define DM_CONTROL 017 /* B'00001111' */
|
||||
#define FRMR_CONTROL 0207 /* B'10000111' */
|
||||
#define RR_CONTROL 01 /* B'00000001' */
|
||||
#define RNR_CONTROL 05 /* B'00000101' */
|
||||
#define REJ_CONTROL 011 /* B'00001001' */
|
||||
|
||||
#define POLLOFF 0
|
||||
#define POLLON 1
|
||||
|
||||
/* Define Link State constants. */
|
||||
|
||||
#define INIT 0
|
||||
#define DM_SENT 1
|
||||
#define SABM_SENT 2
|
||||
#define ABM 3
|
||||
#define WAIT_SABM 4
|
||||
#define WAIT_UA 5
|
||||
#define DISC_SENT 6
|
||||
#define DISCONNECTED 7
|
||||
#define MAXSTATE 8
|
||||
|
||||
/* The following constants are used in a switch statement to process
|
||||
frames read from the communications line. */
|
||||
|
||||
#define SABM 0 * MAXSTATE
|
||||
#define DM 1 * MAXSTATE
|
||||
#define DISC 2 * MAXSTATE
|
||||
#define UA 3 * MAXSTATE
|
||||
#define FRMR 4 * MAXSTATE
|
||||
#define RR 5 * MAXSTATE
|
||||
#define RNR 6 * MAXSTATE
|
||||
#define REJ 7 * MAXSTATE
|
||||
#define IFRAME 8 * MAXSTATE
|
||||
#define ILLEGAL 9 * MAXSTATE
|
||||
|
||||
#define T1 (3 * PR_SLOWHZ) /* IFRAME TIMEOUT - 3 seconds */
|
||||
#define T3 (T1 / 2) /* RR generate timeout - 1.5 seconds */
|
||||
#define N2 10
|
||||
#define MODULUS 8
|
||||
#define MAX_WINDOW_SIZE 7
|
||||
|
||||
#define Z 0
|
||||
#define Y 1
|
||||
#define X 2
|
||||
#define W 3
|
||||
#define A 4
|
||||
|
||||
#define TX 0
|
||||
#define RX 1
|
||||
|
||||
bool range_check ();
|
||||
bool valid_nr ();
|
||||
struct mbuf *hd_remove ();
|
||||
|
||||
#endif
|
@ -1,826 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)if_x25subr.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: if_x25subr.c,v 1.8 1995/10/26 20:30:34 julian Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <machine/mtpr.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/netisr.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netccitt/x25.h>
|
||||
#include <netccitt/x25err.h>
|
||||
#include <netccitt/pk.h>
|
||||
#include <netccitt/pk_var.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#endif
|
||||
|
||||
#ifdef IPX
|
||||
#include <netipx/ipx.h>
|
||||
#include <netipx/ipx_if.h>
|
||||
#endif
|
||||
|
||||
#ifdef NS
|
||||
#include <netns/ns.h>
|
||||
#include <netns/ns_if.h>
|
||||
#endif
|
||||
|
||||
#ifdef ISO
|
||||
int tp_incoming();
|
||||
#include <netiso/argo_debug.h>
|
||||
#include <netiso/iso.h>
|
||||
#include <netiso/iso_var.h>
|
||||
#endif
|
||||
|
||||
struct llinfo_x25 llinfo_x25 = {&llinfo_x25, &llinfo_x25};
|
||||
#ifndef _offsetof
|
||||
#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
|
||||
#endif
|
||||
struct sockaddr *x25_dgram_sockmask;
|
||||
struct sockaddr_x25 x25_dgmask = {
|
||||
_offsetof(struct sockaddr_x25, x25_udata[1]), /* _len */
|
||||
0, /* _family */
|
||||
0, /* _net */
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* _addr */
|
||||
{0}, /* opts */
|
||||
-1, /* _udlen */
|
||||
{-1} /* _udata */
|
||||
};
|
||||
|
||||
struct if_x25stats {
|
||||
int ifx_wrongplen;
|
||||
int ifx_nophdr;
|
||||
} if_x25stats;
|
||||
int x25_autoconnect = 0;
|
||||
|
||||
#define senderr(x) {error = x; goto bad;}
|
||||
/*
|
||||
* Ancillary routines
|
||||
*/
|
||||
static struct llinfo_x25 *
|
||||
x25_lxalloc(rt)
|
||||
register struct rtentry *rt;
|
||||
{
|
||||
register struct llinfo_x25 *lx;
|
||||
register struct sockaddr *dst = rt_key(rt);
|
||||
register struct ifaddr *ifa;
|
||||
|
||||
MALLOC(lx, struct llinfo_x25 *, sizeof (*lx), M_PCB, M_NOWAIT);
|
||||
if (lx == 0)
|
||||
return lx;
|
||||
Bzero(lx, sizeof(*lx));
|
||||
lx->lx_rt = rt;
|
||||
lx->lx_family = dst->sa_family;
|
||||
rt->rt_refcnt++;
|
||||
if (rt->rt_llinfo)
|
||||
insque(lx, (struct llinfo_x25 *)rt->rt_llinfo);
|
||||
else {
|
||||
rt->rt_llinfo = (caddr_t)lx;
|
||||
insque(lx, &llinfo_x25);
|
||||
}
|
||||
for (ifa = rt->rt_ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr->sa_family == AF_CCITT)
|
||||
lx->lx_ia = (struct x25_ifaddr *)ifa;
|
||||
}
|
||||
return lx;
|
||||
}
|
||||
|
||||
static void
|
||||
x25_lxfree(lx)
|
||||
register struct llinfo_x25 *lx;
|
||||
{
|
||||
register struct rtentry *rt = lx->lx_rt;
|
||||
register struct pklcd *lcp = lx->lx_lcd;
|
||||
|
||||
if (lcp) {
|
||||
lcp->lcd_upper = 0;
|
||||
pk_disconnect(lcp);
|
||||
}
|
||||
if ((rt->rt_llinfo == (caddr_t)lx) && (lx->lx_next->lx_rt == rt))
|
||||
rt->rt_llinfo = (caddr_t)lx->lx_next;
|
||||
else
|
||||
rt->rt_llinfo = 0;
|
||||
RTFREE(rt);
|
||||
remque(lx);
|
||||
FREE(lx, M_PCB);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a x25 packet as datagram;
|
||||
*/
|
||||
static void
|
||||
x25_ifinput(lcp, m)
|
||||
struct pklcd *lcp;
|
||||
register struct mbuf *m;
|
||||
{
|
||||
struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext;
|
||||
register struct ifnet *ifp;
|
||||
struct ifqueue *inq;
|
||||
extern struct timeval time;
|
||||
int s, len, isr;
|
||||
void x25_connect_callback();
|
||||
|
||||
if (m == 0 || lcp->lcd_state != DATA_TRANSFER) {
|
||||
x25_connect_callback(lcp, 0);
|
||||
return;
|
||||
}
|
||||
pk_flowcontrol(lcp, 0, 1); /* Generate RR */
|
||||
ifp = m->m_pkthdr.rcvif;
|
||||
ifp->if_lastchange = time;
|
||||
switch (m->m_type) {
|
||||
default:
|
||||
if (m)
|
||||
m_freem(m);
|
||||
return;
|
||||
|
||||
case MT_DATA:
|
||||
/* FALLTHROUGH */;
|
||||
}
|
||||
switch (lx->lx_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
isr = NETISR_IP;
|
||||
inq = &ipintrq;
|
||||
break;
|
||||
|
||||
#endif
|
||||
#ifdef IPX
|
||||
case AF_IPX:
|
||||
isr = NETISR_IPX;
|
||||
inq = &ipxintrq;
|
||||
break;
|
||||
#endif
|
||||
#ifdef NS
|
||||
case AF_NS:
|
||||
isr = NETISR_NS;
|
||||
inq = &nsintrq;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ISO
|
||||
case AF_ISO:
|
||||
isr = NETISR_ISO;
|
||||
inq = &clnlintrq;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
m_freem(m);
|
||||
ifp->if_noproto++;
|
||||
return;
|
||||
}
|
||||
s = splimp();
|
||||
schednetisr(isr);
|
||||
if (IF_QFULL(inq)) {
|
||||
IF_DROP(inq);
|
||||
m_freem(m);
|
||||
} else {
|
||||
IF_ENQUEUE(inq, m);
|
||||
ifp->if_ibytes += m->m_pkthdr.len;
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static void
|
||||
x25_connect_callback(lcp, m)
|
||||
register struct pklcd *lcp;
|
||||
register struct mbuf *m;
|
||||
{
|
||||
register struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext;
|
||||
int do_clear = 1;
|
||||
if (m == 0)
|
||||
goto refused;
|
||||
if (m->m_type != MT_CONTROL) {
|
||||
printf("x25_connect_callback: should panic\n");
|
||||
goto refused;
|
||||
}
|
||||
switch (pk_decode(mtod(m, struct x25_packet *))) {
|
||||
case CALL_ACCEPTED:
|
||||
lcp->lcd_upper = x25_ifinput;
|
||||
if (lcp->lcd_sb.sb_mb)
|
||||
lcp->lcd_send(lcp); /* XXX start queued packets */
|
||||
return;
|
||||
default:
|
||||
do_clear = 0;
|
||||
refused:
|
||||
lcp->lcd_upper = 0;
|
||||
lx->lx_lcd = 0;
|
||||
if (do_clear)
|
||||
pk_disconnect(lcp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#define SA(p) ((struct sockaddr *)(p))
|
||||
#define RT(p) ((struct rtentry *)(p))
|
||||
|
||||
static void
|
||||
x25_dgram_incoming(lcp, m0)
|
||||
register struct pklcd *lcp;
|
||||
struct mbuf *m0;
|
||||
{
|
||||
register struct rtentry *rt, *nrt;
|
||||
register struct mbuf *m = m0->m_next; /* m0 has calling sockaddr_x25 */
|
||||
void x25_rtrequest();
|
||||
|
||||
rt = rtalloc1(SA(&lcp->lcd_faddr), 0, 0UL);
|
||||
if (rt == 0) {
|
||||
refuse: lcp->lcd_upper = 0;
|
||||
pk_close(lcp);
|
||||
return;
|
||||
}
|
||||
rt->rt_refcnt--;
|
||||
if ((nrt = RT(rt->rt_llinfo)) == 0 || rt_mask(rt) != x25_dgram_sockmask)
|
||||
goto refuse;
|
||||
if ((nrt->rt_flags & RTF_UP) == 0) {
|
||||
rt->rt_llinfo = (caddr_t)rtalloc1(rt->rt_gateway, 0, 0UL);
|
||||
rtfree(nrt);
|
||||
if ((nrt = RT(rt->rt_llinfo)) == 0)
|
||||
goto refuse;
|
||||
nrt->rt_refcnt--;
|
||||
}
|
||||
if (nrt->rt_ifa == 0 || nrt->rt_ifa->ifa_rtrequest != x25_rtrequest)
|
||||
goto refuse;
|
||||
lcp->lcd_send(lcp); /* confirm call */
|
||||
x25_rtattach(lcp, nrt);
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
/*
|
||||
* X.25 output routine.
|
||||
*/
|
||||
static int
|
||||
x25_ifoutput(ifp, m0, dst, rt)
|
||||
struct ifnet *ifp;
|
||||
struct mbuf *m0;
|
||||
struct sockaddr *dst;
|
||||
register struct rtentry *rt;
|
||||
{
|
||||
register struct mbuf *m = m0;
|
||||
register struct llinfo_x25 *lx;
|
||||
struct pklcd *lcp;
|
||||
int s, error = 0;
|
||||
|
||||
int plen;
|
||||
for (plen = 0; m; m = m->m_next)
|
||||
plen += m->m_len;
|
||||
m = m0;
|
||||
|
||||
if ((ifp->if_flags & IFF_UP) == 0)
|
||||
senderr(ENETDOWN);
|
||||
while (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) {
|
||||
if (rt) {
|
||||
if (rt->rt_llinfo) {
|
||||
rt = (struct rtentry *)rt->rt_llinfo;
|
||||
continue;
|
||||
}
|
||||
dst = rt->rt_gateway;
|
||||
}
|
||||
if ((rt = rtalloc1(dst, 1, 0UL)) == 0)
|
||||
senderr(EHOSTUNREACH);
|
||||
rt->rt_refcnt--;
|
||||
}
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if ((rt->rt_ifp != ifp) ||
|
||||
(rt->rt_flags & (RTF_CLONING | RTF_GATEWAY)) ||
|
||||
((lx = (struct llinfo_x25 *)rt->rt_llinfo) == 0)) {
|
||||
senderr(ENETUNREACH);
|
||||
}
|
||||
if ((m->m_flags & M_PKTHDR) == 0) {
|
||||
if_x25stats.ifx_nophdr++;
|
||||
m = m_gethdr(M_NOWAIT, MT_HEADER);
|
||||
if (m == 0)
|
||||
senderr(ENOBUFS);
|
||||
m->m_pkthdr.len = plen;
|
||||
m->m_next = m0;
|
||||
}
|
||||
if (plen != m->m_pkthdr.len) {
|
||||
if_x25stats.ifx_wrongplen++;
|
||||
m->m_pkthdr.len = plen;
|
||||
}
|
||||
next_circuit:
|
||||
lcp = lx->lx_lcd;
|
||||
if (lcp == 0) {
|
||||
lx->lx_lcd = lcp = pk_attach((struct socket *)0);
|
||||
if (lcp == 0)
|
||||
senderr(ENOBUFS);
|
||||
lcp->lcd_upper = x25_connect_callback;
|
||||
lcp->lcd_upnext = (caddr_t)lx;
|
||||
lcp->lcd_packetsize = lx->lx_ia->ia_xc.xc_psize;
|
||||
lcp->lcd_flags = X25_MBS_HOLD;
|
||||
}
|
||||
switch (lcp->lcd_state) {
|
||||
case READY:
|
||||
if (dst->sa_family == AF_INET &&
|
||||
ifp->if_type == IFT_X25DDN &&
|
||||
rt->rt_gateway->sa_family != AF_CCITT)
|
||||
x25_ddnip_to_ccitt(dst, rt);
|
||||
if (rt->rt_gateway->sa_family != AF_CCITT) {
|
||||
if ((rt->rt_flags & RTF_XRESOLVE) == 0)
|
||||
senderr(EHOSTUNREACH);
|
||||
} else if (x25_autoconnect)
|
||||
error = pk_connect(lcp,
|
||||
(struct sockaddr_x25 *)rt->rt_gateway);
|
||||
if (error)
|
||||
senderr(error);
|
||||
/* FALLTHROUGH */
|
||||
case SENT_CALL:
|
||||
case DATA_TRANSFER:
|
||||
if (sbspace(&lcp->lcd_sb) < 0) {
|
||||
lx = lx->lx_next;
|
||||
if (lx->lx_rt != rt)
|
||||
senderr(ENOSPC);
|
||||
goto next_circuit;
|
||||
}
|
||||
if (lx->lx_ia)
|
||||
lcp->lcd_dg_timer =
|
||||
lx->lx_ia->ia_xc.xc_dg_idletimo;
|
||||
pk_send(lcp, m);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* We count on the timer routine to close idle
|
||||
* connections, if there are not enough circuits to go
|
||||
* around.
|
||||
*
|
||||
* So throw away data for now.
|
||||
* After we get it all working, we'll rewrite to handle
|
||||
* actively closing connections (other than by timers),
|
||||
* when circuits get tight.
|
||||
*
|
||||
* In the DDN case, the imp itself closes connections
|
||||
* under heavy load.
|
||||
*/
|
||||
error = ENOBUFS;
|
||||
bad:
|
||||
if (m)
|
||||
m_freem(m);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simpleminded timer routine.
|
||||
*/
|
||||
static void
|
||||
x25_iftimeout(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
register struct pkcb *pkcb = 0;
|
||||
register struct pklcd **lcpp, *lcp;
|
||||
int s = splimp();
|
||||
|
||||
FOR_ALL_PKCBS(pkcb)
|
||||
if (pkcb->pk_ia->ia_ifp == ifp)
|
||||
for (lcpp = pkcb->pk_chan + pkcb->pk_maxlcn;
|
||||
--lcpp > pkcb->pk_chan;)
|
||||
if ((lcp = *lcpp) &&
|
||||
lcp->lcd_state == DATA_TRANSFER &&
|
||||
(lcp->lcd_flags & X25_DG_CIRCUIT) &&
|
||||
(lcp->lcd_dg_timer && --lcp->lcd_dg_timer == 0)) {
|
||||
lcp->lcd_upper(lcp, 0);
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
/*
|
||||
* This routine gets called when validating additions of new routes
|
||||
* or deletions of old ones.
|
||||
*/
|
||||
|
||||
static void
|
||||
x25_rtrequest(cmd, rt, dst)
|
||||
int cmd;
|
||||
register struct rtentry *rt;
|
||||
struct sockaddr *dst;
|
||||
{
|
||||
register struct llinfo_x25 *lx = (struct llinfo_x25 *)rt->rt_llinfo;
|
||||
register struct sockaddr_x25 *sa =(struct sockaddr_x25 *)rt->rt_gateway;
|
||||
register struct pklcd *lcp;
|
||||
|
||||
/* would put this pk_init, except routing table doesn't
|
||||
exist yet. */
|
||||
if (x25_dgram_sockmask == 0) {
|
||||
x25_dgram_sockmask =
|
||||
SA(rn_addmask((caddr_t)&x25_dgmask, 0, 4)->rn_key);
|
||||
}
|
||||
if (rt->rt_flags & RTF_GATEWAY) {
|
||||
if (rt->rt_llinfo)
|
||||
RTFREE((struct rtentry *)rt->rt_llinfo);
|
||||
rt->rt_llinfo = (cmd == RTM_ADD) ?
|
||||
(caddr_t)rtalloc1(rt->rt_gateway, 1, 0UL) : 0;
|
||||
return;
|
||||
}
|
||||
if ((rt->rt_flags & RTF_HOST) == 0)
|
||||
return;
|
||||
if (cmd == RTM_DELETE) {
|
||||
while (rt->rt_llinfo)
|
||||
x25_lxfree((struct llinfo *)rt->rt_llinfo);
|
||||
x25_rtinvert(RTM_DELETE, rt->rt_gateway, rt);
|
||||
return;
|
||||
}
|
||||
if (lx == 0 && (lx = x25_lxalloc(rt)) == 0)
|
||||
return;
|
||||
if ((lcp = lx->lx_lcd) && lcp->lcd_state != READY) {
|
||||
/*
|
||||
* This can only happen on a RTM_CHANGE operation
|
||||
* though cmd will be RTM_ADD.
|
||||
*/
|
||||
if (lcp->lcd_ceaddr &&
|
||||
Bcmp(rt->rt_gateway, lcp->lcd_ceaddr,
|
||||
lcp->lcd_ceaddr->x25_len) != 0) {
|
||||
x25_rtinvert(RTM_DELETE, lcp->lcd_ceaddr, rt);
|
||||
lcp->lcd_upper = 0;
|
||||
pk_disconnect(lcp);
|
||||
}
|
||||
lcp = 0;
|
||||
}
|
||||
x25_rtinvert(RTM_ADD, rt->rt_gateway, rt);
|
||||
}
|
||||
|
||||
int x25_dont_rtinvert = 0;
|
||||
|
||||
static void
|
||||
x25_rtinvert(cmd, sa, rt)
|
||||
register struct sockaddr *sa;
|
||||
register struct rtentry *rt;
|
||||
{
|
||||
struct rtentry *rt2 = 0;
|
||||
/*
|
||||
* rt_gateway contains PID indicating which proto
|
||||
* family on the other end, so will be different
|
||||
* from general host route via X.25.
|
||||
*/
|
||||
if (rt->rt_ifp->if_type == IFT_X25DDN || x25_dont_rtinvert)
|
||||
return;
|
||||
if (sa->sa_family != AF_CCITT)
|
||||
return;
|
||||
if (cmd != RTM_DELETE) {
|
||||
rtrequest(RTM_ADD, sa, rt_key(rt), x25_dgram_sockmask,
|
||||
RTF_PROTO2, &rt2);
|
||||
if (rt2) {
|
||||
rt2->rt_llinfo = (caddr_t) rt;
|
||||
rt->rt_refcnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
rt2 = rt;
|
||||
if ((rt = rtalloc1(sa, 0, 0UL)) == 0 ||
|
||||
(rt->rt_flags & RTF_PROTO2) == 0 ||
|
||||
rt->rt_llinfo != (caddr_t)rt2) {
|
||||
printf("x25_rtchange: inverse route screwup\n");
|
||||
return;
|
||||
} else
|
||||
rt2->rt_refcnt--;
|
||||
rtrequest(RTM_DELETE, sa, rt_key(rt2), x25_dgram_sockmask,
|
||||
0, (struct rtentry **) 0);
|
||||
}
|
||||
|
||||
static struct sockaddr_x25 blank_x25 = {sizeof blank_x25, AF_CCITT};
|
||||
/*
|
||||
* IP to X25 address routine copyright ACC, used by permission.
|
||||
*/
|
||||
union imp_addr {
|
||||
struct in_addr ip;
|
||||
struct imp {
|
||||
u_char s_net;
|
||||
u_char s_host;
|
||||
u_char s_lh;
|
||||
u_char s_impno;
|
||||
} imp;
|
||||
};
|
||||
|
||||
/*
|
||||
* The following is totally bogus and here only to preserve
|
||||
* the IP to X.25 translation.
|
||||
*/
|
||||
static int
|
||||
x25_ddnip_to_ccitt(src, rt)
|
||||
struct sockaddr_in *src;
|
||||
register struct rtentry *rt;
|
||||
{
|
||||
register struct sockaddr_x25 *dst = (struct sockaddr_x25 *)rt->rt_gateway;
|
||||
union imp_addr imp_addr;
|
||||
int imp_no, imp_port, temp;
|
||||
char *x25addr = dst->x25_addr;
|
||||
|
||||
|
||||
imp_addr.ip = src->sin_addr;
|
||||
*dst = blank_x25;
|
||||
if ((imp_addr.imp.s_net & 0x80) == 0x00) { /* class A */
|
||||
imp_no = imp_addr.imp.s_impno;
|
||||
imp_port = imp_addr.imp.s_host;
|
||||
} else if ((imp_addr.imp.s_net & 0xc0) == 0x80) { /* class B */
|
||||
imp_no = imp_addr.imp.s_impno;
|
||||
imp_port = imp_addr.imp.s_lh;
|
||||
} else { /* class C */
|
||||
imp_no = imp_addr.imp.s_impno / 32;
|
||||
imp_port = imp_addr.imp.s_impno % 32;
|
||||
}
|
||||
|
||||
x25addr[0] = 12; /* length */
|
||||
/* DNIC is cleared by struct copy above */
|
||||
|
||||
if (imp_port < 64) { /* Physical: 0000 0 IIIHH00 [SS] *//* s_impno
|
||||
* -> III, s_host -> HH */
|
||||
x25addr[5] = 0; /* set flag bit */
|
||||
x25addr[6] = imp_no / 100;
|
||||
x25addr[7] = (imp_no % 100) / 10;
|
||||
x25addr[8] = imp_no % 10;
|
||||
x25addr[9] = imp_port / 10;
|
||||
x25addr[10] = imp_port % 10;
|
||||
} else { /* Logical: 0000 1 RRRRR00 [SS] *//* s
|
||||
* _host * 256 + s_impno -> RRRRR */
|
||||
temp = (imp_port << 8) + imp_no;
|
||||
x25addr[5] = 1;
|
||||
x25addr[6] = temp / 10000;
|
||||
x25addr[7] = (temp % 10000) / 1000;
|
||||
x25addr[8] = (temp % 1000) / 100;
|
||||
x25addr[9] = (temp % 100) / 10;
|
||||
x25addr[10] = temp % 10;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is a sketch and is not to be believed!!!!!
|
||||
*
|
||||
* This is a utility routine to be called by x25 devices when a
|
||||
* call request is honored with the intent of starting datagram forwarding.
|
||||
*/
|
||||
static int
|
||||
x25_dg_rtinit(dst, ia, af)
|
||||
struct sockaddr_x25 *dst;
|
||||
register struct x25_ifaddr *ia;
|
||||
{
|
||||
struct sockaddr *sa = 0;
|
||||
struct rtentry *rt;
|
||||
struct in_addr my_addr;
|
||||
static struct sockaddr_in sin = {sizeof(sin), AF_INET};
|
||||
|
||||
if (ia->ia_ifp->if_type == IFT_X25DDN && af == AF_INET) {
|
||||
/*
|
||||
* Inverse X25 to IP mapping copyright and courtesy ACC.
|
||||
*/
|
||||
int imp_no, imp_port, temp;
|
||||
union imp_addr imp_addr;
|
||||
{
|
||||
/*
|
||||
* First determine our IP addr for network
|
||||
*/
|
||||
register struct in_ifaddr *ina;
|
||||
|
||||
for (ina = in_ifaddr; ina; ina = ina->ia_next)
|
||||
if (ina->ia_ifp == ia->ia_ifp) {
|
||||
my_addr = ina->ia_addr.sin_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
|
||||
register char *x25addr = dst->x25_addr;
|
||||
|
||||
switch (x25addr[5] & 0x0f) {
|
||||
case 0: /* Physical: 0000 0 IIIHH00 [SS] */
|
||||
imp_no =
|
||||
((int) (x25addr[6] & 0x0f) * 100) +
|
||||
((int) (x25addr[7] & 0x0f) * 10) +
|
||||
((int) (x25addr[8] & 0x0f));
|
||||
|
||||
|
||||
imp_port =
|
||||
((int) (x25addr[9] & 0x0f) * 10) +
|
||||
((int) (x25addr[10] & 0x0f));
|
||||
break;
|
||||
case 1: /* Logical: 0000 1 RRRRR00 [SS] */
|
||||
temp = ((int) (x25addr[6] & 0x0f) * 10000)
|
||||
+ ((int) (x25addr[7] & 0x0f) * 1000)
|
||||
+ ((int) (x25addr[8] & 0x0f) * 100)
|
||||
+ ((int) (x25addr[9] & 0x0f) * 10)
|
||||
+ ((int) (x25addr[10] & 0x0f));
|
||||
|
||||
imp_port = temp >> 8;
|
||||
imp_no = temp & 0xff;
|
||||
break;
|
||||
default:
|
||||
return (0L);
|
||||
}
|
||||
imp_addr.ip = my_addr;
|
||||
if ((imp_addr.imp.s_net & 0x80) == 0x00) {
|
||||
/* class A */
|
||||
imp_addr.imp.s_host = imp_port;
|
||||
imp_addr.imp.s_impno = imp_no;
|
||||
imp_addr.imp.s_lh = 0;
|
||||
} else if ((imp_addr.imp.s_net & 0xc0) == 0x80) {
|
||||
/* class B */
|
||||
imp_addr.imp.s_lh = imp_port;
|
||||
imp_addr.imp.s_impno = imp_no;
|
||||
} else {
|
||||
/* class C */
|
||||
imp_addr.imp.s_impno = (imp_no << 5) + imp_port;
|
||||
}
|
||||
}
|
||||
sin.sin_addr = imp_addr.ip;
|
||||
sa = (struct sockaddr *)&sin;
|
||||
} else {
|
||||
/*
|
||||
* This uses the X25 routing table to do inverse
|
||||
* lookup of x25 address to sockaddr.
|
||||
*/
|
||||
if (rt = rtalloc1(SA(dst), 0, 0UL)) {
|
||||
sa = rt->rt_gateway;
|
||||
rt->rt_refcnt--;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Call to rtalloc1 will create rtentry for reverse path
|
||||
* to callee by virtue of cloning magic and will allocate
|
||||
* space for local control block.
|
||||
*/
|
||||
if (sa && (rt = rtalloc1(sa, 1, 0UL)))
|
||||
rt->rt_refcnt--;
|
||||
}
|
||||
int x25_startproto = 1;
|
||||
|
||||
pk_init()
|
||||
{
|
||||
/*
|
||||
* warning, sizeof (struct sockaddr_x25) > 32,
|
||||
* but contains no data of interest beyond 32
|
||||
*/
|
||||
if (x25_startproto) {
|
||||
pk_protolisten(0xcc, 1, x25_dgram_incoming);
|
||||
pk_protolisten(0x81, 1, x25_dgram_incoming);
|
||||
}
|
||||
}
|
||||
|
||||
struct x25_dgproto {
|
||||
u_char spi;
|
||||
u_char spilen;
|
||||
int (*f)();
|
||||
} x25_dgprototab[] = {
|
||||
#if defined(ISO) && defined(TPCONS)
|
||||
{ 0x0, 0, tp_incoming},
|
||||
#endif
|
||||
{ 0xcc, 1, x25_dgram_incoming},
|
||||
{ 0xcd, 1, x25_dgram_incoming},
|
||||
{ 0x81, 1, x25_dgram_incoming},
|
||||
};
|
||||
|
||||
pk_user_protolisten(info)
|
||||
register u_char *info;
|
||||
{
|
||||
register struct x25_dgproto *dp = x25_dgprototab
|
||||
+ ((sizeof x25_dgprototab) / (sizeof *dp));
|
||||
register struct pklcd *lcp;
|
||||
|
||||
while (dp > x25_dgprototab)
|
||||
if ((--dp)->spi == info[0])
|
||||
goto gotspi;
|
||||
return ESRCH;
|
||||
|
||||
gotspi: if (info[1])
|
||||
return pk_protolisten(dp->spi, dp->spilen, dp->f);
|
||||
for (lcp = pk_listenhead; lcp; lcp = lcp->lcd_listen)
|
||||
if (lcp->lcd_laddr.x25_udlen == dp->spilen &&
|
||||
Bcmp(&dp->spi, lcp->lcd_laddr.x25_udata, dp->spilen) == 0) {
|
||||
pk_disconnect(lcp);
|
||||
return 0;
|
||||
}
|
||||
return ESRCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine transfers an X.25 circuit to or from a routing entry.
|
||||
* If the supplied circuit is * in DATA_TRANSFER state, it is added to the
|
||||
* routing entry. If freshly allocated, it glues back the vc from
|
||||
* the rtentry to the socket.
|
||||
*/
|
||||
pk_rtattach(so, m0)
|
||||
register struct socket *so;
|
||||
struct mbuf *m0;
|
||||
{
|
||||
register struct pklcd *lcp = (struct pklcd *)so->so_pcb;
|
||||
register struct mbuf *m = m0;
|
||||
struct sockaddr *dst = mtod(m, struct sockaddr *);
|
||||
register struct rtentry *rt = rtalloc1(dst, 0, 0UL);
|
||||
register struct llinfo_x25 *lx;
|
||||
caddr_t cp;
|
||||
#define ROUNDUP(a) \
|
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||
#define transfer_sockbuf(s, f, l) \
|
||||
while (m = (s)->sb_mb)\
|
||||
{(s)->sb_mb = m->m_act; m->m_act = 0; sbfree((s), m); f(l, m);}
|
||||
|
||||
if (rt)
|
||||
rt->rt_refcnt--;
|
||||
cp = (dst->sa_len < m->m_len) ? ROUNDUP(dst->sa_len) + (caddr_t)dst : 0;
|
||||
while (rt &&
|
||||
((cp == 0 && rt_mask(rt) != 0) ||
|
||||
(cp != 0 && (rt_mask(rt) == 0 ||
|
||||
Bcmp(cp, rt_mask(rt), rt_mask(rt)->sa_len)) != 0)))
|
||||
rt = (struct rtentry *)rt->rt_nodes->rn_dupedkey;
|
||||
if (rt == 0 || (rt->rt_flags & RTF_GATEWAY) ||
|
||||
(lx = (struct llinfo_x25 *)rt->rt_llinfo) == 0)
|
||||
return ESRCH;
|
||||
if (lcp == 0)
|
||||
return ENOTCONN;
|
||||
switch (lcp->lcd_state) {
|
||||
default:
|
||||
return ENOTCONN;
|
||||
|
||||
case READY:
|
||||
/* Detach VC from rtentry */
|
||||
if (lx->lx_lcd == 0)
|
||||
return ENOTCONN;
|
||||
lcp->lcd_so = 0;
|
||||
pk_close(lcp);
|
||||
lcp = lx->lx_lcd;
|
||||
if (lx->lx_next->lx_rt == rt)
|
||||
x25_lxfree(lx);
|
||||
lcp->lcd_so = so;
|
||||
lcp->lcd_upper = 0;
|
||||
lcp->lcd_upnext = 0;
|
||||
transfer_sockbuf(&lcp->lcd_sb, sbappendrecord, &so->so_snd);
|
||||
soisconnected(so);
|
||||
return 0;
|
||||
|
||||
case DATA_TRANSFER:
|
||||
/* Add VC to rtentry */
|
||||
lcp->lcd_so = 0;
|
||||
lcp->lcd_sb = so->so_snd; /* structure copy */
|
||||
bzero((caddr_t)&so->so_snd, sizeof(so->so_snd)); /* XXXXXX */
|
||||
so->so_pcb = 0;
|
||||
x25_rtattach(lcp, rt);
|
||||
transfer_sockbuf(&so->so_rcv, x25_ifinput, lcp);
|
||||
soisdisconnected(so);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
x25_rtattach(lcp0, rt)
|
||||
register struct pklcd *lcp0;
|
||||
struct rtentry *rt;
|
||||
{
|
||||
register struct llinfo_x25 *lx = (struct llinfo_x25 *)rt->rt_llinfo;
|
||||
register struct pklcd *lcp;
|
||||
register struct mbuf *m;
|
||||
if (lcp = lx->lx_lcd) { /* adding an additional VC */
|
||||
if (lcp->lcd_state == READY) {
|
||||
transfer_sockbuf(&lcp->lcd_sb, pk_output, lcp0);
|
||||
lcp->lcd_upper = 0;
|
||||
pk_close(lcp);
|
||||
} else {
|
||||
lx = x25_lxalloc(rt);
|
||||
if (lx == 0)
|
||||
return ENOBUFS;
|
||||
}
|
||||
}
|
||||
lx->lx_lcd = lcp = lcp0;
|
||||
lcp->lcd_upper = x25_ifinput;
|
||||
lcp->lcd_upnext = (caddr_t)lx;
|
||||
}
|
@ -1,470 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Dirk Husemann, Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Dirk Husemann and the Computer Science Department (IV) of
|
||||
* the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)llc_input.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: llc_input.c,v 1.3 1994/12/13 22:32:13 wollman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_llc.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netccitt/dll.h>
|
||||
#include <netccitt/llc_var.h>
|
||||
|
||||
/*
|
||||
* This module implements LLC as specified by ISO 8802-2.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* llcintr() handles all LLC frames (except ISO CLNS ones for the time being)
|
||||
* and tries to pass them on to the appropriate network layer entity.
|
||||
*/
|
||||
void
|
||||
llcintr()
|
||||
{
|
||||
register struct mbuf *m;
|
||||
register int i;
|
||||
register int frame_kind;
|
||||
register u_char cmdrsp;
|
||||
struct llc_linkcb *linkp;
|
||||
struct rtentry *sirt;
|
||||
struct npaidbentry *sapinfo;
|
||||
struct sdl_hdr *sdlhdr;
|
||||
struct llc *frame;
|
||||
char *c;
|
||||
long expected_len;
|
||||
|
||||
struct ifnet *ifp;
|
||||
struct rtentry *llrt;
|
||||
struct rtentry *nlrt;
|
||||
|
||||
for (;;) {
|
||||
i = splimp();
|
||||
IF_DEQUEUE(&llcintrq, m);
|
||||
splx(i);
|
||||
if (m == 0)
|
||||
break;
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((m->m_flags & M_PKTHDR) == 0)
|
||||
panic("llcintr no HDR");
|
||||
#endif
|
||||
/*
|
||||
* Get ifp this packet was received on
|
||||
*/
|
||||
ifp = m->m_pkthdr.rcvif;
|
||||
|
||||
sdlhdr = mtod(m, struct sdl_hdr *);
|
||||
|
||||
/*
|
||||
* [Copied from net/ip_input.c]
|
||||
*
|
||||
* Check that the amount of data in the buffers is
|
||||
* at least as much as the LLC header tells us.
|
||||
* Trim mbufs if longer than expected.
|
||||
* Drop packets if shorter than we think they are.
|
||||
*
|
||||
* Layout of mbuf chain at this point:
|
||||
*
|
||||
* +-------------------------------+----+ -\
|
||||
* | sockaddr_dl src - sdlhdr_src | 20 | \
|
||||
* +-------------------------------+----+ |
|
||||
* | sockaddr_dl dst - sdlhdr_dst | 20 | > sizeof(struct sdl_hdr) == 44
|
||||
* +-------------------------------+----+ |
|
||||
* | LLC frame len - sdlhdr_len | 04 | /
|
||||
* +-------------------------------+----+ -/
|
||||
* /
|
||||
* | m_next
|
||||
* \
|
||||
* +----------------------------+----+ -\
|
||||
* | llc DSAP | 01 | \
|
||||
* +----------------------------+----+ |
|
||||
* | llc SSAP | 01 | |
|
||||
* +----------------------------+----+ > sdlhdr_len
|
||||
* | llc control | 01 | |
|
||||
* +----------------------------+----+ |
|
||||
* | ... | | /
|
||||
* -/
|
||||
*
|
||||
* Thus the we expect to have exactly
|
||||
* (sdlhdr->sdlhdr_len+sizeof(struct sdl_hdr)) in the mbuf chain
|
||||
*/
|
||||
expected_len = sdlhdr->sdlhdr_len + sizeof(struct sdl_hdr);
|
||||
|
||||
if (m->m_pkthdr.len < expected_len) {
|
||||
m_freem(m);
|
||||
continue;
|
||||
}
|
||||
if (m->m_pkthdr.len > expected_len) {
|
||||
if (m->m_len == m->m_pkthdr.len) {
|
||||
m->m_len = expected_len;
|
||||
m->m_pkthdr.len = expected_len;
|
||||
} else
|
||||
m_adj(m, expected_len - m->m_pkthdr.len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get llc header
|
||||
*/
|
||||
if (m->m_len > sizeof(struct sdl_hdr))
|
||||
frame = mtod((struct mbuf *)((struct sdl_hdr*)(m+1)),
|
||||
struct llc *);
|
||||
else frame = mtod(m->m_next, struct llc *);
|
||||
if (frame == (struct llc *) NULL)
|
||||
panic("llcintr no llc header");
|
||||
|
||||
/*
|
||||
* Now check for bogus I/S frame, i.e. those with a control
|
||||
* field telling us they're an I/S frame yet their length
|
||||
* is less than the established I/S frame length (DSAP + SSAP +
|
||||
* control + N(R)&P/F = 4) --- we drop those suckers
|
||||
*/
|
||||
if (((frame->llc_control & 0x03) != 0x03)
|
||||
&& ((expected_len - sizeof(struct sdl_hdr)) < LLC_ISFRAMELEN)) {
|
||||
m_freem(m);
|
||||
printf("llc: hurz error\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get link control block for the addressed link connection.
|
||||
* If there is none we take care of it later on.
|
||||
*/
|
||||
cmdrsp = (frame->llc_ssap & 0x01);
|
||||
frame->llc_ssap &= ~0x01;
|
||||
if (llrt = rtalloc1((struct sockaddr *)&sdlhdr->sdlhdr_src, 0,
|
||||
0UL))
|
||||
llrt->rt_refcnt--;
|
||||
#ifdef notyet
|
||||
else llrt = npaidb_enter(&sdlhdr->sdlhdr_src, 0, 0, 0);
|
||||
#endif /* notyet */
|
||||
else {
|
||||
/*
|
||||
* We cannot do anything currently here as we
|
||||
* don't `know' this link --- drop it
|
||||
*/
|
||||
m_freem(m);
|
||||
continue;
|
||||
}
|
||||
linkp = ((struct npaidbentry *)(llrt->rt_llinfo))->np_link;
|
||||
nlrt = ((struct npaidbentry *)(llrt->rt_llinfo))->np_rt;
|
||||
|
||||
/*
|
||||
* If the link is not existing right now, we can try and look up
|
||||
* the SAP info block.
|
||||
*/
|
||||
if ((linkp == 0) && frame->llc_ssap)
|
||||
sapinfo = llc_getsapinfo(frame->llc_dsap, ifp);
|
||||
|
||||
/*
|
||||
* Handle XID and TEST frames
|
||||
* XID: if DLSAP == 0, return type-of-services
|
||||
* window-0
|
||||
* DLSAP-0
|
||||
* format-identifier-?
|
||||
* if DLSAP != 0, locate sapcb and return
|
||||
* type-of-services
|
||||
* SAP-window
|
||||
* format-identifier-?
|
||||
* TEST: swap (snpah_dst, snpah_src) and return frame
|
||||
*
|
||||
* Also toggle the CMD/RESP bit
|
||||
*
|
||||
* Is this behaviour correct? Check ISO 8802-2 (90)!
|
||||
*/
|
||||
frame_kind = llc_decode(frame, (struct llc_linkcb *)0);
|
||||
switch(frame_kind) {
|
||||
case LLCFT_XID:
|
||||
if (linkp || sapinfo) {
|
||||
if (linkp)
|
||||
frame->llc_window = linkp->llcl_window;
|
||||
else frame->llc_window = sapinfo->si_window;
|
||||
frame->llc_fid = 9; /* XXX */
|
||||
frame->llc_class = sapinfo->si_class;
|
||||
frame->llc_ssap = frame->llc_dsap;
|
||||
} else {
|
||||
frame->llc_window = 0;
|
||||
frame->llc_fid = 9;
|
||||
frame->llc_class = 1;
|
||||
frame->llc_dsap = frame->llc_ssap = 0;
|
||||
}
|
||||
|
||||
/* fall thru to */
|
||||
case LLCFT_TEST:
|
||||
sdl_swapaddr(&(mtod(m, struct sdl_hdr *)->sdlhdr_dst),
|
||||
&(mtod(m, struct sdl_hdr *)->sdlhdr_src));
|
||||
|
||||
/* Now set the CMD/RESP bit */
|
||||
frame->llc_ssap |= (cmdrsp == 0x0 ? 0x1 : 0x0);
|
||||
|
||||
/* Ship it out again */
|
||||
(*ifp->if_output)(ifp, m,
|
||||
(struct sockaddr *) &(mtod(m, struct sdl_hdr *)->sdlhdr_dst),
|
||||
(struct rtentry *) 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create link control block in case it is not existing
|
||||
*/
|
||||
if (linkp == 0 && sapinfo) {
|
||||
if ((linkp = llc_newlink(&sdlhdr->sdlhdr_src, ifp, nlrt,
|
||||
(nlrt == 0) ? 0 : nlrt->rt_llinfo,
|
||||
llrt)) == 0) {
|
||||
printf("llcintr: couldn't create new link\n");
|
||||
m_freem(m);
|
||||
continue;
|
||||
}
|
||||
((struct npaidbentry *)llrt->rt_llinfo)->np_link = linkp;
|
||||
} else if (linkp == 0) {
|
||||
/* The link is not known to us, drop the frame and continue */
|
||||
m_freem(m);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop SNPA header and get rid of empty mbuf at the
|
||||
* front of the mbuf chain (I don't like 'em)
|
||||
*/
|
||||
m_adj(m, sizeof(struct sdl_hdr));
|
||||
/*
|
||||
* LLC_UFRAMELEN is sufficient, m_pullup() will pull up
|
||||
* the min(m->m_len, maxprotohdr_len [=40]) thus doing
|
||||
* the trick ...
|
||||
*/
|
||||
if ((m = m_pullup(m, LLC_UFRAMELEN)))
|
||||
/*
|
||||
* Pass it on thru the elements of procedure
|
||||
*/
|
||||
llc_input(linkp, m, cmdrsp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* llc_input() --- We deal with the various incoming frames here.
|
||||
* Basically we (indirectly) call the appropriate
|
||||
* state handler function that's pointed to by
|
||||
* llcl_statehandler.
|
||||
*
|
||||
* The statehandler returns an action code ---
|
||||
* further actions like
|
||||
* o notify network layer
|
||||
* o block further sending
|
||||
* o deblock link
|
||||
* o ...
|
||||
* are then enacted accordingly.
|
||||
*/
|
||||
llc_input(struct llc_linkcb *linkp, struct mbuf *m, u_char cmdrsp)
|
||||
{
|
||||
int frame_kind;
|
||||
int pollfinal;
|
||||
int action = 0;
|
||||
struct llc *frame;
|
||||
struct ifnet *ifp = linkp->llcl_if;
|
||||
|
||||
if ((frame = mtod(m, struct llc *)) == (struct llc *) 0) {
|
||||
m_freem(m);
|
||||
return 0;
|
||||
}
|
||||
pollfinal = ((frame->llc_control & 0x03) == 0x03) ?
|
||||
LLCGBITS(frame->llc_control, u_pf) :
|
||||
LLCGBITS(frame->llc_control_ext, s_pf);
|
||||
|
||||
/*
|
||||
* first decode the frame
|
||||
*/
|
||||
frame_kind = llc_decode(frame, linkp);
|
||||
|
||||
switch (action = llc_statehandler(linkp, frame, frame_kind, cmdrsp,
|
||||
pollfinal)) {
|
||||
case LLC_DATA_INDICATION:
|
||||
m_adj(m, LLC_ISFRAMELEN);
|
||||
if (m = m_pullup(m, NLHDRSIZEGUESS)) {
|
||||
m->m_pkthdr.rcvif = (struct ifnet *)linkp->llcl_nlnext;
|
||||
(*linkp->llcl_sapinfo->si_input)(m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* release mbuf if not an info frame */
|
||||
if (action != LLC_DATA_INDICATION && m)
|
||||
m_freem(m);
|
||||
|
||||
/* try to get frames out ... */
|
||||
llc_start(linkp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called by configuration setup. It sets up a station control
|
||||
* block and notifies all registered upper level protocols.
|
||||
*/
|
||||
caddr_t
|
||||
llc_ctlinput(int prc, struct sockaddr *addr, caddr_t info)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
struct dll_ctlinfo *ctlinfo = (struct dll_ctlinfo *)info;
|
||||
u_char sap;
|
||||
struct dllconfig *config;
|
||||
caddr_t pcb;
|
||||
struct rtentry *nlrt;
|
||||
struct rtentry *llrt;
|
||||
struct llc_linkcb *linkp;
|
||||
register int i;
|
||||
|
||||
/* info must point to something valid at all times */
|
||||
if (info == 0)
|
||||
return 0;
|
||||
|
||||
if (prc == PRC_IFUP || prc == PRC_IFDOWN) {
|
||||
/* we use either this set ... */
|
||||
ifa = ifa_ifwithaddr(addr);
|
||||
ifp = ifa ? ifa->ifa_ifp : 0;
|
||||
if (ifp == 0)
|
||||
return 0;
|
||||
|
||||
sap = ctlinfo->dlcti_lsap;
|
||||
config = ctlinfo->dlcti_cfg;
|
||||
pcb = (caddr_t) 0;
|
||||
nlrt = (struct rtentry *) 0;
|
||||
} else {
|
||||
/* or this one */
|
||||
sap = 0;
|
||||
config = (struct dllconfig *) 0;
|
||||
pcb = ctlinfo->dlcti_pcb;
|
||||
nlrt = ctlinfo->dlcti_rt;
|
||||
|
||||
if ((llrt = rtalloc1(nlrt->rt_gateway, 0, 0UL)))
|
||||
llrt->rt_refcnt--;
|
||||
else return 0;
|
||||
|
||||
linkp = ((struct npaidbentry *)llrt->rt_llinfo)->np_link;
|
||||
}
|
||||
|
||||
switch (prc) {
|
||||
case PRC_IFUP:
|
||||
(void) llc_setsapinfo(ifp, addr->sa_family, sap, config);
|
||||
return 0;
|
||||
|
||||
case PRC_IFDOWN: {
|
||||
register struct llc_linkcb *linkp;
|
||||
register struct llc_linkcb *nlinkp;
|
||||
register int i;
|
||||
|
||||
/*
|
||||
* All links are accessible over the doubly linked list llccb_q
|
||||
*/
|
||||
if (!LQEMPTY) {
|
||||
/*
|
||||
* A for-loop is not that great an idea as the linkp
|
||||
* will get deleted by llc_timer()
|
||||
*/
|
||||
linkp = LQFIRST;
|
||||
while (LQVALID(linkp)) {
|
||||
nlinkp = LQNEXT(linkp);
|
||||
if (linkp->llcl_if = ifp) {
|
||||
i = splimp();
|
||||
(void)llc_statehandler(linkp, (struct llc *)0,
|
||||
NL_DISCONNECT_REQUEST,
|
||||
0, 1);
|
||||
splx(i);
|
||||
}
|
||||
linkp = nlinkp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case PRC_CONNECT_REQUEST:
|
||||
if (linkp == 0) {
|
||||
if ((linkp = llc_newlink((struct sockaddr_dl *) nlrt->rt_gateway,
|
||||
nlrt->rt_ifp, nlrt,
|
||||
pcb, llrt)) == 0)
|
||||
return (0);
|
||||
((struct npaidbentry *)llrt->rt_llinfo)->np_link = linkp;
|
||||
i = splimp();
|
||||
(void)llc_statehandler(linkp, (struct llc *) 0,
|
||||
NL_CONNECT_REQUEST, 0, 1);
|
||||
splx(i);
|
||||
}
|
||||
return ((caddr_t)linkp);
|
||||
|
||||
case PRC_DISCONNECT_REQUEST:
|
||||
if (linkp == 0)
|
||||
panic("no link control block!");
|
||||
|
||||
i = splimp();
|
||||
(void)llc_statehandler(linkp, (struct llc *) 0,
|
||||
NL_DISCONNECT_REQUEST, 0, 1);
|
||||
splx(i);
|
||||
|
||||
/*
|
||||
* The actual removal of the link control block is done by the
|
||||
* cleaning neutrum (i.e. llc_timer()).
|
||||
*/
|
||||
break;
|
||||
|
||||
case PRC_RESET_REQUEST:
|
||||
if (linkp == 0)
|
||||
panic("no link control block!");
|
||||
|
||||
i = splimp();
|
||||
(void)llc_statehandler(linkp, (struct llc *) 0,
|
||||
NL_RESET_REQUEST, 0, 1);
|
||||
splx(i);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,305 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Dirk Husemann, Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Dirk Husemann and the Computer Science Department (IV) of
|
||||
* the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)llc_output.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: llc_output.c,v 1.3 1995/03/19 14:29:00 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_llc.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netccitt/dll.h>
|
||||
#include <netccitt/llc_var.h>
|
||||
|
||||
/*
|
||||
* llc_output() --- called by an upper layer (network layer) entity whenever
|
||||
* there is an INFO frame to be transmitted. We enqueue the
|
||||
* info frame and call llc_start() to do the actual sending.
|
||||
*/
|
||||
|
||||
llc_output(struct llc_linkcb *linkp, struct mbuf *m)
|
||||
{
|
||||
register int i;
|
||||
|
||||
i = splimp();
|
||||
LLC_ENQUEUE(linkp, m);
|
||||
llc_start(linkp);
|
||||
splx(i);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* llc_start() --- We try to subsequently dequeue all the frames available and
|
||||
* send them out.
|
||||
*/
|
||||
void
|
||||
llc_start(struct llc_linkcb *linkp)
|
||||
{
|
||||
register int i;
|
||||
register struct mbuf *m;
|
||||
int action;
|
||||
|
||||
while ((LLC_STATEEQ(linkp, NORMAL) || LLC_STATEEQ(linkp, BUSY) ||
|
||||
LLC_STATEEQ(linkp, REJECT)) &&
|
||||
(linkp->llcl_slotsfree > 0) &&
|
||||
(LLC_GETFLAG(linkp, REMOTE_BUSY) == 0)) {
|
||||
LLC_DEQUEUE(linkp, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
LLC_SETFRAME(linkp, m);
|
||||
(void)llc_statehandler(linkp, (struct llc *) 0, NL_DATA_REQUEST,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* llc_send() --- Handles single frames. If dealing with INFO frames we need to
|
||||
* prepend the LLC header, otherwise we just allocate an mbuf.
|
||||
* In both cases the actual send is done by llc_rawsend().
|
||||
*/
|
||||
llc_send(struct llc_linkcb *linkp, int frame_kind, int cmdrsp, int pollfinal)
|
||||
{
|
||||
register struct mbuf *m = (struct mbuf *)0;
|
||||
register struct llc *frame;
|
||||
|
||||
if (frame_kind == LLCFT_INFO)
|
||||
m = linkp->llcl_output_buffers[llc_seq2slot(linkp,
|
||||
linkp->llcl_vs)];
|
||||
LLC_GETHDR(frame, m);
|
||||
|
||||
/* pass it on to llc_rawsend() */
|
||||
llc_rawsend(linkp, m, frame, frame_kind, linkp->llcl_vs, cmdrsp, pollfinal);
|
||||
|
||||
if (frame_kind == LLCFT_INFO)
|
||||
LLC_INC(linkp->llcl_vs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* llc_resend() --- llc_resend() retransmits all unacknowledged INFO frames.
|
||||
*/
|
||||
llc_resend(struct llc_linkcb *linkp, int cmdrsp, int pollfinal)
|
||||
{
|
||||
register struct llc *frame;
|
||||
register struct mbuf *m;
|
||||
register int seq, slot;
|
||||
|
||||
if (linkp->llcl_slotsfree < linkp->llcl_window)
|
||||
/* assert lock between nr_received & V(S) */
|
||||
if (linkp->llcl_nr_received != linkp->llcl_vs)
|
||||
panic("llc: V(S) != N(R) received");
|
||||
|
||||
for (slot = llc_seq2slot(linkp, linkp->llcl_vs);
|
||||
slot != linkp->llcl_freeslot;
|
||||
LLC_INC(linkp->llcl_vs),
|
||||
slot = llc_seq2slot(linkp, linkp->llcl_vs)) {
|
||||
m = linkp->llcl_output_buffers[slot];
|
||||
LLC_GETHDR(frame, m);
|
||||
llc_rawsend(linkp, m, frame, LLCFT_INFO, linkp->llcl_vs,
|
||||
cmdrsp, pollfinal);
|
||||
pollfinal = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* llc_rawsend() --- constructs an LLC frame and sends it out via the
|
||||
* associated interface of the link control block.
|
||||
*
|
||||
* We need to make sure that outgoing frames have the correct length,
|
||||
* in particular the 4 byte ones (RR, RNR, REJ) as LLC_GETHDR() will
|
||||
* set the mbuf len to 3 as default len for non INFO frames ...
|
||||
*
|
||||
* Frame kind Length (w/o MAC header, {D,S}SAP incl.)
|
||||
* --------------------------------------------------------------
|
||||
* DISC, SABME, UA, DM 3 bytes ({D,S}SAP + CONTROL)
|
||||
* RR, RNR, REJ 4 bytes ({D,S}SAP + CONTROL0 + CONTROL1)
|
||||
* XID 6 bytes ({D,S}SAP + CONTROL0 + FI,CLASS,WINDOW)
|
||||
* FRMR 7 bytes ({D,S}SAP + CONTROL0 + REJ CONTROL,V(S),V(R),CAUSE)
|
||||
* INFO 4 -- MTU
|
||||
* UI, TEST 3 -- MTU
|
||||
*
|
||||
*/
|
||||
#define LLC_SETLEN(m, l) (m)->m_pkthdr.len = (m)->m_len = (l)
|
||||
|
||||
llc_rawsend(struct llc_linkcb *linkp, struct mbuf *m, struct llc *frame,
|
||||
int frame_kind, int vs, int cmdrsp, int pollfinal)
|
||||
{
|
||||
register short adjust = LLC_UFRAMELEN;
|
||||
struct ifnet *ifp;
|
||||
|
||||
switch (frame_kind) {
|
||||
/* supervisory and information frames */
|
||||
case LLCFT_INFO:
|
||||
frame->llc_control = LLC_INFO;
|
||||
LLCSBITS(frame->llc_control, i_ns, vs);
|
||||
LLCSBITS(frame->llc_control_ext, i_nr, linkp->llcl_vr);
|
||||
adjust = LLC_ISFRAMELEN;
|
||||
break;
|
||||
case LLCFT_RR:
|
||||
frame->llc_control = LLC_RR;
|
||||
LLC_SETLEN(m, LLC_ISFRAMELEN);
|
||||
LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
|
||||
adjust = LLC_ISFRAMELEN;
|
||||
break;
|
||||
case LLCFT_RNR:
|
||||
frame->llc_control = LLC_RNR;
|
||||
LLC_SETLEN(m, LLC_ISFRAMELEN);
|
||||
LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
|
||||
adjust = LLC_ISFRAMELEN;
|
||||
break;
|
||||
case LLCFT_REJ:
|
||||
frame->llc_control = LLC_REJ;
|
||||
LLC_SETLEN(m, LLC_ISFRAMELEN);
|
||||
LLCSBITS(frame->llc_control_ext, s_nr, linkp->llcl_vr);
|
||||
adjust = LLC_ISFRAMELEN;
|
||||
break;
|
||||
/* unnumbered frames */
|
||||
case LLCFT_DM:
|
||||
frame->llc_control = LLC_DM;
|
||||
break;
|
||||
case LLCFT_SABME:
|
||||
frame->llc_control = LLC_SABME;
|
||||
break;
|
||||
case LLCFT_DISC:
|
||||
frame->llc_control = LLC_DISC;
|
||||
break;
|
||||
case LLCFT_UA:
|
||||
frame->llc_control = LLC_UA;
|
||||
break;
|
||||
case LLCFT_UI:
|
||||
frame->llc_control = LLC_UI;
|
||||
break;
|
||||
case LLCFT_FRMR:
|
||||
frame->llc_control = LLC_FRMR;
|
||||
/* get more space --- FRMR frame are longer then usual */
|
||||
LLC_SETLEN(m, LLC_FRMRLEN);
|
||||
bcopy((caddr_t) &linkp->llcl_frmrinfo,
|
||||
(caddr_t) &frame->llc_frmrinfo,
|
||||
sizeof(struct frmrinfo));
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* We don't send {XID, TEST} frames
|
||||
*/
|
||||
if (m)
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in DSAP/SSAP
|
||||
*/
|
||||
frame->llc_dsap = frame->llc_ssap = LLSAPADDR(&linkp->llcl_addr);
|
||||
frame->llc_ssap |= cmdrsp;
|
||||
|
||||
/*
|
||||
* Check for delayed action pending. ISO 8802-2, 7.9.2 (5)
|
||||
* and ISO 8802-2, 7.9.2.3 (32), (34), (36) pertain to this
|
||||
* piece of code --- hopefully we got it right here (i.e.
|
||||
* in the spirit of (32), (34), and (36) ...
|
||||
*/
|
||||
switch (frame_kind) {
|
||||
case LLCFT_RR:
|
||||
case LLCFT_RNR:
|
||||
case LLCFT_REJ:
|
||||
case LLCFT_INFO:
|
||||
switch (LLC_GETFLAG(linkp, DACTION)) {
|
||||
case LLC_DACKCMD:
|
||||
case LLC_DACKRSP:
|
||||
LLC_STOPTIMER(linkp, DACTION);
|
||||
break;
|
||||
case LLC_DACKCMDPOLL:
|
||||
if (cmdrsp == LLC_CMD) {
|
||||
pollfinal = 1;
|
||||
LLC_STOPTIMER(linkp, DACTION);
|
||||
}
|
||||
break;
|
||||
case LLC_DACKRSPFINAL:
|
||||
if (cmdrsp == LLC_RSP) {
|
||||
pollfinal = 1;
|
||||
LLC_STOPTIMER(linkp, DACTION);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (adjust == LLC_UFRAMELEN)
|
||||
LLCSBITS(frame->llc_control, u_pf, pollfinal);
|
||||
else LLCSBITS(frame->llc_control_ext, s_pf, pollfinal);
|
||||
|
||||
/*
|
||||
* Get interface to send frame onto
|
||||
*/
|
||||
ifp = linkp->llcl_if;
|
||||
if (frame_kind == LLCFT_INFO) {
|
||||
/*
|
||||
* send out a copy of the frame, retain the
|
||||
* original
|
||||
*/
|
||||
(*ifp->if_output)(ifp, m_copy(m, 0, (int)M_COPYALL),
|
||||
rt_key(linkp->llcl_nlrt),
|
||||
linkp->llcl_nlrt);
|
||||
/*
|
||||
* Account for the LLC header and let it ``disappear''
|
||||
* as the raw info frame payload is what we hold in
|
||||
* the output_buffers of the link.
|
||||
*/
|
||||
m_adj(m, LLC_ISFRAMELEN);
|
||||
} else (*ifp->if_output)(ifp, m,
|
||||
rt_key(linkp->llcl_nlrt),
|
||||
linkp->llcl_nlrt);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Dirk Husemann, Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Dirk Husemann and the Computer Science Department (IV) of
|
||||
* the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)llc_timer.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: llc_timer.c,v 1.2 1994/08/02 07:47:23 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_llc.h>
|
||||
|
||||
#include <netccitt/dll.h>
|
||||
#include <netccitt/llc_var.h>
|
||||
|
||||
|
||||
/*
|
||||
* Various timer values. They can be adjusted
|
||||
* by patching the binary with adb if necessary.
|
||||
*/
|
||||
/* ISO 8802-2 timers */
|
||||
int llc_n2 = LLC_N2_VALUE;
|
||||
int llc_ACK_timer = LLC_ACK_TIMER;
|
||||
int llc_P_timer = LLC_P_TIMER;
|
||||
int llc_BUSY_timer = LLC_BUSY_TIMER;
|
||||
int llc_REJ_timer = LLC_REJ_TIMER;
|
||||
/* Implementation specific timers */
|
||||
int llc_AGE_timer = LLC_AGE_TIMER;
|
||||
int llc_DACTION_timer = LLC_DACTION_TIMER;
|
||||
|
||||
/*
|
||||
* The timer routine. We are called every 500ms by the kernel.
|
||||
* Handle the various virtual timers.
|
||||
*/
|
||||
|
||||
void
|
||||
llc_timer()
|
||||
{
|
||||
register struct llc_linkcb *linkp;
|
||||
register struct llc_linkcb *nlinkp;
|
||||
register int timer;
|
||||
register int action;
|
||||
register int s = splimp();
|
||||
|
||||
/*
|
||||
* All links are accessible over the doubly linked list llccb_q
|
||||
*/
|
||||
if (!LQEMPTY) {
|
||||
/*
|
||||
* A for-loop is not that great an idea as the linkp
|
||||
* might get deleted if the age timer has expired ...
|
||||
*/
|
||||
linkp = LQFIRST;
|
||||
while (LQVALID(linkp)) {
|
||||
nlinkp = LQNEXT(linkp);
|
||||
/*
|
||||
* Check implementation specific timers first
|
||||
*/
|
||||
/* The delayed action/acknowledge idle timer */
|
||||
switch (LLC_TIMERXPIRED(linkp, DACTION)) {
|
||||
case LLC_TIMER_RUNNING:
|
||||
LLC_AGETIMER(linkp, DACTION);
|
||||
break;
|
||||
case LLC_TIMER_EXPIRED: {
|
||||
register int cmdrsp;
|
||||
register int pollfinal;
|
||||
|
||||
switch (LLC_GETFLAG(linkp, DACTION)) {
|
||||
case LLC_DACKCMD:
|
||||
cmdrsp = LLC_CMD, pollfinal = 0;
|
||||
break;
|
||||
case LLC_DACKCMDPOLL:
|
||||
cmdrsp = LLC_CMD, pollfinal = 1;
|
||||
break;
|
||||
case LLC_DACKRSP:
|
||||
cmdrsp = LLC_RSP, pollfinal = 0;
|
||||
break;
|
||||
case LLC_DACKRSPFINAL:
|
||||
cmdrsp = LLC_RSP, pollfinal = 1;
|
||||
break;
|
||||
}
|
||||
llc_send(linkp, LLCFT_RR, cmdrsp, pollfinal);
|
||||
LLC_STOPTIMER(linkp, DACTION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* The link idle timer */
|
||||
switch (LLC_TIMERXPIRED(linkp, AGE)) {
|
||||
case LLC_TIMER_RUNNING:
|
||||
LLC_AGETIMER(linkp, AGE);
|
||||
break;
|
||||
case LLC_TIMER_EXPIRED:
|
||||
/*
|
||||
* Only crunch the link when really no
|
||||
* timers are running any more.
|
||||
*/
|
||||
if (llc_anytimersup(linkp) == 0) {
|
||||
llc_dellink(linkp);
|
||||
LLC_STOPTIMER(linkp, AGE);
|
||||
goto gone;
|
||||
} else {
|
||||
LLC_STARTTIMER(linkp, AGE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Now, check all the ISO 8802-2 timers
|
||||
*/
|
||||
FOR_ALL_LLC_TIMERS(timer) {
|
||||
action = 0;
|
||||
if ((linkp->llcl_timerflags & (1<<timer)) &&
|
||||
(linkp->llcl_timers[timer] == 0)) {
|
||||
switch (timer) {
|
||||
case LLC_ACK_SHIFT:
|
||||
action = LLC_ACK_TIMER_EXPIRED;
|
||||
break;
|
||||
case LLC_P_SHIFT:
|
||||
action = LLC_P_TIMER_EXPIRED;
|
||||
break;
|
||||
case LLC_BUSY_SHIFT:
|
||||
action = LLC_BUSY_TIMER_EXPIRED;
|
||||
break;
|
||||
case LLC_REJ_SHIFT:
|
||||
action = LLC_REJ_TIMER_EXPIRED;
|
||||
break;
|
||||
}
|
||||
linkp->llcl_timerflags &= ~(1<<timer);
|
||||
(void)llc_statehandler(linkp, (struct llc *)0, action, 0, 1);
|
||||
} else if (linkp->llcl_timers[timer] > 0)
|
||||
linkp->llcl_timers[timer]--;
|
||||
}
|
||||
|
||||
gone: linkp = nlinkp;
|
||||
}
|
||||
}
|
||||
splx (s);
|
||||
}
|
@ -1,640 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Dirk Husemann, Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Dirk Husemann and the Computer Science Department (IV) of
|
||||
* the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)llc_var.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: llc_var.h,v 1.5 1995/07/29 11:41:24 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_LLC_VAR_H_
|
||||
#define _NETCCITT_LLC_VAR_H_
|
||||
|
||||
#ifdef __STDC__
|
||||
/*
|
||||
* Forward structure declarations for function prototypes [sic].
|
||||
*/
|
||||
struct llc;
|
||||
#endif
|
||||
|
||||
#define NPAIDB_LINK 0
|
||||
|
||||
struct npaidbentry {
|
||||
union {
|
||||
/* MAC,DLSAP -> CONS */
|
||||
struct {
|
||||
struct llc_linkcb *NE_link;
|
||||
struct rtentry *NE_rt;
|
||||
} NE;
|
||||
/* SAP info for unconfigured incoming calls */
|
||||
struct {
|
||||
u_short SI_class;
|
||||
#define LLC_CLASS_I 0x1
|
||||
#define LLC_CLASS_II 0x3
|
||||
#define LLC_CLASS_III 0x4 /* Future */
|
||||
#define LLC_CLASS_IV 0x7 /* Future */
|
||||
u_short SI_window;
|
||||
u_short SI_trace;
|
||||
u_short SI_xchxid;
|
||||
void (*SI_input)
|
||||
__P((struct mbuf *));
|
||||
caddr_t (*SI_ctlinput)
|
||||
__P((int, struct sockaddr *, caddr_t));
|
||||
} SI;
|
||||
} NESIun;
|
||||
};
|
||||
#define np_link NESIun.NE.NE_link
|
||||
#define np_rt NESIun.NE.NE_rt
|
||||
#define si_class NESIun.SI.SI_class
|
||||
#define si_window NESIun.SI.SI_window
|
||||
#define si_trace NESIun.SI.SI_trace
|
||||
#define si_xchxid NESIun.SI.SI_xchxid
|
||||
#define si_input NESIun.SI.SI_input
|
||||
#define si_ctlinput NESIun.SI.SI_ctlinput
|
||||
|
||||
#define NPDL_SAPNETMASK 0x7e
|
||||
|
||||
/*
|
||||
* Definitions for accessing bitfields/bitslices inside
|
||||
* LLC2 headers
|
||||
*/
|
||||
struct bitslice {
|
||||
unsigned int bs_mask;
|
||||
unsigned int bs_shift;
|
||||
};
|
||||
|
||||
|
||||
#define i_z 0
|
||||
#define i_ns 1
|
||||
#define i_pf 0
|
||||
#define i_nr 1
|
||||
#define s_oz 2
|
||||
#define s_selector 3
|
||||
#define s_pf 0
|
||||
#define s_nr 1
|
||||
#define u_bb 2
|
||||
#define u_select_other 3
|
||||
#define u_pf 4
|
||||
#define u_select 5
|
||||
#define f_vs 1
|
||||
#define f_cr 0
|
||||
#define f_vr 1
|
||||
#define f_wxyzv 6
|
||||
|
||||
#define LLCGBITS(Arg, Index) (((Arg) & llc_bitslice[(Index)].bs_mask) >> llc_bitslice[(Index)].bs_shift)
|
||||
#define LLCSBITS(Arg, Index, Val) (Arg) |= (((Val) << llc_bitslice[(Index)].bs_shift) & llc_bitslice[(Index)].bs_mask)
|
||||
#define LLCCSBITS(Arg, Index, Val) (Arg) = (((Val) << llc_bitslice[(Index)].bs_shift) & llc_bitslice[(Index)].bs_mask)
|
||||
|
||||
extern struct bitslice llc_bitslice[];
|
||||
|
||||
#define LLC_CMD 0
|
||||
#define LLC_RSP 1
|
||||
#define LLC_MAXCMDRSP 2
|
||||
|
||||
/*
|
||||
* LLC events --- These events may either be frames received from the
|
||||
* remote LLC DSAP, request from the network layer user,
|
||||
* timer events from llc_timer(), or diagnostic events from
|
||||
* llc_input().
|
||||
*/
|
||||
|
||||
/* LLC frame types */
|
||||
#define LLCFT_INFO 0 * LLC_MAXCMDRSP
|
||||
#define LLCFT_RR 1 * LLC_MAXCMDRSP
|
||||
#define LLCFT_RNR 2 * LLC_MAXCMDRSP
|
||||
#define LLCFT_REJ 3 * LLC_MAXCMDRSP
|
||||
#define LLCFT_DM 4 * LLC_MAXCMDRSP
|
||||
#define LLCFT_SABME 5 * LLC_MAXCMDRSP
|
||||
#define LLCFT_DISC 6 * LLC_MAXCMDRSP
|
||||
#define LLCFT_UA 7 * LLC_MAXCMDRSP
|
||||
#define LLCFT_FRMR 8 * LLC_MAXCMDRSP
|
||||
#define LLCFT_UI 9 * LLC_MAXCMDRSP
|
||||
#define LLCFT_XID 10 * LLC_MAXCMDRSP
|
||||
#define LLCFT_TEST 11 * LLC_MAXCMDRSP
|
||||
|
||||
/* LLC2 timer events */
|
||||
#define LLC_ACK_TIMER_EXPIRED 12 * LLC_MAXCMDRSP
|
||||
#define LLC_P_TIMER_EXPIRED 13 * LLC_MAXCMDRSP
|
||||
#define LLC_REJ_TIMER_EXPIRED 14 * LLC_MAXCMDRSP
|
||||
#define LLC_BUSY_TIMER_EXPIRED 15 * LLC_MAXCMDRSP
|
||||
|
||||
/* LLC2 diagnostic events */
|
||||
#define LLC_INVALID_NR 16 * LLC_MAXCMDRSP
|
||||
#define LLC_INVALID_NS 17 * LLC_MAXCMDRSP
|
||||
#define LLC_BAD_PDU 18 * LLC_MAXCMDRSP
|
||||
#define LLC_LOCAL_BUSY_DETECTED 19 * LLC_MAXCMDRSP
|
||||
#define LLC_LOCAL_BUSY_CLEARED 20 * LLC_MAXCMDRSP
|
||||
|
||||
/* Network layer user requests */
|
||||
/*
|
||||
* NL_CONNECT_REQUEST --- The user has requested that a data link connection
|
||||
* be established with a remote LLC DSAP.
|
||||
*/
|
||||
#define NL_CONNECT_REQUEST 21 * LLC_MAXCMDRSP
|
||||
/*
|
||||
* NL_CONNECT_RESPONSE --- The user has accepted the data link connection.
|
||||
*/
|
||||
#define NL_CONNECT_RESPONSE 22 * LLC_MAXCMDRSP
|
||||
/*
|
||||
* NL_RESET_REQUEST --- The user has requested that the data link with the
|
||||
* remote LLC DSAP be reset.
|
||||
*/
|
||||
#define NL_RESET_REQUEST 23 * LLC_MAXCMDRSP
|
||||
/*
|
||||
* NL_RESET_RESPONSE --- The user has accepted the reset of the data link
|
||||
* connection.
|
||||
*/
|
||||
#define NL_RESET_RESPONSE 24 * LLC_MAXCMDRSP
|
||||
/*
|
||||
* NL_DISCONNECT_REQUEST --- The user has requested that the data link
|
||||
* connection with remote LLC DSAP be terminated.
|
||||
*/
|
||||
#define NL_DISCONNECT_REQUEST 25 * LLC_MAXCMDRSP
|
||||
/*
|
||||
* NL_DATA_REQUEST --- The user has requested that a data unit be sent ot the
|
||||
* remote LLC DSAP.
|
||||
*/
|
||||
#define NL_DATA_REQUEST 26 * LLC_MAXCMDRSP
|
||||
/*
|
||||
* NL_INITIATE_PF_CYCLE --- The local LLC wants to initiate a P/F cycle.
|
||||
*/
|
||||
#define NL_INITIATE_PF_CYCLE 27 * LLC_MAXCMDRSP
|
||||
/*
|
||||
* NL_LOCAL_BUSY_DETECTED --- The local entity has encountered a busy condition
|
||||
*/
|
||||
#define NL_LOCAL_BUSY_DETECTED 28 * LLC_MAXCMDRSP
|
||||
|
||||
#define LLCFT_NONE 255
|
||||
|
||||
/* return message from state handlers */
|
||||
|
||||
/*
|
||||
* LLC_CONNECT_INDICATION --- Inform the user that a connection has been
|
||||
* requested by a remote LLC SSAP.
|
||||
*/
|
||||
#define LLC_CONNECT_INDICATION 1
|
||||
/*
|
||||
* LLC_CONNECT_CONFIRM --- The connection service component indicates that the
|
||||
* remote network entity has accepted the connection.
|
||||
*/
|
||||
#define LLC_CONNECT_CONFIRM 2
|
||||
/*
|
||||
* LLC_DISCONNECT_INDICATION --- Inform the user that the remote network
|
||||
* entity has intiated disconnection of the data
|
||||
* link connection.
|
||||
*/
|
||||
#define LLC_DISCONNECT_INDICATION 3
|
||||
/*
|
||||
* LLC_RESET_CONFIRM --- The connection service component indicates that the
|
||||
* remote network entity has accepted the reset.
|
||||
*/
|
||||
#define LLC_RESET_CONFIRM 4
|
||||
/*
|
||||
* LLC_RESET_INDICATION_REMOTE --- The remote network entity or remote peer
|
||||
* has initiated a reset of the data link
|
||||
* connection.
|
||||
*/
|
||||
#define LLC_RESET_INDICATION_REMOTE 5
|
||||
/*
|
||||
* LLC_RESET_INDICATION_LOCAL --- The local LLC has determined that the data
|
||||
* link connection is in need of
|
||||
* reinitialization.
|
||||
*/
|
||||
#define LLC_RESET_INDICATION_LOCAL 6
|
||||
/*
|
||||
* LLC_FRMR_RECEIVED --- The local connection service component has received a
|
||||
* FRMR response PDU.
|
||||
*/
|
||||
#define LLC_FRMR_RECEIVED 7
|
||||
/*
|
||||
* LLC_FRMR_SENT --- The local connection component has received an ivalid
|
||||
* PDU, and has sent a FRMR response PDU.
|
||||
*/
|
||||
#define LLC_FRMR_SENT 8
|
||||
/*
|
||||
* LLC_DATA_INDICATION --- The connection service component passes the data
|
||||
* unit from the received I PDU to the user.
|
||||
*/
|
||||
#define LLC_DATA_INDICATION 9
|
||||
/*
|
||||
* LLC_REMOTE_NOT_BUSY --- The remote LLC DSAP is no longer busy. The local
|
||||
* connection service component will now accept a
|
||||
* DATA_REQUEST.
|
||||
*/
|
||||
#define LLC_REMOTE_NOT_BUSY 10
|
||||
/*
|
||||
* LLC_REMOTE_BUSY --- The remote LLC DSAP is busy. The local connection
|
||||
* service component will not accept a DATA_REQUEST.
|
||||
*/
|
||||
#define LLC_REMOTE_BUSY 11
|
||||
|
||||
/* Internal return code */
|
||||
#define LLC_PASSITON 255
|
||||
|
||||
#define INFORMATION_CONTROL 0x00
|
||||
#define SUPERVISORY_CONTROL 0x02
|
||||
#define UNUMBERED_CONTROL 0x03
|
||||
|
||||
/*
|
||||
* Other necessary definitions
|
||||
*/
|
||||
|
||||
#define LLC_MAX_SEQUENCE 128
|
||||
#define LLC_MAX_WINDOW 127
|
||||
#define LLC_WINDOW_SIZE 7
|
||||
|
||||
/*
|
||||
* Don't we love this one? CCITT likes to suck on bits 8=)
|
||||
*/
|
||||
#define NLHDRSIZEGUESS 3
|
||||
|
||||
/*
|
||||
* LLC control block
|
||||
*/
|
||||
|
||||
struct llc_linkcb {
|
||||
struct llccb_q {
|
||||
struct llccb_q *q_forw; /* admin chain */
|
||||
struct llccb_q *q_backw;
|
||||
} llcl_q;
|
||||
struct npaidbentry *llcl_sapinfo; /* SAP information */
|
||||
struct sockaddr_dl llcl_addr; /* link snpa address */
|
||||
struct rtentry *llcl_nlrt; /* layer 3 -> LLC */
|
||||
struct rtentry *llcl_llrt; /* LLC -> layer 3 */
|
||||
struct ifnet *llcl_if; /* our interface */
|
||||
caddr_t llcl_nlnext; /* cb for network layer */
|
||||
struct mbuf *llcl_writeqh; /* Write queue head */
|
||||
struct mbuf *llcl_writeqt; /* Write queue tail */
|
||||
struct mbuf **llcl_output_buffers;
|
||||
short llcl_timers[6]; /* timer array */
|
||||
long llcl_timerflags; /* flags signalling running timers */
|
||||
int (*llcl_statehandler)
|
||||
__P((struct llc_linkcb *, struct llc *, int, int, int));
|
||||
int llcl_P_flag;
|
||||
int llcl_F_flag;
|
||||
int llcl_S_flag;
|
||||
int llcl_DATA_flag;
|
||||
int llcl_REMOTE_BUSY_flag;
|
||||
int llcl_DACTION_flag; /* delayed action */
|
||||
int llcl_retry;
|
||||
/*
|
||||
* The following components deal --- in one way or the other ---
|
||||
* with the LLC2 window. Indicated by either [L] or [W] is the
|
||||
* domain of the specific component:
|
||||
*
|
||||
* [L] The domain is 0--LLC_MAX_WINDOW
|
||||
* [W] The domain is 0--llcl_window
|
||||
*/
|
||||
short llcl_vr; /* next to receive [L] */
|
||||
short llcl_vs; /* next to send [L] */
|
||||
short llcl_nr_received; /* next frame to b ack'd [L] */
|
||||
short llcl_freeslot; /* next free slot [W] */
|
||||
short llcl_projvs; /* V(S) associated with freeslot */
|
||||
short llcl_slotsfree; /* free slots [W] */
|
||||
short llcl_window; /* window size */
|
||||
/*
|
||||
* In llcl_frmrinfo we jot down the last frmr info field, which we
|
||||
* need to do as we need to be able to resend it in the ERROR state.
|
||||
*/
|
||||
struct frmrinfo llcl_frmrinfo; /* last FRMR info field */
|
||||
};
|
||||
#define llcl_frmr_pdu0 llcl_frmrinfo.rej_pdu_0
|
||||
#define llcl_frmr_pdu1 llcl_frmrinfo.rej_pdu_1
|
||||
#define llcl_frmr_control llcl_frmrinfo.frmr_control
|
||||
#define llcl_frmr_control_ext llcl_frmrinfo.frmr_control_ext
|
||||
#define llcl_frmr_cause llcl_frmrinfo.frmr_cause
|
||||
|
||||
#define LQNEXT(l) (struct llc_linkcb *)((l)->llcl_q.q_forw)
|
||||
#define LQEMPTY (llccb_q.q_forw == &llccb_q)
|
||||
#define LQFIRST (struct llc_linkcb *)(llccb_q.q_forw)
|
||||
#define LQVALID(l) (!((struct llccb_q *)(l) == &llccb_q))
|
||||
|
||||
#define LLC_ENQUEUE(l, m) if ((l)->llcl_writeqh == NULL) { \
|
||||
(l)->llcl_writeqh = (m); \
|
||||
(l)->llcl_writeqt = (m); \
|
||||
} else { \
|
||||
(l)->llcl_writeqt->m_nextpkt = (m); \
|
||||
(l)->llcl_writeqt = (m); \
|
||||
}
|
||||
|
||||
#define LLC_DEQUEUE(l, m) if ((l)->llcl_writeqh == NULL) \
|
||||
(m) = NULL; \
|
||||
else { \
|
||||
(m) = (l)->llcl_writeqh; \
|
||||
(l)->llcl_writeqh = (l)->llcl_writeqh->m_nextpkt; \
|
||||
}
|
||||
|
||||
#define LLC_SETFRAME(l, m) { \
|
||||
if ((l)->llcl_slotsfree > 0) { \
|
||||
(l)->llcl_slotsfree--; \
|
||||
(l)->llcl_output_buffers[(l)->llcl_freeslot] = (m); \
|
||||
(l)->llcl_freeslot = ((l)->llcl_freeslot+1) % (l)->llcl_window; \
|
||||
LLC_INC((l)->llcl_projvs); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* handling of sockaddr_dl's
|
||||
*/
|
||||
|
||||
#define LLADDRLEN(s) ((s)->sdl_alen + (s)->sdl_nlen)
|
||||
#define LLSAPADDR(s) ((s)->sdl_data[LLADDRLEN(s)-1] & 0xff)
|
||||
#define LLSAPLOC(s, if) ((s)->sdl_nlen + (if)->if_addrlen)
|
||||
|
||||
struct sdl_hdr {
|
||||
struct sockaddr_dl sdlhdr_dst;
|
||||
struct sockaddr_dl sdlhdr_src;
|
||||
long sdlhdr_len;
|
||||
};
|
||||
|
||||
#define LLC_GETHDR(f,m) { \
|
||||
struct mbuf *_m = (struct mbuf *) (m); \
|
||||
if (_m) { \
|
||||
M_PREPEND(_m, LLC_ISFRAMELEN, M_DONTWAIT); \
|
||||
bzero(mtod(_m, caddr_t), LLC_ISFRAMELEN); \
|
||||
} else { \
|
||||
MGETHDR (_m, M_DONTWAIT, MT_HEADER); \
|
||||
if (_m != NULL) { \
|
||||
_m->m_pkthdr.len = _m->m_len = LLC_UFRAMELEN; \
|
||||
_m->m_next = _m->m_act = NULL; \
|
||||
bzero(mtod(_m, caddr_t), LLC_UFRAMELEN); \
|
||||
} else return; \
|
||||
} \
|
||||
(m) = _m; \
|
||||
(f) = mtod(m, struct llc *); \
|
||||
}
|
||||
|
||||
#define LLC_NEWSTATE(l, LLCstate) (l)->llcl_statehandler = llc_state_##LLCstate
|
||||
#define LLC_STATEEQ(l, LLCstate) ((l)->llcl_statehandler == llc_state_##LLCstate ? 1 : 0)
|
||||
|
||||
#define LLC_ACK_SHIFT 0
|
||||
#define LLC_P_SHIFT 1
|
||||
#define LLC_BUSY_SHIFT 2
|
||||
#define LLC_REJ_SHIFT 3
|
||||
#define LLC_AGE_SHIFT 4
|
||||
#define LLC_DACTION_SHIFT 5
|
||||
|
||||
#define LLC_TIMER_NOTRUNNING 0
|
||||
#define LLC_TIMER_RUNNING 1
|
||||
#define LLC_TIMER_EXPIRED 2
|
||||
|
||||
#define LLC_STARTTIMER(l, LLCtimer) { \
|
||||
(l)->llcl_timers[LLC_##LLCtimer##_SHIFT] = llc_##LLCtimer##_timer; \
|
||||
(l)->llcl_timerflags |= (1<<LLC_##LLCtimer##_SHIFT); \
|
||||
}
|
||||
#define LLC_STOPTIMER(l, LLCtimer) { \
|
||||
(l)->llcl_timers[LLC_##LLCtimer##_SHIFT] = 0; \
|
||||
(l)->llcl_timerflags &= ~(1<<LLC_##LLCtimer##_SHIFT); \
|
||||
}
|
||||
#define LLC_AGETIMER(l, LLCtimer) if ((l)->llcl_timers[LLC_##LLCtimer##_SHIFT] > 0) \
|
||||
(l)->llcl_timers[LLC_##LLCtimer##_SHIFT]--;
|
||||
|
||||
#define LLC_TIMERXPIRED(l, LLCtimer) \
|
||||
(((l)->llcl_timerflags & (1<<LLC_##LLCtimer##_SHIFT)) ? \
|
||||
(((l)->llcl_timers[LLC_##LLCtimer##_SHIFT] == 0 ) ? \
|
||||
LLC_TIMER_EXPIRED : LLC_TIMER_RUNNING) : LLC_TIMER_NOTRUNNING)
|
||||
|
||||
#define FOR_ALL_LLC_TIMERS(t) for ((t) = LLC_ACK_SHIFT; (t) < LLC_AGE_SHIFT; (t)++)
|
||||
|
||||
#define LLC_SETFLAG(l, LLCflag, v) (l)->llcl_##LLCflag##_flag = (v)
|
||||
#define LLC_GETFLAG(l, LLCflag) (l)->llcl_##LLCflag##_flag
|
||||
|
||||
#define LLC_RESETCOUNTER(l) { \
|
||||
(l)->llcl_vs = (l)->llcl_vr = (l)->llcl_retry = 0; \
|
||||
llc_resetwindow((l)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* LLC2 macro definitions
|
||||
*/
|
||||
|
||||
|
||||
#define LLC_START_ACK_TIMER(l) LLC_STARTTIMER((l), ACK)
|
||||
#define LLC_STOP_ACK_TIMER(l) LLC_STOPTIMER((l), ACK)
|
||||
#define LLC_START_REJ_TIMER(l) LLC_STARTTIMER((l), REJ)
|
||||
#define LLC_STOP_REJ_TIMER(l) LLC_STOPTIMER((l), REJ)
|
||||
#define LLC_START_P_TIMER(l) { \
|
||||
LLC_STARTTIMER((l), P); \
|
||||
if (LLC_GETFLAG((l), P) == 0) \
|
||||
(l)->llcl_retry = 0; \
|
||||
LLC_SETFLAG((l), P, 1); \
|
||||
}
|
||||
#define LLC_STOP_P_TIMER(l) { \
|
||||
LLC_STOPTIMER((l), P); \
|
||||
LLC_SETFLAG((l), P, 0); \
|
||||
}
|
||||
#define LLC_STOP_ALL_TIMERS(l) { \
|
||||
LLC_STOPTIMER((l), ACK); \
|
||||
LLC_STOPTIMER((l), REJ); \
|
||||
LLC_STOPTIMER((l), BUSY); \
|
||||
LLC_STOPTIMER((l), P); \
|
||||
}
|
||||
|
||||
|
||||
#define LLC_INC(i) (i) = ((i)+1) % LLC_MAX_SEQUENCE
|
||||
|
||||
#define LLC_NR_VALID(l, nr) ((l)->llcl_vs < (l)->llcl_nr_received ? \
|
||||
(((nr) >= (l)->llcl_nr_received) || \
|
||||
((nr) <= (l)->llcl_vs) ? 1 : 0) : \
|
||||
(((nr) <= (l)->llcl_vs) && \
|
||||
((nr) >= (l)->llcl_nr_received) ? 1 : 0))
|
||||
|
||||
#define LLC_UPDATE_P_FLAG(l, cr, pf) { \
|
||||
if ((cr) == LLC_RSP && (pf) == 1) { \
|
||||
LLC_SETFLAG((l), P, 0); \
|
||||
LLC_STOPTIMER((l), P); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LLC_UPDATE_NR_RECEIVED(l, nr) { \
|
||||
while ((l)->llcl_nr_received != (nr)) { \
|
||||
struct mbuf *_m; \
|
||||
register short seq; \
|
||||
if (_m = (l)->llcl_output_buffers[seq = llc_seq2slot((l), (l)->llcl_nr_received)]) \
|
||||
m_freem(_m); \
|
||||
(l)->llcl_output_buffers[seq] = NULL; \
|
||||
LLC_INC((l)->llcl_nr_received); \
|
||||
(l)->llcl_slotsfree++; \
|
||||
} \
|
||||
(l)->llcl_retry = 0; \
|
||||
if ((l)->llcl_slotsfree < (l)->llcl_window) { \
|
||||
LLC_START_ACK_TIMER(l); \
|
||||
} else LLC_STOP_ACK_TIMER(l); \
|
||||
LLC_STARTTIMER((l), DACTION); \
|
||||
}
|
||||
|
||||
#define LLC_SET_REMOTE_BUSY(l,a) { \
|
||||
if (LLC_GETFLAG((l), REMOTE_BUSY) == 0) { \
|
||||
LLC_SETFLAG((l), REMOTE_BUSY, 1); \
|
||||
LLC_STARTTIMER((l), BUSY); \
|
||||
(a) = LLC_REMOTE_BUSY; \
|
||||
} else { \
|
||||
(a) = 0; \
|
||||
} \
|
||||
}
|
||||
#define LLC_CLEAR_REMOTE_BUSY(l,a) { \
|
||||
if (LLC_GETFLAG((l), REMOTE_BUSY) == 1) { \
|
||||
LLC_SETFLAG((l), REMOTE_BUSY, 1); \
|
||||
LLC_STOPTIMER((l), BUSY); \
|
||||
if (LLC_STATEEQ((l), NORMAL) || \
|
||||
LLC_STATEEQ((l), REJECT) || \
|
||||
LLC_STATEEQ((l), BUSY)) \
|
||||
llc_resend((l), LLC_CMD, 0); \
|
||||
(a) = LLC_REMOTE_NOT_BUSY; \
|
||||
} else { \
|
||||
(a) = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LLC_DACKCMD 0x1
|
||||
#define LLC_DACKCMDPOLL 0x2
|
||||
#define LLC_DACKRSP 0x3
|
||||
#define LLC_DACKRSPFINAL 0x4
|
||||
|
||||
#define LLC_SENDACKNOWLEDGE(l, cmd, pf) { \
|
||||
if ((cmd) == LLC_CMD) { \
|
||||
LLC_SETFLAG((l), DACTION, ((pf) == 0 ? LLC_DACKCMD : LLC_DACKCMDPOLL)); \
|
||||
} else { \
|
||||
LLC_SETFLAG((l), DACTION, ((pf) == 0 ? LLC_DACKRSP : LLC_DACKRSPFINAL)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LLC_FRMR_W (1<<0)
|
||||
#define LLC_FRMR_X (1<<1)
|
||||
#define LLC_FRMR_Y (1<<2)
|
||||
#define LLC_FRMR_Z (1<<3)
|
||||
#define LLC_FRMR_V (1<<4)
|
||||
|
||||
#define LLC_SETFRMR(l, f, cr, c) { \
|
||||
if ((f)->llc_control & 0x3) { \
|
||||
(l)->llcl_frmr_pdu0 = (f)->llc_control; \
|
||||
(l)->llcl_frmr_pdu1 = 0; \
|
||||
} else { \
|
||||
(l)->llcl_frmr_pdu0 = (f)->llc_control; \
|
||||
(l)->llcl_frmr_pdu1 = (f)->llc_control_ext; \
|
||||
} \
|
||||
LLCCSBITS((l)->llcl_frmr_control, f_vs, (l)->llcl_vs); \
|
||||
LLCCSBITS((l)->llcl_frmr_control_ext, f_cr, (cr)); \
|
||||
LLCSBITS((l)->llcl_frmr_control_ext, f_vr, (l)->llcl_vr); \
|
||||
LLCCSBITS((l)->llcl_frmr_cause, f_wxyzv, (c)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* LLC tracing levels:
|
||||
* LLCTR_INTERESTING interesting event, we might care to know about
|
||||
* it, but then again, we might not ...
|
||||
* LLCTR_SHOULDKNOW we probably should know about this event
|
||||
* LLCTR_URGENT something has gone utterly wrong ...
|
||||
*/
|
||||
#define LLCTR_INTERESTING 1
|
||||
#define LLCTR_SHOULDKNOW 2
|
||||
#define LLCTR_URGENT 3
|
||||
|
||||
#ifdef LLCDEBUG
|
||||
#define LLC_TRACE(lp, l, msg) llc_trace((lp), (l), (msg))
|
||||
#else /* LLCDEBUG */
|
||||
#define LLC_TRACE(lp, l, msg) /* NOOP */
|
||||
#endif /* LLCDEBUG */
|
||||
|
||||
#define LLC_N2_VALUE 15 /* up to 15 retries */
|
||||
#define LLC_ACK_TIMER 10 /* 5 secs */
|
||||
#define LLC_P_TIMER 4 /* 2 secs */
|
||||
#define LLC_BUSY_TIMER 12 /* 6 secs */
|
||||
#define LLC_REJ_TIMER 12 /* 6 secs */
|
||||
#define LLC_AGE_TIMER 40 /* 20 secs */
|
||||
#define LLC_DACTION_TIMER 2 /* 1 secs */
|
||||
|
||||
#if defined (KERNEL) && defined(LLC)
|
||||
extern int llc_n2;
|
||||
extern int llc_ACK_timer;
|
||||
extern int llc_P_timer;
|
||||
extern int llc_REJ_timer;
|
||||
extern int llc_BUSY_timer;
|
||||
extern int llc_AGE_timer;
|
||||
extern int llc_DACTION_timer;
|
||||
|
||||
extern int af_link_rts_init_done;
|
||||
|
||||
#define USES_AF_LINK_RTS { \
|
||||
if (!af_link_rts_init_done) { \
|
||||
rn_inithead((void **)&rt_tables[AF_LINK], 32); \
|
||||
af_link_rts_init_done++; \
|
||||
} \
|
||||
}
|
||||
|
||||
extern struct ifqueue llcintrq;
|
||||
|
||||
extern struct llccb_q llccb_q;
|
||||
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
int sdl_sethdrif __P((struct ifnet *, u_char *, u_char, u_char *, u_char, u_char,
|
||||
struct sdl_hdr *));
|
||||
struct npaidbentry *llc_setsapinfo __P((struct ifnet *, u_char, u_char,
|
||||
struct dllconfig *));
|
||||
struct npaidbentry *llc_getsapinfo __P((u_char, struct ifnet *));
|
||||
struct rtentry *npaidb_enrich __P((short, caddr_t, struct sockaddr_dl *));
|
||||
int npaidb_destroy __P((struct rtentry *));
|
||||
short llc_seq2slot __P((struct llc_linkcb *, short));
|
||||
void sdl_swapaddr __P((struct sockaddr_dl *, struct sockaddr_dl *));
|
||||
|
||||
int llc_state_NORMAL __P((struct llc_linkcb *, struct llc *, int, int, int));
|
||||
int llc_state_BUSY __P((struct llc_linkcb *, struct llc *, int, int, int));
|
||||
int llc_state_REJECT __P((struct llc_linkcb *, struct llc *, int, int, int));
|
||||
int llc_statehandler __P((struct llc_linkcb *, struct llc *, int, int, int));
|
||||
void llc_init __P((void));
|
||||
struct llc_linkcb *llc_newlink __P((struct sockaddr_dl *, struct ifnet *,
|
||||
struct rtentry *, caddr_t, struct rtentry *));
|
||||
void llc_dellink __P((struct llc_linkcb *));
|
||||
int llc_anytimersup __P((struct llc_linkcb *));
|
||||
int llc_decode __P((struct llc *, struct llc_linkcb *));
|
||||
void llc_timer __P((void));
|
||||
void llcintr __P((void));
|
||||
int llc_input __P((struct llc_linkcb *, struct mbuf *, u_char));
|
||||
caddr_t llc_ctlinput __P((int, struct sockaddr *, caddr_t));
|
||||
int llc_output __P((struct llc_linkcb *, struct mbuf *));
|
||||
void llc_start __P((struct llc_linkcb *));
|
||||
int llc_send __P((struct llc_linkcb *, int, int, int));
|
||||
int llc_resend __P((struct llc_linkcb *, int, int));
|
||||
int llc_rawsend __P((struct llc_linkcb *, struct mbuf *, struct llc *, int, int,
|
||||
int, int));
|
||||
int cons_rtrequest __P((int, struct rtentry *, struct sockaddr *));
|
||||
int x25_llcglue __P((int, struct sockaddr *));
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pk.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: pk.h,v 1.5 1995/11/21 12:54:10 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_PK_H_
|
||||
#define _NETCITT_PK_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* X.25 Packet Level Definitions:
|
||||
*
|
||||
*/
|
||||
|
||||
/* Packet type identifier field definitions. */
|
||||
|
||||
#define X25_CALL 11
|
||||
#define X25_CALL_ACCEPTED 15
|
||||
#define X25_CLEAR 19
|
||||
#define X25_CLEAR_CONFIRM 23
|
||||
#define X25_DATA 0
|
||||
#define X25_INTERRUPT 35
|
||||
#define X25_INTERRUPT_CONFIRM 39
|
||||
|
||||
#define X25_RR 1
|
||||
#define X25_RNR 5
|
||||
#define X25_REJECT 9
|
||||
#define X25_RESET 27
|
||||
#define X25_RESET_CONFIRM 31
|
||||
#define X25_DIAGNOSTIC 241
|
||||
|
||||
#define X25_RESTART 251
|
||||
#define X25_RESTART_CONFIRM 255
|
||||
|
||||
/* Restart cause field definitions. */
|
||||
|
||||
#define X25_RESTART_DTE_ORIGINATED 0
|
||||
#define X25_RESTART_LOCAL_PROCEDURE_ERROR 1
|
||||
#define X25_RESTART_NETWORK_CONGESTION 3
|
||||
#define X25_RESTART_NETWORK_OPERATIONAL 7
|
||||
#define X25_RESTART_DTE_ORIGINATED2 128
|
||||
|
||||
|
||||
/* Miscellaneous definitions. */
|
||||
|
||||
#define DATA_PACKET_DESIGNATOR 0x01
|
||||
#define RR_OR_RNR_PACKET_DESIGNATOR 0x02
|
||||
#define RR_PACKET_DESIGNATOR 0x04
|
||||
|
||||
#define DEFAULT_WINDOW_SIZE 2
|
||||
#define MODULUS 8
|
||||
|
||||
#define ADDRLN 1
|
||||
#define MAXADDRLN 15
|
||||
#define FACILITIESLN 1
|
||||
#define MAXFACILITIESLN 10
|
||||
#define MAXUSERDATA 16
|
||||
#define MAXCALLINFOLN 1+15+1+10+16
|
||||
|
||||
#define PACKET_OK 0
|
||||
#define IGNORE_PACKET 1
|
||||
#define ERROR_PACKET 2
|
||||
|
||||
typedef char bool;
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
/*
|
||||
* X.25 Packet format definitions
|
||||
* This will eventually have to be rewritten without reference
|
||||
* to bit fields, to be ansi C compliant and alignment safe.
|
||||
*/
|
||||
|
||||
typedef u_char octet;
|
||||
|
||||
struct x25_calladdr {
|
||||
octet addrlens;
|
||||
octet address_field[MAXADDRLN];
|
||||
};
|
||||
|
||||
struct x25_packet {
|
||||
octet bits;
|
||||
octet logical_channel_number;
|
||||
octet packet_type;
|
||||
octet packet_data;
|
||||
};
|
||||
#define packet_cause packet_data
|
||||
|
||||
struct data_packet {
|
||||
octet bits;
|
||||
};
|
||||
|
||||
#define FACILITIES_REVERSE_CHARGE 0x1
|
||||
#define FACILITIES_THROUGHPUT 0x2
|
||||
#define FACILITIES_PACKETSIZE 0x42
|
||||
#define FACILITIES_WINDOWSIZE 0x43
|
||||
|
||||
#define PKHEADERLN 3
|
||||
|
||||
#define DP(xp) (((struct data_packet *)&(xp) -> packet_type) -> bits)
|
||||
#define PS(xp) X25GBITS(DP(xp), p_s)
|
||||
#define PR(xp) X25GBITS(DP(xp), p_r)
|
||||
#define MBIT(xp) X25GBITS(DP(xp), m_bit)
|
||||
#define SPR(xp, v) X25SBITS(DP(xp), p_r, (v))
|
||||
#define SPS(xp, v) X25SBITS(DP(xp), p_s, (v))
|
||||
#define SMBIT(xp, v) X25SBITS(DP(xp), m_bit, (v))
|
||||
|
||||
#define LCN(xp) (xp -> logical_channel_number + \
|
||||
(X25GBITS(xp -> bits, lc_group_number) ? (X25GBITS(xp -> bits, lc_group_number) << 8) : 0))
|
||||
#define SET_LCN(xp, lcn) ((xp -> logical_channel_number = lcn), \
|
||||
(X25SBITS(xp -> bits, lc_group_number, lcn > 255 ? lcn >> 8 : 0)))
|
||||
|
||||
struct mbuf *pk_template __P((int lcn, int type));
|
||||
|
||||
/* Define X.25 packet level states. */
|
||||
|
||||
/* Call setup and clearing substates. */
|
||||
|
||||
#define LISTEN 0
|
||||
#define READY 1
|
||||
#define RECEIVED_CALL 2
|
||||
#define SENT_CALL 3
|
||||
#define DATA_TRANSFER 4
|
||||
#define RECEIVED_CLEAR 5
|
||||
#define SENT_CLEAR 6
|
||||
|
||||
/* DTE states. */
|
||||
|
||||
#define DTE_WAITING 7
|
||||
#define DTE_RECEIVED_RESTART 8
|
||||
#define DTE_SENT_RESTART 9
|
||||
#define DTE_READY 0
|
||||
|
||||
/* Cleaning out ... */
|
||||
|
||||
#define LCN_ZOMBIE 10
|
||||
|
||||
#define MAXSTATES 11
|
||||
|
||||
/*
|
||||
* The following definitions are used in a switch statement after
|
||||
* determining the packet type. These values are returned by the
|
||||
* pk_decode procedure.
|
||||
*/
|
||||
|
||||
#define CALL 0 * MAXSTATES
|
||||
#define CALL_ACCEPTED 1 * MAXSTATES
|
||||
#define CLEAR 2 * MAXSTATES
|
||||
#define CLEAR_CONF 3 * MAXSTATES
|
||||
#define DATA 4 * MAXSTATES
|
||||
#define INTERRUPT 5 * MAXSTATES
|
||||
#define INTERRUPT_CONF 6 * MAXSTATES
|
||||
#define RR 7 * MAXSTATES
|
||||
#define RNR 8 * MAXSTATES
|
||||
#define RESET 9 * MAXSTATES
|
||||
#define RESET_CONF 10 * MAXSTATES
|
||||
#define RESTART 11 * MAXSTATES
|
||||
#define RESTART_CONF 12 * MAXSTATES
|
||||
#define REJECT 13 * MAXSTATES
|
||||
#define DIAG_TYPE 14 * MAXSTATES
|
||||
#define INVALID_PACKET 15 * MAXSTATES
|
||||
#define DELETE_PACKET INVALID_PACKET
|
||||
|
||||
/*
|
||||
* The following definitions are used by the restart procedures
|
||||
* for noting wether the PLE is supposed to behave as DTE or DCE
|
||||
* (essentially necessary for operation over LLC2)
|
||||
*/
|
||||
#define DTE_DXERESOLVING 0x0001
|
||||
#define DTE_PLAYDTE 0x0002
|
||||
#define DTE_PLAYDCE 0x0004
|
||||
#define DTE_CONNECTPENDING 0x0010
|
||||
#define DTE_PRETENDDTE 0x0020
|
||||
|
||||
#define MAXRESTARTCOLLISIONS 10
|
||||
|
||||
#endif
|
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pk_acct.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: pk_acct.c,v 1.2 1994/08/02 07:47:29 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/x25.h>
|
||||
#include <netccitt/pk.h>
|
||||
#include <netccitt/pk_var.h>
|
||||
#include <netccitt/x25acct.h>
|
||||
|
||||
|
||||
struct vnode *pkacctp;
|
||||
/*
|
||||
* Turn on packet accounting
|
||||
*/
|
||||
|
||||
pk_accton (path)
|
||||
char *path;
|
||||
{
|
||||
register struct vnode *vp = NULL;
|
||||
struct nameidata nd;
|
||||
struct vnode *oacctp = pkacctp;
|
||||
struct proc *p = curproc;
|
||||
int error;
|
||||
|
||||
if (path == 0)
|
||||
goto close;
|
||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p);
|
||||
if (error = vn_open (&nd, FWRITE, 0644))
|
||||
return (error);
|
||||
vp = nd.ni_vp;
|
||||
VOP_UNLOCK(vp);
|
||||
if (vp -> v_type != VREG) {
|
||||
vrele (vp);
|
||||
return (EACCES);
|
||||
}
|
||||
pkacctp = vp;
|
||||
if (oacctp) {
|
||||
close:
|
||||
error = vn_close (oacctp, FWRITE, p -> p_ucred, p);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a record on the accounting file.
|
||||
*/
|
||||
|
||||
pk_acct (lcp)
|
||||
register struct pklcd *lcp;
|
||||
{
|
||||
register struct vnode *vp;
|
||||
register struct sockaddr_x25 *sa;
|
||||
register char *src, *dst;
|
||||
register int len;
|
||||
register long etime;
|
||||
static struct x25acct acbuf;
|
||||
|
||||
if ((vp = pkacctp) == 0)
|
||||
return;
|
||||
bzero ((caddr_t)&acbuf, sizeof (acbuf));
|
||||
if (lcp -> lcd_ceaddr != 0)
|
||||
sa = lcp -> lcd_ceaddr;
|
||||
else if (lcp -> lcd_craddr != 0) {
|
||||
sa = lcp -> lcd_craddr;
|
||||
acbuf.x25acct_callin = 1;
|
||||
} else
|
||||
return;
|
||||
|
||||
if (sa -> x25_opts.op_flags & X25_REVERSE_CHARGE)
|
||||
acbuf.x25acct_revcharge = 1;
|
||||
acbuf.x25acct_stime = lcp -> lcd_stime;
|
||||
acbuf.x25acct_etime = time.tv_sec - acbuf.x25acct_stime;
|
||||
acbuf.x25acct_uid = curproc -> p_cred -> p_ruid;
|
||||
acbuf.x25acct_psize = sa -> x25_opts.op_psize;
|
||||
acbuf.x25acct_net = sa -> x25_net;
|
||||
/*
|
||||
* Convert address to bcd
|
||||
*/
|
||||
src = sa -> x25_addr;
|
||||
dst = acbuf.x25acct_addr;
|
||||
for (len = 0; *src; len++)
|
||||
if (len & 01)
|
||||
*dst++ |= *src++ & 0xf;
|
||||
else
|
||||
*dst = *src++ << 4;
|
||||
acbuf.x25acct_addrlen = len;
|
||||
|
||||
bcopy (sa -> x25_udata, acbuf.x25acct_udata,
|
||||
sizeof (acbuf.x25acct_udata));
|
||||
acbuf.x25acct_txcnt = lcp -> lcd_txcnt;
|
||||
acbuf.x25acct_rxcnt = lcp -> lcd_rxcnt;
|
||||
|
||||
(void) vn_rdwr(UIO_WRITE, vp, (caddr_t)&acbuf, sizeof (acbuf),
|
||||
(off_t)0, UIO_SYSSPACE, IO_UNIT|IO_APPEND,
|
||||
curproc -> p_ucred, (int *)0,
|
||||
(struct proc *)0);
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pk_debug.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/x25.h>
|
||||
#include <netccitt/pk.h>
|
||||
#include <netccitt/pk_var.h>
|
||||
|
||||
char *pk_state[] = {
|
||||
"Listen", "Ready", "Received-Call",
|
||||
"Sent-Call", "Data-Transfer","Received-Clear",
|
||||
"Sent-Clear",
|
||||
};
|
||||
|
||||
char *pk_name[] = {
|
||||
"Call", "Call-Conf", "Clear",
|
||||
"Clear-Conf", "Data", "Intr", "Intr-Conf",
|
||||
"Rr", "Rnr", "Reset", "Reset-Conf",
|
||||
"Restart", "Restart-Conf", "Reject", "Diagnostic",
|
||||
"Invalid"
|
||||
};
|
||||
|
||||
pk_trace (xcp, m, dir)
|
||||
struct x25config *xcp;
|
||||
register struct mbuf *m;
|
||||
char *dir;
|
||||
{
|
||||
register char *s;
|
||||
struct x25_packet *xp = mtod(m, struct x25_packet *);
|
||||
register int i, len = 0, cnt = 0;
|
||||
|
||||
if (xcp -> xc_ptrace == 0)
|
||||
return;
|
||||
|
||||
i = pk_decode (xp) / MAXSTATES;
|
||||
for (; m; m = m -> m_next) {
|
||||
len = len + m -> m_len;
|
||||
++cnt;
|
||||
}
|
||||
printf ("LCN=%d %s: %s #=%d, len=%d ",
|
||||
LCN(xp), dir, pk_name[i], cnt, len);
|
||||
for (s = (char *) xp, i = 0; i < 5; ++i, ++s)
|
||||
printf ("%x ", (int) * s & 0xff);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
mbuf_cache(c, m)
|
||||
register struct mbuf_cache *c;
|
||||
struct mbuf *m;
|
||||
{
|
||||
register struct mbuf **mp;
|
||||
|
||||
if (c->mbc_size != c->mbc_oldsize) {
|
||||
unsigned zero_size, copy_size;
|
||||
unsigned new_size = c->mbc_size * sizeof(m);
|
||||
caddr_t cache = (caddr_t)c->mbc_cache;
|
||||
|
||||
if (new_size) {
|
||||
c->mbc_cache = (struct mbuf **)
|
||||
malloc(new_size, M_MBUF, M_NOWAIT);
|
||||
if (c->mbc_cache == 0) {
|
||||
c->mbc_cache = (struct mbuf **)cache;
|
||||
return;
|
||||
}
|
||||
c->mbc_num %= c->mbc_size;
|
||||
} else
|
||||
c->mbc_cache = 0;
|
||||
if (c->mbc_size < c->mbc_oldsize) {
|
||||
register struct mbuf **mplim;
|
||||
mp = c->mbc_size + (struct mbuf **)cache;
|
||||
mplim = c->mbc_oldsize + (struct mbuf **)cache;
|
||||
while (mp < mplim)
|
||||
m_freem(*mp++);
|
||||
zero_size = 0;
|
||||
} else
|
||||
zero_size = (c->mbc_size - c->mbc_oldsize) * sizeof(m);
|
||||
copy_size = new_size - zero_size;
|
||||
c->mbc_oldsize = c->mbc_size;
|
||||
if (copy_size)
|
||||
bcopy(cache, (caddr_t)c->mbc_cache, copy_size);
|
||||
if (cache)
|
||||
free(cache, M_MBUF);
|
||||
if (zero_size)
|
||||
bzero(copy_size + (caddr_t)c->mbc_cache, zero_size);
|
||||
}
|
||||
if (c->mbc_size == 0)
|
||||
return;
|
||||
mp = c->mbc_cache + c->mbc_num;
|
||||
c->mbc_num = (1 + c->mbc_num) % c->mbc_size;
|
||||
if (*mp)
|
||||
m_freem(*mp);
|
||||
if (*mp = m_copym(m, 0, M_COPYALL, M_DONTWAIT))
|
||||
(*mp)->m_flags |= m->m_flags & 0x08;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,371 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Dirk Husemann, Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Dirk Husemann and the Computer Science Department (IV) of
|
||||
* the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pk_llcsubr.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: pk_llcsubr.c,v 1.3 1994/12/13 22:32:16 wollman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_llc.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netccitt/dll.h>
|
||||
#include <netccitt/x25.h>
|
||||
#include <netccitt/pk.h>
|
||||
#include <netccitt/pk_var.h>
|
||||
#include <netccitt/llc_var.h>
|
||||
|
||||
|
||||
/*
|
||||
* Routing support for X.25
|
||||
*
|
||||
* We distinguish between two cases:
|
||||
* RTF_HOST:
|
||||
* rt_key(rt) X.25 address of host
|
||||
* rt_gateway SNPA (MAC+DLSAP) address of host
|
||||
* rt_llinfo pkcb for rt_key(rt)
|
||||
*
|
||||
* RTF_GATEWAY
|
||||
* rt_key(rt) X.25 address of host or suitably masked network
|
||||
* rt_gateway X.25 address of next X.25 gateway (switch)
|
||||
* rt_llinfo rtentry for rt_gateway address
|
||||
* ought to be of type RTF_HOST
|
||||
*
|
||||
*
|
||||
* Mapping of X.121 to pkcbs:
|
||||
*
|
||||
* HDLC uses the DTE-DCE model of X.25, therefore we need a many-to-one
|
||||
* relationship, i.e.:
|
||||
*
|
||||
* {X.121_a, X.121_b, X.121_c, ..., X.121_i} -> pkcb_0
|
||||
*
|
||||
* LLC2 utilizes the DTE-DTE model of X.25, resulting effectively in a
|
||||
* one-to-one relationship, i.e.:
|
||||
*
|
||||
* {X.121_j} -> pkcb_1a
|
||||
* {X.121_k} -> pkcb_1b
|
||||
* ...
|
||||
* {X.121_q} -> pkcb_1q
|
||||
*
|
||||
* It might make sense to allow a many-to-one relation for LLC2 also,
|
||||
*
|
||||
* {X.121_r, X.121_s, X.121_t, X.121_u} -> pkcb_2a
|
||||
*
|
||||
* This would make addresses X.121_[r-u] essentially aliases of one
|
||||
* address ({X.121_[r-u]} would constitute a representative set).
|
||||
*
|
||||
* Each one-to-one relation must obviously be entered individually with
|
||||
* a route add command, whereas a many-to-one relationship can be
|
||||
* either entered individually or generated by using a netmask.
|
||||
*
|
||||
* To facilitate dealings the many-to-one case for LLC2 can only be
|
||||
* established via a netmask.
|
||||
*
|
||||
*/
|
||||
|
||||
#define XTRACTPKP(rt) ((rt)->rt_flags & RTF_GATEWAY ? \
|
||||
((rt)->rt_llinfo ? \
|
||||
(struct pkcb *) ((struct rtentry *)((rt)->rt_llinfo))->rt_llinfo : \
|
||||
(struct pkcb *) NULL) : \
|
||||
(struct pkcb *)((rt)->rt_llinfo))
|
||||
|
||||
#define equal(a1, a2) (bcmp((caddr_t)(a1), \
|
||||
(caddr_t)(a2), \
|
||||
(a1)->sa_len) == 0)
|
||||
#define XIFA(rt) ((struct x25_ifaddr *)((rt)->rt_ifa))
|
||||
#define SA(s) ((struct sockaddr *)s)
|
||||
|
||||
int
|
||||
cons_rtrequest(int cmd, struct rtentry *rt, struct sockaddr *dst)
|
||||
{
|
||||
register struct pkcb *pkp;
|
||||
register int i;
|
||||
register char one_to_one;
|
||||
struct pkcb *pk_newlink();
|
||||
struct rtentry *npaidb_enter();
|
||||
|
||||
pkp = XTRACTPKP(rt);
|
||||
|
||||
switch(cmd) {
|
||||
case RTM_RESOLVE:
|
||||
case RTM_ADD:
|
||||
if (pkp)
|
||||
return(EEXIST);
|
||||
|
||||
if (rt->rt_flags & RTF_GATEWAY) {
|
||||
if (rt->rt_llinfo)
|
||||
RTFREE((struct rtentry *)rt->rt_llinfo);
|
||||
rt->rt_llinfo = (caddr_t) rtalloc1(rt->rt_gateway, 1,
|
||||
0UL);
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
* Assumptions: (1) ifnet structure is filled in
|
||||
* (2) at least the pkcb created via
|
||||
* x25config (ifconfig?) has been
|
||||
* set up already.
|
||||
* (3) HDLC interfaces have an if_type of
|
||||
* IFT_X25{,DDN}, LLC2 interfaces
|
||||
* anything else (any better way to
|
||||
* do this?)
|
||||
*
|
||||
*/
|
||||
if (!rt->rt_ifa)
|
||||
return (ENETDOWN);
|
||||
|
||||
/*
|
||||
* We differentiate between dealing with a many-to-one
|
||||
* (HDLC: DTE-DCE) and a one-to-one (LLC2: DTE-DTE)
|
||||
* relationship (by looking at the if type).
|
||||
*
|
||||
* Only in case of the many-to-one relationship (HDLC)
|
||||
* we set the ia->ia_pkcb pointer to the pkcb allocated
|
||||
* via pk_newlink() as we will use just that one pkcb for
|
||||
* future route additions (the rtentry->rt_llinfo pointer
|
||||
* points to the pkcb allocated for that route).
|
||||
*
|
||||
* In case of the one-to-one relationship (LLC2) we
|
||||
* create a new pkcb (via pk_newlink()) for each new rtentry.
|
||||
*
|
||||
* NOTE: Only in case of HDLC does ia->ia_pkcb point
|
||||
* to a pkcb, in the LLC2 case it doesn't (as we don't
|
||||
* need it here)!
|
||||
*/
|
||||
one_to_one = ISISO8802(rt->rt_ifp);
|
||||
|
||||
if (!(pkp = XIFA(rt)->ia_pkcb) && !one_to_one)
|
||||
XIFA(rt)->ia_pkcb = pkp =
|
||||
pk_newlink(XIFA(rt), (caddr_t) 0);
|
||||
else if (one_to_one &&
|
||||
!equal(rt->rt_gateway, rt->rt_ifa->ifa_addr)) {
|
||||
pkp = pk_newlink(XIFA(rt), (caddr_t) 0);
|
||||
/*
|
||||
* We also need another route entry for mapping
|
||||
* MAC+LSAP->X.25 address
|
||||
*/
|
||||
pkp->pk_llrt = npaidb_enter(rt->rt_gateway, rt_key(rt), rt, 0);
|
||||
}
|
||||
if (pkp) {
|
||||
if (!pkp->pk_rt)
|
||||
pkp->pk_rt = rt;
|
||||
pkp->pk_refcount++;
|
||||
}
|
||||
rt->rt_llinfo = (caddr_t) pkp;
|
||||
|
||||
return(0);
|
||||
|
||||
case RTM_DELETE:
|
||||
{
|
||||
/*
|
||||
* The pkp might be empty if we are dealing
|
||||
* with an interface route entry for LLC2, in this
|
||||
* case we don't need to do anything ...
|
||||
*/
|
||||
if (pkp) {
|
||||
if ( rt->rt_flags & RTF_GATEWAY ) {
|
||||
if (rt->rt_llinfo)
|
||||
RTFREE((struct rtentry *)rt->rt_llinfo);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (pkp->pk_llrt)
|
||||
npaidb_destroy(pkp->pk_llrt);
|
||||
|
||||
pk_dellink (pkp);
|
||||
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Network Protocol Addressing Information DataBase (npaidb)
|
||||
*
|
||||
* To speed up locating the entity dealing with an LLC packet use is made
|
||||
* of a routing tree. This npaidb routing tree is handled
|
||||
* by the normal rn_*() routines just like (almost) any other routing tree.
|
||||
*
|
||||
* The mapping being done by the npaidb_*() routines is as follows:
|
||||
*
|
||||
* Key: MAC,LSAP (enhancing struct sockaddr_dl)
|
||||
* Gateway: sockaddr_x25 (i.e. X.25 address - X.121 or NSAP)
|
||||
* Llinfo: npaidbentry {
|
||||
* struct llc_linkcb *npaidb_linkp;
|
||||
* struct rtentry *npaidb_rt;
|
||||
* }
|
||||
*
|
||||
* Using the npaidbentry provided by llinfo we can then access
|
||||
*
|
||||
* o the pkcb by using (struct pkcb *) (npaidb_rt->rt_llinfo)
|
||||
* o the linkcb via npaidb_linkp
|
||||
*
|
||||
* The following functions are provided
|
||||
*
|
||||
* o npaidb_enter(struct sockaddr_dl *sdl, struct sockaddr_x25 *sx25,
|
||||
* struct struct llc_linkcb *link, struct rtentry *rt)
|
||||
*
|
||||
* o npaidb_enrich(short type, caddr_t info)
|
||||
*
|
||||
*/
|
||||
|
||||
struct sockaddr_dl npdl_netmask = {
|
||||
sizeof(struct sockaddr_dl), /* _len */
|
||||
0, /* _family */
|
||||
0, /* _index */
|
||||
0, /* _type */
|
||||
-1, /* _nlen */
|
||||
-1, /* _alen */
|
||||
-1, /* _slen */
|
||||
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* _data */
|
||||
};
|
||||
struct sockaddr npdl_dummy;
|
||||
|
||||
int npdl_datasize = sizeof(struct sockaddr_dl)-
|
||||
((int)((caddr_t)&((struct sockaddr_dl *)0)->sdl_data[0]));
|
||||
|
||||
struct rtentry *
|
||||
npaidb_enter(struct sockaddr_dl *key, struct sockaddr *value,
|
||||
struct rtentry *rt, struct llc_linkcb *link)
|
||||
{
|
||||
struct rtentry *nprt; register int i;
|
||||
|
||||
USES_AF_LINK_RTS;
|
||||
|
||||
if ((nprt = rtalloc1(SA(key), 0, 0UL)) == 0) {
|
||||
register u_int size = sizeof(struct npaidbentry);
|
||||
register u_char saploc = LLSAPLOC(key, rt->rt_ifp);
|
||||
|
||||
/*
|
||||
* set up netmask: LLC2 packets have the lowest bit set in
|
||||
* response packets (e.g. 0x7e for command packets, 0x7f for
|
||||
* response packets), to facilitate the lookup we use a netmask
|
||||
* of 11111110 for the SAP position. The remaining positions
|
||||
* are zeroed out.
|
||||
*/
|
||||
npdl_netmask.sdl_data[saploc] = NPDL_SAPNETMASK;
|
||||
bzero((caddr_t)&npdl_netmask.sdl_data[saploc+1],
|
||||
npdl_datasize-saploc-1);
|
||||
|
||||
if (value == 0)
|
||||
value = &npdl_dummy;
|
||||
|
||||
/* now enter it */
|
||||
rtrequest(RTM_ADD, SA(key), SA(value),
|
||||
SA(&npdl_netmask), 0, &nprt);
|
||||
|
||||
/* and reset npdl_netmask */
|
||||
for (i = saploc; i < npdl_datasize; i++)
|
||||
npdl_netmask.sdl_data[i] = -1;
|
||||
|
||||
nprt->rt_llinfo = malloc(size , M_PCB, M_WAITOK);
|
||||
if (nprt->rt_llinfo) {
|
||||
bzero (nprt->rt_llinfo, size);
|
||||
((struct npaidbentry *) (nprt->rt_llinfo))->np_rt = rt;
|
||||
}
|
||||
} else nprt->rt_refcnt--;
|
||||
return nprt;
|
||||
}
|
||||
|
||||
struct rtentry *
|
||||
npaidb_enrich(short type, caddr_t info, struct sockaddr_dl *sdl)
|
||||
{
|
||||
struct rtentry *rt;
|
||||
|
||||
USES_AF_LINK_RTS;
|
||||
|
||||
if (rt = rtalloc1((struct sockaddr *)sdl, 0, 0UL)) {
|
||||
rt->rt_refcnt--;
|
||||
switch (type) {
|
||||
case NPAIDB_LINK:
|
||||
((struct npaidbentry *)(rt->rt_llinfo))->np_link =
|
||||
(struct llc_linkcb *) info;
|
||||
break;
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
return ((struct rtentry *) 0);
|
||||
|
||||
}
|
||||
|
||||
npaidb_destroy(struct rtentry *rt)
|
||||
{
|
||||
USES_AF_LINK_RTS;
|
||||
|
||||
if (rt->rt_llinfo)
|
||||
free((caddr_t) rt->rt_llinfo, M_PCB);
|
||||
return(rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
|
||||
0, 0));
|
||||
}
|
||||
|
||||
|
||||
#ifdef LLC
|
||||
/*
|
||||
* Glue between X.25 and LLC2
|
||||
*/
|
||||
int
|
||||
x25_llcglue(int prc, struct sockaddr *addr)
|
||||
{
|
||||
register struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)addr;
|
||||
register struct x25_ifaddr *x25ifa;
|
||||
struct dll_ctlinfo ctlinfo;
|
||||
|
||||
if((x25ifa = (struct x25_ifaddr *)ifa_ifwithaddr(addr)) == 0)
|
||||
return 0;
|
||||
|
||||
ctlinfo.dlcti_cfg =
|
||||
(struct dllconfig *)(((struct sockaddr_x25 *)(&x25ifa->ia_xc))+1);
|
||||
ctlinfo.dlcti_lsap = LLC_X25_LSAP;
|
||||
|
||||
return ((int)llc_ctlinput(prc, addr, (caddr_t)&ctlinfo));
|
||||
}
|
||||
#endif /* LLC */
|
@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (C) Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1992
|
||||
* Copyright (c) 1991, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by the
|
||||
* Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the the University of British Columbia and the Computer Science
|
||||
* Department (IV) of the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pk_output.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: pk_output.c,v 1.2 1994/08/02 07:47:38 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/x25.h>
|
||||
#include <netccitt/pk.h>
|
||||
#include <netccitt/pk_var.h>
|
||||
|
||||
struct mbuf_cache pk_output_cache = {0 }, pk_input_cache;
|
||||
struct mbuf *nextpk ();
|
||||
|
||||
pk_output (lcp)
|
||||
register struct pklcd *lcp;
|
||||
{
|
||||
register struct x25_packet *xp;
|
||||
register struct mbuf *m;
|
||||
register struct pkcb *pkp = lcp -> lcd_pkp;
|
||||
|
||||
if (lcp == 0 || pkp == 0) {
|
||||
printf ("pk_output: zero arg\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while ((m = nextpk (lcp)) != NULL) {
|
||||
xp = mtod (m, struct x25_packet *);
|
||||
|
||||
switch (pk_decode (xp) + lcp -> lcd_state) {
|
||||
/*
|
||||
* All the work is already done - just set the state and
|
||||
* pass to peer.
|
||||
*/
|
||||
case CALL + READY:
|
||||
lcp -> lcd_state = SENT_CALL;
|
||||
lcp -> lcd_timer = pk_t21;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Just set the state to allow packet to flow and send the
|
||||
* confirmation.
|
||||
*/
|
||||
case CALL_ACCEPTED + RECEIVED_CALL:
|
||||
lcp -> lcd_state = DATA_TRANSFER;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Just set the state. Keep the LCD around till the clear
|
||||
* confirmation is returned.
|
||||
*/
|
||||
case CLEAR + RECEIVED_CALL:
|
||||
case CLEAR + SENT_CALL:
|
||||
case CLEAR + DATA_TRANSFER:
|
||||
lcp -> lcd_state = SENT_CLEAR;
|
||||
lcp -> lcd_retry = 0;
|
||||
/* fall through */
|
||||
|
||||
case CLEAR + SENT_CLEAR:
|
||||
lcp -> lcd_timer = pk_t23;
|
||||
lcp -> lcd_retry++;
|
||||
break;
|
||||
|
||||
case CLEAR_CONF + RECEIVED_CLEAR:
|
||||
case CLEAR_CONF + SENT_CLEAR:
|
||||
case CLEAR_CONF + READY:
|
||||
lcp -> lcd_state = READY;
|
||||
break;
|
||||
|
||||
case DATA + DATA_TRANSFER:
|
||||
SPS(xp, lcp -> lcd_ssn);
|
||||
lcp -> lcd_input_window =
|
||||
(lcp -> lcd_rsn + 1) % MODULUS;
|
||||
SPR(xp, lcp -> lcd_input_window);
|
||||
lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
|
||||
lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS;
|
||||
if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + lcp -> lcd_windowsize) % MODULUS))
|
||||
lcp -> lcd_window_condition = TRUE;
|
||||
break;
|
||||
|
||||
case INTERRUPT + DATA_TRANSFER:
|
||||
#ifdef ancient_history
|
||||
xp -> packet_data = 0;
|
||||
#endif
|
||||
lcp -> lcd_intrconf_pending = TRUE;
|
||||
break;
|
||||
|
||||
case INTERRUPT_CONF + DATA_TRANSFER:
|
||||
break;
|
||||
|
||||
case RR + DATA_TRANSFER:
|
||||
case RNR + DATA_TRANSFER:
|
||||
lcp -> lcd_input_window =
|
||||
(lcp -> lcd_rsn + 1) % MODULUS;
|
||||
SPR(xp, lcp -> lcd_input_window);
|
||||
lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
|
||||
break;
|
||||
|
||||
case RESET + DATA_TRANSFER:
|
||||
lcp -> lcd_reset_condition = TRUE;
|
||||
break;
|
||||
|
||||
case RESET_CONF + DATA_TRANSFER:
|
||||
lcp -> lcd_reset_condition = FALSE;
|
||||
break;
|
||||
|
||||
/*
|
||||
* A restart should be only generated internally. Therefore
|
||||
* all logic for restart is in the pk_restart routine.
|
||||
*/
|
||||
case RESTART + READY:
|
||||
lcp -> lcd_timer = pk_t20;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Restarts are all handled internally. Therefore all the
|
||||
* logic for the incoming restart packet is handled in the
|
||||
* pk_input routine.
|
||||
*/
|
||||
case RESTART_CONF + READY:
|
||||
break;
|
||||
|
||||
default:
|
||||
m_freem (m);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Trace the packet. */
|
||||
pk_trace (pkp -> pk_xcp, m, "P-Out");
|
||||
|
||||
/* Pass the packet on down to the link layer */
|
||||
if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize) {
|
||||
m->m_flags |= 0x08;
|
||||
mbuf_cache(&pk_input_cache, m);
|
||||
}
|
||||
(*pkp -> pk_lloutput) (pkp -> pk_llnext, m, pkp -> pk_rt);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This procedure returns the next packet to send or null. A
|
||||
* packet is composed of one or more mbufs.
|
||||
*/
|
||||
|
||||
struct mbuf *
|
||||
nextpk (lcp)
|
||||
struct pklcd *lcp;
|
||||
{
|
||||
register struct mbuf *m, *n;
|
||||
struct socket *so = lcp -> lcd_so;
|
||||
register struct sockbuf *sb = & (so ? so -> so_snd : lcp -> lcd_sb);
|
||||
|
||||
if (lcp -> lcd_template) {
|
||||
m = lcp -> lcd_template;
|
||||
lcp -> lcd_template = NULL;
|
||||
} else {
|
||||
if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition ||
|
||||
lcp -> lcd_reset_condition)
|
||||
return (NULL);
|
||||
|
||||
if ((m = sb -> sb_mb) == 0)
|
||||
return (NULL);
|
||||
|
||||
sb -> sb_mb = m -> m_nextpkt;
|
||||
m->m_act = 0;
|
||||
for (n = m; n; n = n -> m_next)
|
||||
sbfree (sb, n);
|
||||
}
|
||||
return (m);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Computing Centre, University of British Columbia, 1984
|
||||
* Copyright (C) Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1990, 1992
|
||||
* Copyright (c) 1990, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by the
|
||||
* Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the the University of British Columbia and the Computer Science
|
||||
* Department (IV) of the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pk_timer.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: pk_timer.c,v 1.2 1994/08/02 07:47:44 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netccitt/x25.h>
|
||||
#include <netccitt/pk.h>
|
||||
#include <netccitt/pk_var.h>
|
||||
|
||||
/*
|
||||
* Various timer values. They can be adjusted
|
||||
* by patching the binary with adb if necessary.
|
||||
*/
|
||||
int pk_t20 = 18 * PR_SLOWHZ; /* restart timer */
|
||||
int pk_t21 = 20 * PR_SLOWHZ; /* call timer */
|
||||
/* XXX pk_t22 is never used */
|
||||
int pk_t22 = 18 * PR_SLOWHZ; /* reset timer */
|
||||
int pk_t23 = 18 * PR_SLOWHZ; /* clear timer */
|
||||
|
||||
pk_timer ()
|
||||
{
|
||||
register struct pkcb *pkp;
|
||||
register struct pklcd *lcp, **pp;
|
||||
register int lcns_jammed, cant_restart;
|
||||
|
||||
FOR_ALL_PKCBS(pkp) {
|
||||
switch (pkp -> pk_state) {
|
||||
case DTE_SENT_RESTART:
|
||||
lcp = pkp -> pk_chan[0];
|
||||
/*
|
||||
* If restart failures are common, a link level
|
||||
* reset should be initiated here.
|
||||
*/
|
||||
if (lcp -> lcd_timer && --lcp -> lcd_timer == 0) {
|
||||
pk_message (0, pkp -> pk_xcp,
|
||||
"packet level restart failed");
|
||||
pkp -> pk_state = DTE_WAITING;
|
||||
}
|
||||
break;
|
||||
|
||||
case DTE_READY:
|
||||
lcns_jammed = cant_restart = 0;
|
||||
for (pp = &pkp -> pk_chan[1]; pp <= &pkp -> pk_chan[pkp -> pk_maxlcn]; pp++) {
|
||||
if ((lcp = *pp) == 0)
|
||||
continue;
|
||||
switch (lcp -> lcd_state) {
|
||||
case SENT_CALL:
|
||||
if (--lcp -> lcd_timer == 0) {
|
||||
if (lcp -> lcd_so)
|
||||
lcp -> lcd_so -> so_error = ETIMEDOUT;
|
||||
pk_clear (lcp, 49, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SENT_CLEAR:
|
||||
if (lcp -> lcd_retry >= 3)
|
||||
lcns_jammed++;
|
||||
else
|
||||
if (--lcp -> lcd_timer == 0)
|
||||
pk_clear (lcp, 50, 1);
|
||||
break;
|
||||
|
||||
case DATA_TRANSFER: /* lcn active */
|
||||
cant_restart++;
|
||||
break;
|
||||
|
||||
case LCN_ZOMBIE: /* zombie state */
|
||||
pk_freelcd (lcp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lcns_jammed > pkp -> pk_maxlcn / 2 && cant_restart == 0) {
|
||||
pk_message (0, pkp -> pk_xcp, "%d lcns jammed: attempting restart", lcns_jammed);
|
||||
pk_restart (pkp, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,605 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (C) Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1992
|
||||
* Copyright (c) 1991, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by the
|
||||
* Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the the University of British Columbia and the Computer Science
|
||||
* Department (IV) of the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pk_usrreq.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: pk_usrreq.c,v 1.2 1994/08/02 07:47:46 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netccitt/x25.h>
|
||||
#include <netccitt/pk.h>
|
||||
#include <netccitt/pk_var.h>
|
||||
|
||||
static old_to_new();
|
||||
static new_to_old();
|
||||
/*
|
||||
*
|
||||
* X.25 Packet level protocol interface to socket abstraction.
|
||||
*
|
||||
* Process an X.25 user request on a logical channel. If this is a send
|
||||
* request then m is the mbuf chain of the send data. If this is a timer
|
||||
* expiration (called from the software clock routine) them timertype is
|
||||
* the particular timer.
|
||||
*
|
||||
*/
|
||||
|
||||
pk_usrreq (so, req, m, nam, control)
|
||||
struct socket *so;
|
||||
int req;
|
||||
register struct mbuf *m, *nam;
|
||||
struct mbuf *control;
|
||||
{
|
||||
register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
|
||||
register int error = 0;
|
||||
|
||||
if (req == PRU_CONTROL)
|
||||
return (pk_control (so, (int)m, (caddr_t)nam,
|
||||
(struct ifnet *)control));
|
||||
if (control && control -> m_len) {
|
||||
error = EINVAL;
|
||||
goto release;
|
||||
}
|
||||
if (lcp == NULL && req != PRU_ATTACH) {
|
||||
error = EINVAL;
|
||||
goto release;
|
||||
}
|
||||
|
||||
/*
|
||||
pk_trace (pkcbhead, TR_USER, (struct pklcd *)0,
|
||||
req, (struct x25_packet *)0);
|
||||
*/
|
||||
|
||||
switch (req) {
|
||||
/*
|
||||
* X.25 attaches to socket via PRU_ATTACH and allocates a logical
|
||||
* channel descriptor. If the socket is to receive connections,
|
||||
* then the LISTEN state is entered.
|
||||
*/
|
||||
case PRU_ATTACH:
|
||||
if (lcp) {
|
||||
error = EISCONN;
|
||||
/* Socket already connected. */
|
||||
break;
|
||||
}
|
||||
lcp = pk_attach (so);
|
||||
if (lcp == 0)
|
||||
error = ENOBUFS;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Detach a logical channel from the socket. If the state of the
|
||||
* channel is embryonic, simply discard it. Otherwise we have to
|
||||
* initiate a PRU_DISCONNECT which will finish later.
|
||||
*/
|
||||
case PRU_DETACH:
|
||||
pk_disconnect (lcp);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Give the socket an address.
|
||||
*/
|
||||
case PRU_BIND:
|
||||
if (nam -> m_len == sizeof (struct x25_sockaddr))
|
||||
old_to_new (nam);
|
||||
error = pk_bind (lcp, nam);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Prepare to accept connections.
|
||||
*/
|
||||
case PRU_LISTEN:
|
||||
error = pk_listen (lcp);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL
|
||||
* and mark the socket as connecting. Set timer waiting for
|
||||
* CALL ACCEPT or CLEAR.
|
||||
*/
|
||||
case PRU_CONNECT:
|
||||
if (nam -> m_len == sizeof (struct x25_sockaddr))
|
||||
old_to_new (nam);
|
||||
if (pk_checksockaddr (nam))
|
||||
return (EINVAL);
|
||||
error = pk_connect (lcp, mtod (nam, struct sockaddr_x25 *));
|
||||
break;
|
||||
|
||||
/*
|
||||
* Initiate a disconnect to peer entity via a CLEAR REQUEST packet.
|
||||
* The socket will be disconnected when we receive a confirmation
|
||||
* or a clear collision.
|
||||
*/
|
||||
case PRU_DISCONNECT:
|
||||
pk_disconnect (lcp);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Accept an INCOMING CALL. Most of the work has already been done
|
||||
* by pk_input. Just return the callers address to the user.
|
||||
*/
|
||||
case PRU_ACCEPT:
|
||||
if (lcp -> lcd_craddr == NULL)
|
||||
break;
|
||||
bcopy ((caddr_t)lcp -> lcd_craddr, mtod (nam, caddr_t),
|
||||
sizeof (struct sockaddr_x25));
|
||||
nam -> m_len = sizeof (struct sockaddr_x25);
|
||||
if (lcp -> lcd_flags & X25_OLDSOCKADDR)
|
||||
new_to_old (nam);
|
||||
break;
|
||||
|
||||
/*
|
||||
* After a receive, we should send a RR.
|
||||
*/
|
||||
case PRU_RCVD:
|
||||
pk_flowcontrol (lcp, /*sbspace (&so -> so_rcv) <= */ 0, 1);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Send INTERRUPT packet.
|
||||
*/
|
||||
case PRU_SENDOOB:
|
||||
if (m == 0) {
|
||||
MGETHDR(m, M_WAITOK, MT_OOBDATA);
|
||||
m -> m_pkthdr.len = m -> m_len = 1;
|
||||
*mtod (m, octet *) = 0;
|
||||
}
|
||||
if (m -> m_pkthdr.len > 32) {
|
||||
m_freem (m);
|
||||
error = EMSGSIZE;
|
||||
break;
|
||||
}
|
||||
MCHTYPE(m, MT_OOBDATA);
|
||||
/* FALLTHROUGH */
|
||||
|
||||
/*
|
||||
* Do send by placing data on the socket output queue.
|
||||
*/
|
||||
case PRU_SEND:
|
||||
if (control) {
|
||||
register struct cmsghdr *ch = mtod (m, struct cmsghdr *);
|
||||
control -> m_len -= sizeof (*ch);
|
||||
control -> m_data += sizeof (*ch);
|
||||
error = pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level,
|
||||
ch -> cmsg_type, &control);
|
||||
}
|
||||
if (error == 0 && m)
|
||||
error = pk_send (lcp, m);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Abort a virtual circuit. For example all completed calls
|
||||
* waiting acceptance.
|
||||
*/
|
||||
case PRU_ABORT:
|
||||
pk_disconnect (lcp);
|
||||
break;
|
||||
|
||||
/* Begin unimplemented hooks. */
|
||||
|
||||
case PRU_SHUTDOWN:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
|
||||
case PRU_CONTROL:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
|
||||
case PRU_SENSE:
|
||||
#ifdef BSD4_3
|
||||
((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat;
|
||||
#else
|
||||
error = EOPNOTSUPP;
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* End unimplemented hooks. */
|
||||
|
||||
case PRU_SOCKADDR:
|
||||
if (lcp -> lcd_ceaddr == 0)
|
||||
return (EADDRNOTAVAIL);
|
||||
nam -> m_len = sizeof (struct sockaddr_x25);
|
||||
bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t),
|
||||
sizeof (struct sockaddr_x25));
|
||||
if (lcp -> lcd_flags & X25_OLDSOCKADDR)
|
||||
new_to_old (nam);
|
||||
break;
|
||||
|
||||
case PRU_PEERADDR:
|
||||
if (lcp -> lcd_state != DATA_TRANSFER)
|
||||
return (ENOTCONN);
|
||||
nam -> m_len = sizeof (struct sockaddr_x25);
|
||||
bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr :
|
||||
(caddr_t)lcp -> lcd_ceaddr,
|
||||
mtod (nam, caddr_t), sizeof (struct sockaddr_x25));
|
||||
if (lcp -> lcd_flags & X25_OLDSOCKADDR)
|
||||
new_to_old (nam);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Receive INTERRUPT packet.
|
||||
*/
|
||||
case PRU_RCVOOB:
|
||||
if (so -> so_options & SO_OOBINLINE) {
|
||||
register struct mbuf *n = so -> so_rcv.sb_mb;
|
||||
if (n && n -> m_type == MT_OOBDATA) {
|
||||
unsigned len = n -> m_pkthdr.len;
|
||||
so -> so_rcv.sb_mb = n -> m_nextpkt;
|
||||
if (len != n -> m_len &&
|
||||
(n = m_pullup (n, len)) == 0)
|
||||
break;
|
||||
m -> m_len = len;
|
||||
bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len);
|
||||
m_freem (n);
|
||||
}
|
||||
break;
|
||||
}
|
||||
m -> m_len = 1;
|
||||
*mtod (m, char *) = lcp -> lcd_intrdata;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic ("pk_usrreq");
|
||||
}
|
||||
release:
|
||||
if (control != NULL)
|
||||
m_freem (control);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* If you want to use UBC X.25 level 3 in conjunction with some
|
||||
* other X.25 level 2 driver, have the ifp -> if_ioctl routine
|
||||
* assign pk_start to ia -> ia_start when called with SIOCSIFCONF_X25.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
pk_start (lcp)
|
||||
register struct pklcd *lcp;
|
||||
{
|
||||
pk_output (lcp);
|
||||
return (0); /* XXX pk_output should return a value */
|
||||
}
|
||||
|
||||
#ifndef _offsetof
|
||||
#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
|
||||
#endif
|
||||
struct sockaddr_x25 pk_sockmask = {
|
||||
_offsetof(struct sockaddr_x25, x25_addr[0]), /* x25_len */
|
||||
0, /* x25_family */
|
||||
-1, /* x25_net id */
|
||||
};
|
||||
|
||||
/*ARGSUSED*/
|
||||
pk_control (so, cmd, data, ifp)
|
||||
struct socket *so;
|
||||
int cmd;
|
||||
caddr_t data;
|
||||
register struct ifnet *ifp;
|
||||
{
|
||||
register struct ifreq_x25 *ifr = (struct ifreq_x25 *)data;
|
||||
register struct ifaddr *ifa = 0;
|
||||
register struct x25_ifaddr *ia = 0;
|
||||
struct pklcd *dev_lcp = 0;
|
||||
int error, s, old_maxlcn;
|
||||
unsigned n;
|
||||
|
||||
/*
|
||||
* Find address for this interface, if it exists.
|
||||
*/
|
||||
if (ifp)
|
||||
for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next)
|
||||
if (ifa -> ifa_addr -> sa_family == AF_CCITT)
|
||||
break;
|
||||
|
||||
ia = (struct x25_ifaddr *)ifa;
|
||||
switch (cmd) {
|
||||
case SIOCGIFCONF_X25:
|
||||
if (ifa == 0)
|
||||
return (EADDRNOTAVAIL);
|
||||
ifr -> ifr_xc = ia -> ia_xc;
|
||||
return (0);
|
||||
|
||||
case SIOCSIFCONF_X25:
|
||||
if ((so->so_state & SS_PRIV) == 0)
|
||||
return (EPERM);
|
||||
if (ifp == 0)
|
||||
panic ("pk_control");
|
||||
if (ifa == (struct ifaddr *)0) {
|
||||
register struct mbuf *m;
|
||||
|
||||
MALLOC(ia, struct x25_ifaddr *, sizeof (*ia),
|
||||
M_IFADDR, M_WAITOK);
|
||||
if (ia == 0)
|
||||
return (ENOBUFS);
|
||||
bzero ((caddr_t)ia, sizeof (*ia));
|
||||
if (ifa = ifp -> if_addrlist) {
|
||||
for ( ; ifa -> ifa_next; ifa = ifa -> ifa_next)
|
||||
;
|
||||
ifa -> ifa_next = &ia -> ia_ifa;
|
||||
} else
|
||||
ifp -> if_addrlist = &ia -> ia_ifa;
|
||||
ifa = &ia -> ia_ifa;
|
||||
ifa -> ifa_netmask = (struct sockaddr *)&pk_sockmask;
|
||||
ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr;
|
||||
ifa -> ifa_dstaddr = (struct sockaddr *)&ia -> ia_dstaddr; /* XXX */
|
||||
ia -> ia_ifp = ifp;
|
||||
ia -> ia_dstaddr.x25_family = AF_CCITT;
|
||||
ia -> ia_dstaddr.x25_len = pk_sockmask.x25_len;
|
||||
} else if (ISISO8802(ifp) == 0) {
|
||||
rtinit (ifa, (int)RTM_DELETE, 0);
|
||||
}
|
||||
old_maxlcn = ia -> ia_maxlcn;
|
||||
ia -> ia_xc = ifr -> ifr_xc;
|
||||
ia -> ia_dstaddr.x25_net = ia -> ia_xc.xc_addr.x25_net;
|
||||
if (ia -> ia_maxlcn != old_maxlcn && old_maxlcn != 0) {
|
||||
/* VERY messy XXX */
|
||||
register struct pkcb *pkp;
|
||||
FOR_ALL_PKCBS(pkp)
|
||||
if (pkp -> pk_ia == ia)
|
||||
pk_resize (pkp);
|
||||
}
|
||||
/*
|
||||
* Give the interface a chance to initialize if this
|
||||
p * is its first address, and to validate the address.
|
||||
*/
|
||||
ia -> ia_start = pk_start;
|
||||
s = splimp();
|
||||
if (ifp -> if_ioctl)
|
||||
error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25,
|
||||
(caddr_t) ifa);
|
||||
if (error)
|
||||
ifp -> if_flags &= ~IFF_UP;
|
||||
else if (ISISO8802(ifp) == 0)
|
||||
error = rtinit (ifa, (int)RTM_ADD, RTF_UP);
|
||||
splx (s);
|
||||
return (error);
|
||||
|
||||
default:
|
||||
if (ifp == 0 || ifp -> if_ioctl == 0)
|
||||
return (EOPNOTSUPP);
|
||||
return ((*ifp -> if_ioctl)(ifp, cmd, data));
|
||||
}
|
||||
}
|
||||
|
||||
pk_ctloutput (cmd, so, level, optname, mp)
|
||||
struct socket *so;
|
||||
struct mbuf **mp;
|
||||
int cmd, level, optname;
|
||||
{
|
||||
register struct mbuf *m = *mp;
|
||||
register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
|
||||
int error = EOPNOTSUPP;
|
||||
|
||||
if (m == 0)
|
||||
return (EINVAL);
|
||||
if (cmd == PRCO_SETOPT) switch (optname) {
|
||||
case PK_FACILITIES:
|
||||
if (m == 0)
|
||||
return (EINVAL);
|
||||
lcp -> lcd_facilities = m;
|
||||
*mp = 0;
|
||||
return (0);
|
||||
|
||||
case PK_ACCTFILE:
|
||||
if ((so->so_state & SS_PRIV) == 0)
|
||||
error = EPERM;
|
||||
else if (m -> m_len)
|
||||
error = pk_accton (mtod (m, char *));
|
||||
else
|
||||
error = pk_accton ((char *)0);
|
||||
break;
|
||||
|
||||
case PK_RTATTACH:
|
||||
error = pk_rtattach (so, m);
|
||||
break;
|
||||
|
||||
case PK_PRLISTEN:
|
||||
error = pk_user_protolisten (mtod (m, u_char *));
|
||||
}
|
||||
if (*mp) {
|
||||
(void) m_freem (*mp);
|
||||
*mp = 0;
|
||||
}
|
||||
return (error);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do an in-place conversion of an "old style"
|
||||
* socket address to the new style
|
||||
*/
|
||||
|
||||
static
|
||||
old_to_new (m)
|
||||
register struct mbuf *m;
|
||||
{
|
||||
register struct x25_sockaddr *oldp;
|
||||
register struct sockaddr_x25 *newp;
|
||||
register char *ocp, *ncp;
|
||||
struct sockaddr_x25 new;
|
||||
|
||||
oldp = mtod (m, struct x25_sockaddr *);
|
||||
newp = &new;
|
||||
bzero ((caddr_t)newp, sizeof (*newp));
|
||||
|
||||
newp -> x25_family = AF_CCITT;
|
||||
newp -> x25_len = sizeof(*newp);
|
||||
newp -> x25_opts.op_flags = (oldp -> xaddr_facilities & X25_REVERSE_CHARGE)
|
||||
| X25_MQBIT | X25_OLDSOCKADDR;
|
||||
if (oldp -> xaddr_facilities & XS_HIPRIO) /* Datapac specific */
|
||||
newp -> x25_opts.op_psize = X25_PS128;
|
||||
bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr,
|
||||
(unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1));
|
||||
if (bcmp ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4) != 0) {
|
||||
bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4);
|
||||
newp -> x25_udlen = 4;
|
||||
}
|
||||
ocp = (caddr_t)oldp -> xaddr_userdata;
|
||||
ncp = newp -> x25_udata + 4;
|
||||
while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) {
|
||||
if (newp -> x25_udlen == 0)
|
||||
newp -> x25_udlen = 4;
|
||||
*ncp++ = *ocp++;
|
||||
newp -> x25_udlen++;
|
||||
}
|
||||
bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp));
|
||||
m -> m_len = sizeof (*newp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an in-place conversion of a new style
|
||||
* socket address to the old style
|
||||
*/
|
||||
|
||||
static
|
||||
new_to_old (m)
|
||||
register struct mbuf *m;
|
||||
{
|
||||
register struct x25_sockaddr *oldp;
|
||||
register struct sockaddr_x25 *newp;
|
||||
register char *ocp, *ncp;
|
||||
struct x25_sockaddr old;
|
||||
|
||||
oldp = &old;
|
||||
newp = mtod (m, struct sockaddr_x25 *);
|
||||
bzero ((caddr_t)oldp, sizeof (*oldp));
|
||||
|
||||
oldp -> xaddr_facilities = newp -> x25_opts.op_flags & X25_REVERSE_CHARGE;
|
||||
if (newp -> x25_opts.op_psize == X25_PS128)
|
||||
oldp -> xaddr_facilities |= XS_HIPRIO; /* Datapac specific */
|
||||
ocp = (char *)oldp -> xaddr_addr;
|
||||
ncp = newp -> x25_addr;
|
||||
while (*ncp) {
|
||||
*ocp++ = *ncp++;
|
||||
oldp -> xaddr_len++;
|
||||
}
|
||||
|
||||
bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4);
|
||||
if (newp -> x25_udlen > 4)
|
||||
bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata,
|
||||
(unsigned)(newp -> x25_udlen - 4));
|
||||
|
||||
bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp));
|
||||
m -> m_len = sizeof (*oldp);
|
||||
}
|
||||
|
||||
|
||||
pk_checksockaddr (m)
|
||||
struct mbuf *m;
|
||||
{
|
||||
register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *);
|
||||
register char *cp;
|
||||
|
||||
if (m -> m_len != sizeof (struct sockaddr_x25))
|
||||
return (1);
|
||||
if (sa -> x25_family != AF_CCITT ||
|
||||
sa -> x25_udlen > sizeof (sa -> x25_udata))
|
||||
return (1);
|
||||
for (cp = sa -> x25_addr; *cp; cp++) {
|
||||
if (*cp < '0' || *cp > '9' ||
|
||||
cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1])
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
pk_send (lcp, m)
|
||||
struct pklcd *lcp;
|
||||
register struct mbuf *m;
|
||||
{
|
||||
int mqbit = 0, error = 0;
|
||||
register struct x25_packet *xp;
|
||||
register struct socket *so;
|
||||
|
||||
if (m -> m_type == MT_OOBDATA) {
|
||||
if (lcp -> lcd_intrconf_pending)
|
||||
error = ETOOMANYREFS;
|
||||
if (m -> m_pkthdr.len > 32)
|
||||
error = EMSGSIZE;
|
||||
M_PREPEND(m, PKHEADERLN, M_WAITOK);
|
||||
if (m == 0 || error)
|
||||
goto bad;
|
||||
*(mtod (m, octet *)) = 0;
|
||||
xp = mtod (m, struct x25_packet *);
|
||||
X25SBITS(xp -> bits, fmt_identifier, 1);
|
||||
xp -> packet_type = X25_INTERRUPT;
|
||||
SET_LCN(xp, lcp -> lcd_lcn);
|
||||
sbinsertoob ( (so = lcp -> lcd_so) ?
|
||||
&so -> so_snd : &lcp -> lcd_sb, m);
|
||||
goto send;
|
||||
}
|
||||
/*
|
||||
* Application has elected (at call setup time) to prepend
|
||||
* a control byte to each packet written indicating m-bit
|
||||
* and q-bit status. Examine and then discard this byte.
|
||||
*/
|
||||
if (lcp -> lcd_flags & X25_MQBIT) {
|
||||
if (m -> m_len < 1) {
|
||||
m_freem (m);
|
||||
return (EMSGSIZE);
|
||||
}
|
||||
mqbit = *(mtod (m, u_char *));
|
||||
m -> m_len--;
|
||||
m -> m_data++;
|
||||
m -> m_pkthdr.len--;
|
||||
}
|
||||
error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1);
|
||||
send:
|
||||
if (error == 0 && lcp -> lcd_state == DATA_TRANSFER)
|
||||
lcp -> lcd_send (lcp); /* XXXXXXXXX fix pk_output!!! */
|
||||
return (error);
|
||||
bad:
|
||||
if (m)
|
||||
m_freem (m);
|
||||
return (error);
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Computing Centre, University of British Columbia, 1985
|
||||
* Copyright (C) Computer Science Department IV,
|
||||
* University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by the
|
||||
* Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the the University of British Columbia and the Computer Science
|
||||
* Department (IV) of the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pk_var.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: pk_var.h,v 1.7 1995/11/21 12:54:12 bde Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_PK_VAR_H_
|
||||
#define _NETCCITT_PK_VAR_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* X.25 Logical Channel Descriptor
|
||||
*
|
||||
*/
|
||||
|
||||
struct pklcd {
|
||||
struct pklcd_q {
|
||||
struct pklcd_q *q_forw; /* debugging chain */
|
||||
struct pklcd_q *q_back; /* debugging chain */
|
||||
} lcd_q;
|
||||
int (*lcd_upper) __P((struct pklcd *lcp, struct mbuf *m));
|
||||
/* switch to socket vs datagram vs ...*/
|
||||
caddr_t lcd_upnext; /* reference for lcd_upper() */
|
||||
int (*lcd_send) __P((struct pklcd *lcp));
|
||||
/* if X.25 front end, direct connect */
|
||||
caddr_t lcd_downnext; /* reference for lcd_send() */
|
||||
short lcd_lcn; /* Logical channel number */
|
||||
short lcd_state; /* Logical Channel state */
|
||||
short lcd_timer; /* Various timer values */
|
||||
short lcd_dg_timer; /* to reclaim idle datagram circuits */
|
||||
bool lcd_intrconf_pending; /* Interrupt confirmation pending */
|
||||
octet lcd_intrdata; /* Octet of incoming intr data */
|
||||
char lcd_retry; /* Timer retry count */
|
||||
char lcd_rsn; /* Seq no of last received packet */
|
||||
char lcd_ssn; /* Seq no of next packet to send */
|
||||
char lcd_output_window; /* Output flow control window */
|
||||
char lcd_input_window; /* Input flow control window */
|
||||
char lcd_last_transmitted_pr;/* Last Pr value transmitted */
|
||||
bool lcd_rnr_condition; /* Remote in busy condition */
|
||||
bool lcd_window_condition; /* Output window size exceeded */
|
||||
bool lcd_reset_condition; /* True, if waiting reset confirm */
|
||||
bool lcd_rxrnr_condition; /* True, if we have sent rnr */
|
||||
char lcd_packetsize; /* Maximum packet size */
|
||||
char lcd_windowsize; /* Window size - both directions */
|
||||
octet lcd_closed_user_group; /* Closed user group specification */
|
||||
char lcd_flags; /* copy of sockaddr_x25 op_flags */
|
||||
struct mbuf *lcd_facilities; /* user supplied facilities for cr */
|
||||
struct mbuf *lcd_template; /* Address of response packet */
|
||||
struct socket *lcd_so; /* Socket addr for connection */
|
||||
struct sockaddr_x25 *lcd_craddr;/* Calling address pointer */
|
||||
struct sockaddr_x25 *lcd_ceaddr;/* Called address pointer */
|
||||
time_t lcd_stime; /* time circuit established */
|
||||
long lcd_txcnt; /* Data packet transmit count */
|
||||
long lcd_rxcnt; /* Data packet receive count */
|
||||
short lcd_intrcnt; /* Interrupt packet transmit count */
|
||||
struct pklcd *lcd_listen; /* Next lcd on listen queue */
|
||||
struct pkcb *lcd_pkp; /* Network this lcd is attached to */
|
||||
struct mbuf *lcd_cps; /* Complete Packet Sequence reassembly*/
|
||||
long lcd_cpsmax; /* Max length for CPS */
|
||||
struct sockaddr_x25 lcd_faddr; /* Remote Address (Calling) */
|
||||
struct sockaddr_x25 lcd_laddr; /* Local Address (Called) */
|
||||
struct sockbuf lcd_sb; /* alternate for datagram service */
|
||||
};
|
||||
|
||||
struct dll_ctlinfo;
|
||||
|
||||
/*
|
||||
* Per network information, allocated dynamically
|
||||
* when a new network is configured.
|
||||
*/
|
||||
|
||||
struct pkcb {
|
||||
struct pkcb_q {
|
||||
struct pkcb_q *q_forw;
|
||||
struct pkcb_q *q_backw;
|
||||
} pk_q;
|
||||
short pk_state; /* packet level status */
|
||||
short pk_maxlcn; /* local copy of xc_maxlcn */
|
||||
int (*pk_lloutput) __P((caddr_t, struct mbuf *, struct rtentry *));
|
||||
/* link level output procedure */
|
||||
caddr_t (*pk_llctlinput) __P((int, int, struct dll_ctlinfo *));
|
||||
/* link level ctloutput procedure */
|
||||
caddr_t pk_llnext; /* handle for next level down */
|
||||
struct x25config *pk_xcp; /* network specific configuration */
|
||||
struct x25_ifaddr *pk_ia; /* backpointer to ifaddr */
|
||||
struct pklcd **pk_chan; /* actual size == xc_maxlcn+1 */
|
||||
short pk_dxerole; /* DXE role of PLE over LLC2 */
|
||||
short pk_restartcolls; /* counting RESTART collisions til resolved */
|
||||
struct rtentry *pk_rt; /* back pointer to route */
|
||||
struct rtentry *pk_llrt; /* pointer to reverse mapping */
|
||||
u_short pk_refcount; /* ref count */
|
||||
};
|
||||
|
||||
#define FOR_ALL_PKCBS(p) for((p) = (struct pkcb *)(pkcb_q.q_forw); \
|
||||
(pkcb_q.q_forw != &pkcb_q) && ((struct pkcb_q *)(p) != &pkcb_q); \
|
||||
(p) = (struct pkcb *)((p) -> pk_q.q_forw))
|
||||
|
||||
#define PQEMPTY (pkcb_q.q_forw == &pkcb_q)
|
||||
|
||||
/*
|
||||
* Interface address, x25 version. Exactly one of these structures is
|
||||
* allocated for each interface with an x25 address.
|
||||
*
|
||||
* The ifaddr structure contains the protocol-independent part
|
||||
* of the structure, and is assumed to be first.
|
||||
*/
|
||||
struct x25_ifaddr {
|
||||
struct ifaddr ia_ifa; /* protocol-independent info */
|
||||
#define ia_ifp ia_ifa.ifa_ifp
|
||||
#define ia_flags ia_ifa.ifa_flags
|
||||
struct x25config ia_xc; /* network specific configuration */
|
||||
struct pkcb *ia_pkcb;
|
||||
#define ia_maxlcn ia_xc.xc_maxlcn
|
||||
int (*ia_start) __P((struct pklcd *lcp));
|
||||
/* connect, confirm method */
|
||||
struct sockaddr_x25 ia_dstaddr; /* reserve space for route dst */
|
||||
};
|
||||
|
||||
/*
|
||||
* ``Link-Level'' extension to Routing Entry for upper level
|
||||
* packet switching via X.25 virtual circuits.
|
||||
*/
|
||||
struct llinfo_x25 {
|
||||
struct llinfo_x25 *lx_next; /* chain together in linked list */
|
||||
struct llinfo_x25 *lx_prev; /* chain together in linked list */
|
||||
struct rtentry *lx_rt; /* back pointer to route */
|
||||
struct pklcd *lx_lcd; /* local connection block */
|
||||
struct x25_ifaddr *lx_ia; /* may not be same as rt_ifa */
|
||||
int lx_state; /* can't trust lcd->lcd_state */
|
||||
int lx_flags;
|
||||
int lx_timer; /* for idle timeout */
|
||||
int lx_family; /* for dispatch */
|
||||
};
|
||||
|
||||
/* States for lx_state */
|
||||
#define LXS_NEWBORN 0
|
||||
#define LXS_RESOLVING 1
|
||||
#define LXS_FREE 2
|
||||
#define LXS_CONNECTING 3
|
||||
#define LXS_CONNECTED 4
|
||||
#define LXS_DISCONNECTING 5
|
||||
#define LXS_LISTENING 6
|
||||
|
||||
/* flags */
|
||||
#define LXF_VALID 0x1 /* Circuit is live, etc. */
|
||||
#define LXF_RTHELD 0x2 /* this lcb references rtentry */
|
||||
#define LXF_LISTEN 0x4 /* accepting incoming calls */
|
||||
|
||||
/*
|
||||
* Definitions for accessing bitfields/bitslices inside X.25 structs
|
||||
*/
|
||||
|
||||
|
||||
struct x25bitslice {
|
||||
unsigned int bs_mask;
|
||||
unsigned int bs_shift;
|
||||
};
|
||||
|
||||
#define calling_addrlen 0
|
||||
#define called_addrlen 1
|
||||
#define q_bit 2
|
||||
#define d_bit 3
|
||||
#define fmt_identifier 4
|
||||
#define lc_group_number 1
|
||||
#define p_r 5
|
||||
#define m_bit 6
|
||||
#define p_s 7
|
||||
#define zilch 8
|
||||
|
||||
#define X25GBITS(Arg, Index) (((Arg) & x25_bitslice[(Index)].bs_mask) >> x25_bitslice[(Index)].bs_shift)
|
||||
#define X25SBITS(Arg, Index, Val) (Arg) |= (((Val) << x25_bitslice[(Index)].bs_shift) & x25_bitslice[(Index)].bs_mask)
|
||||
#define X25CSBITS(Arg, Index, Val) (Arg) = (((Val) << x25_bitslice[(Index)].bs_shift) & x25_bitslice[(Index)].bs_mask)
|
||||
|
||||
extern struct x25bitslice x25_bitslice[];
|
||||
|
||||
|
||||
#define ISOFIFTTYPE(i,t) ((i)->if_type == (t))
|
||||
#define ISISO8802(i) ((ISOFIFTTYPE(i, IFT_ETHER) || \
|
||||
ISOFIFTTYPE(i, IFT_ISO88023) || \
|
||||
ISOFIFTTYPE(i, IFT_ISO88024) || \
|
||||
ISOFIFTTYPE(i, IFT_ISO88025) || \
|
||||
ISOFIFTTYPE(i, IFT_ISO88026) || \
|
||||
ISOFIFTTYPE(i, IFT_P10) || \
|
||||
ISOFIFTTYPE(i, IFT_P80) || \
|
||||
ISOFIFTTYPE(i, IFT_FDDI)))
|
||||
|
||||
/*
|
||||
* miscellaneous debugging info
|
||||
*/
|
||||
struct mbuf_cache {
|
||||
int mbc_size;
|
||||
int mbc_num;
|
||||
int mbc_oldsize;
|
||||
struct mbuf **mbc_cache;
|
||||
};
|
||||
|
||||
#if defined(KERNEL) && defined(CCITT)
|
||||
extern struct pkcb_q pkcb_q;
|
||||
extern struct pklcd *pk_listenhead;
|
||||
void ccittintr __P((void));
|
||||
struct pklcd *pk_attach __P((struct socket *so));
|
||||
|
||||
extern char *pk_name[], *pk_state[];
|
||||
extern int pk_t20, pk_t21, pk_t22, pk_t23;
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* University of Erlangen-Nuremberg, Germany, 1992
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by the
|
||||
* Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the the University of British Columbia and the Computer Science
|
||||
* Department (IV) of the University of Erlangen-Nuremberg, Germany.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)x25.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: x25.h,v 1.3 1994/08/21 05:44:11 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_X25_H_
|
||||
#define _NETCCITT_X25_H_
|
||||
|
||||
#ifdef KERNEL
|
||||
#define PRC_IFUP 3
|
||||
#define PRC_LINKUP 4
|
||||
#define PRC_LINKDOWN 5
|
||||
#define PRC_LINKRESET 6
|
||||
#define PRC_LINKDONTCOPY 7
|
||||
#ifndef PRC_DISCONNECT_REQUEST
|
||||
#define PRC_DISCONNECT_REQUEST 10
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CCITTPROTO_HDLC 1
|
||||
#define CCITTPROTO_X25 2 /* packet level protocol */
|
||||
#define IEEEPROTO_802LLC 3 /* doesn't belong here */
|
||||
|
||||
#define HDLCPROTO_LAP 1
|
||||
#define HDLCPROTO_LAPB 2
|
||||
#define HDLCPROTO_UNSET 3
|
||||
#define HDLCPROTO_LAPD 4
|
||||
|
||||
/* socket options */
|
||||
#define PK_ACCTFILE 1 /* use level = CCITTPROTO_X25 */
|
||||
#define PK_FACILITIES 2 /* use level = CCITTPROTO_X25 */
|
||||
#define PK_RTATTACH 3 /* use level = CCITTPROTO_X25 */
|
||||
#define PK_PRLISTEN 4 /* use level = CCITTPROTO_X25 */
|
||||
|
||||
#define MAX_FACILITIES 109 /* maximum size for facilities */
|
||||
|
||||
/*
|
||||
* X.25 Socket address structure. It contains the X.121 or variation of
|
||||
* X.121, facilities information, higher level protocol value (first four
|
||||
* bytes of the User Data field), and the last 12 characters of the User
|
||||
* Data field.
|
||||
*/
|
||||
|
||||
struct x25_sockaddr { /* obsolete - use sockaddr_x25 */
|
||||
short xaddr_len; /* Length of xaddr_addr. */
|
||||
u_char xaddr_addr[15]; /* Network dependent or X.121 address. */
|
||||
u_char xaddr_facilities; /* Facilities information. */
|
||||
#define XS_REVERSE_CHARGE 0x01
|
||||
#define XS_HIPRIO 0x02
|
||||
u_char xaddr_proto[4]; /* Protocol ID (4 bytes of user data). */
|
||||
u_char xaddr_userdata[12]; /* Remaining User data field. */
|
||||
};
|
||||
|
||||
/*
|
||||
* X.25 Socket address structure. It contains the network id, X.121
|
||||
* address, facilities information, higher level protocol value (first four
|
||||
* bytes of the User Data field), and up to 12 characters of User Data.
|
||||
*/
|
||||
|
||||
struct sockaddr_x25 {
|
||||
u_char x25_len;
|
||||
u_char x25_family; /* must be AF_CCITT */
|
||||
short x25_net; /* network id code (usually a dnic) */
|
||||
char x25_addr[16]; /* X.121 address (null terminated) */
|
||||
struct x25opts {
|
||||
char op_flags; /* miscellaneous options */
|
||||
/* pk_var.h defines other lcd_flags */
|
||||
#define X25_REVERSE_CHARGE 0x01 /* remote DTE pays for call */
|
||||
#define X25_DBIT 0x02 /* not yet supported */
|
||||
#define X25_MQBIT 0x04 /* prepend M&Q bit status byte to packet data */
|
||||
#define X25_OLDSOCKADDR 0x08 /* uses old sockaddr structure */
|
||||
#define X25_DG_CIRCUIT 0x10 /* lcd_flag: used for datagrams */
|
||||
#define X25_DG_ROUTING 0x20 /* lcd_flag: peer addr not yet known */
|
||||
#define X25_MBS_HOLD 0x40 /* lcd_flag: collect m-bit sequences */
|
||||
char op_psize; /* requested packet size */
|
||||
#define X25_PS128 7
|
||||
#define X25_PS256 8
|
||||
#define X25_PS512 9
|
||||
char op_wsize; /* window size (1 .. 7) */
|
||||
char op_speed; /* throughput class */
|
||||
} x25_opts;
|
||||
short x25_udlen; /* user data field length */
|
||||
char x25_udata[16]; /* user data field */
|
||||
};
|
||||
|
||||
/*
|
||||
* network configuration info
|
||||
* this structure must be 16 bytes long
|
||||
*/
|
||||
|
||||
struct x25config {
|
||||
struct sockaddr_x25 xc_addr;
|
||||
/* link level parameters */
|
||||
u_short xc_lproto:4, /* link level protocol eg. CCITTPROTO_HDLC */
|
||||
xc_lptype:4, /* protocol type eg. HDLCPROTO_LAPB */
|
||||
xc_ltrace:1, /* link level tracing flag */
|
||||
xc_lwsize:7; /* link level window size */
|
||||
u_short xc_lxidxchg:1, /* link level XID exchange flag - NOT YET */
|
||||
/* packet level parameters */
|
||||
xc_rsvd1:2,
|
||||
xc_pwsize:3, /* default window size */
|
||||
xc_psize:4, /* default packet size 7=128, 8=256, ... */
|
||||
xc_type:3, /* network type */
|
||||
#define X25_1976 0
|
||||
#define X25_1980 1
|
||||
#define X25_1984 2
|
||||
#define X25_DDN 3
|
||||
#define X25_BASIC 4
|
||||
xc_ptrace:1, /* packet level tracing flag */
|
||||
xc_nodnic:1, /* remove our dnic when calling on net */
|
||||
xc_prepnd0:1; /* prepend 0 when making offnet calls */
|
||||
u_short xc_maxlcn; /* max logical channels */
|
||||
u_short xc_dg_idletimo; /* timeout for idle datagram circuits. */
|
||||
};
|
||||
|
||||
#ifdef IFNAMSIZ
|
||||
struct ifreq_x25 {
|
||||
char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
|
||||
struct x25config ifr_xc;
|
||||
};
|
||||
#define SIOCSIFCONF_X25 _IOW('i', 12, struct ifreq_x25) /* set ifnet config */
|
||||
#define SIOCGIFCONF_X25 _IOWR('i',13, struct ifreq_x25) /* get ifnet config */
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)x25acct.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: x25acct.h,v 1.2 1994/08/02 07:47:52 davidg Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_X25ACCT_H_
|
||||
#define _NETCCITT_X25ACCT_H_
|
||||
|
||||
/*
|
||||
* Format of X.25 accounting record written
|
||||
* to X25ACCTF whenever a circuit is closed.
|
||||
*/
|
||||
|
||||
#ifdef waterloo
|
||||
#define X25ACCTF "/usr/adm/logs/x25acct"
|
||||
#else
|
||||
#define X25ACCTF "/usr/adm/x25acct"
|
||||
#endif
|
||||
|
||||
struct x25acct {
|
||||
time_t x25acct_stime; /* start time */
|
||||
#ifdef waterloo
|
||||
u_long x25acct_etime; /* elapsed time (seconds) */
|
||||
#else
|
||||
u_short x25acct_etime; /* elapsed time (seconds) */
|
||||
#endif
|
||||
short x25acct_uid; /* user id */
|
||||
short x25acct_net; /* network id */
|
||||
u_short x25acct_psize:4, /* packet size */
|
||||
x25acct_addrlen:4, /* x25acct_addr length */
|
||||
x25acct_revcharge:1, /* reverse charging */
|
||||
x25acct_callin:1, /* incoming call */
|
||||
x25acct_unused:6;
|
||||
char x25acct_addr[8]; /* remote DTE address (in bcd) */
|
||||
char x25acct_udata[4]; /* protocol id */
|
||||
long x25acct_txcnt; /* packets transmitted */
|
||||
long x25acct_rxcnt; /* packets received */
|
||||
};
|
||||
|
||||
#endif
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) University of British Columbia, 1984
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Laboratory for Computation Vision and the Computer Science Department
|
||||
* of the University of British Columbia.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)x25err.h 8.1 (Berkeley) 6/10/93
|
||||
* $Id: x25err.h,v 1.3 1994/08/21 05:44:12 paul Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETCCITT_X25ERR_H_
|
||||
#define _NETCCITT_X25ERR_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* X.25 Reset and Clear errors and diagnostics. These values are
|
||||
* returned in the u_error field of the u structure.
|
||||
*
|
||||
*/
|
||||
|
||||
#define EXRESET 100 /* Reset: call reset */
|
||||
#define EXROUT 101 /* Reset: out of order */
|
||||
#define EXRRPE 102 /* Reset: remote procedure error */
|
||||
#define EXRLPE 103 /* Reset: local procedure error */
|
||||
#define EXRNCG 104 /* Reset: network congestion */
|
||||
|
||||
#define EXCLEAR 110 /* Clear: call cleared */
|
||||
#define EXCBUSY 111 /* Clear: number busy */
|
||||
#define EXCOUT 112 /* Clear: out of order */
|
||||
#define EXCRPE 113 /* Clear: remote procedure error */
|
||||
#define EXCRRC 114 /* Clear: collect call refused */
|
||||
#define EXCINV 115 /* Clear: invalid call */
|
||||
#define EXCAB 116 /* Clear: access barred */
|
||||
#define EXCLPE 117 /* Clear: local procedure error */
|
||||
#define EXCNCG 118 /* Clear: network congestion */
|
||||
#define EXCNOB 119 /* Clear: not obtainable */
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user