summaryrefslogtreecommitdiffstats
path: root/sys/netccitt/pk_llcsubr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netccitt/pk_llcsubr.c')
-rw-r--r--sys/netccitt/pk_llcsubr.c370
1 files changed, 370 insertions, 0 deletions
diff --git a/sys/netccitt/pk_llcsubr.c b/sys/netccitt/pk_llcsubr.c
new file mode 100644
index 0000000..7269fb2
--- /dev/null
+++ b/sys/netccitt/pk_llcsubr.c
@@ -0,0 +1,370 @@
+/*
+ * 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$
+ */
+
+#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);
+ 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)) == 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)) {
+ 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 */
OpenPOWER on IntegriCloud