summaryrefslogtreecommitdiffstats
path: root/sys/netatm/ipatm/ipatm_load.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netatm/ipatm/ipatm_load.c')
-rw-r--r--sys/netatm/ipatm/ipatm_load.c878
1 files changed, 878 insertions, 0 deletions
diff --git a/sys/netatm/ipatm/ipatm_load.c b/sys/netatm/ipatm/ipatm_load.c
new file mode 100644
index 0000000..8caa635
--- /dev/null
+++ b/sys/netatm/ipatm/ipatm_load.c
@@ -0,0 +1,878 @@
+/*
+ *
+ * ===================================
+ * HARP | Host ATM Research Platform
+ * ===================================
+ *
+ *
+ * This Host ATM Research Platform ("HARP") file (the "Software") is
+ * made available by Network Computing Services, Inc. ("NetworkCS")
+ * "AS IS". NetworkCS does not provide maintenance, improvements or
+ * support of any kind.
+ *
+ * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
+ * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
+ * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
+ * In no event shall NetworkCS be responsible for any damages, including
+ * but not limited to consequential damages, arising from or relating to
+ * any use of the Software or related support.
+ *
+ * Copyright 1994-1998 Network Computing Services, Inc.
+ *
+ * Copies of this Software may be made, however, the above copyright
+ * notice must be reproduced on all copies.
+ *
+ * @(#) $Id: ipatm_load.c,v 1.12 1998/07/30 22:23:00 mks Exp $
+ *
+ */
+
+/*
+ * IP Over ATM Support
+ * -------------------
+ *
+ * Support for running as a loadable kernel module
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: ipatm_load.c,v 1.12 1998/07/30 22:23:00 mks Exp $";
+#endif
+
+#ifndef ATM_IP_MODULE
+#include "opt_atm.h"
+#endif
+
+#include <netatm/kern_include.h>
+
+#include <netatm/ipatm/ipatm.h>
+#include <netatm/ipatm/ipatm_var.h>
+#include <netatm/ipatm/ipatm_serv.h>
+
+
+/*
+ * Global variables
+ */
+int ipatm_vccnt = 0;
+int ipatm_vcidle = IPATM_VCIDLE;
+int ipatm_print = 0;
+u_long last_map_ipdst = 0;
+struct ipvcc* last_map_ipvcc = NULL;
+
+struct ip_nif *ipatm_nif_head = NULL;
+
+struct ipatm_stat ipatm_stat = {0};
+
+struct atm_time ipatm_itimer = {0, 0}; /* VCC idle timer */
+
+Atm_endpoint ipatm_endpt = {
+ NULL,
+ ENDPT_IP,
+ ipatm_ioctl,
+ ipatm_getname,
+ ipatm_connected,
+ ipatm_cleared,
+ ipatm_incoming,
+ NULL,
+ NULL,
+ NULL,
+ ipatm_cpcs_data,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct sp_info ipatm_vcpool = {
+ "ipatm vcc pool", /* si_name */
+ sizeof(struct ipvcc), /* si_blksiz */
+ 10, /* si_blkcnt */
+ 100 /* si_maxallow */
+};
+
+struct sp_info ipatm_nifpool = {
+ "ipatm nif pool", /* si_name */
+ sizeof(struct ip_nif), /* si_blksiz */
+ 5, /* si_blkcnt */
+ 20 /* si_maxallow */
+};
+
+
+/*
+ * Local functions
+ */
+static int ipatm_start __P((void));
+static int ipatm_stop __P((void));
+
+
+/*
+ * Local variables
+ */
+static struct atm_ncm ipatm_ncm = {
+ NULL,
+ AF_INET,
+ ipatm_ifoutput,
+ ipatm_nifstat
+};
+
+static struct ipatm_listener {
+ Atm_attributes attr;
+ Atm_connection *conn;
+} ipatm_listeners[] = {
+{
+ { NULL, /* nif */
+ CMAPI_CPCS, /* api */
+ 0, /* api_init */
+ 0, /* headin */
+ 0, /* headout */
+ { /* aal */
+ T_ATM_PRESENT,
+ ATM_AAL5
+ },
+ { /* traffic */
+ T_ATM_PRESENT,
+ {
+ {
+ T_ATM_ABSENT,
+ 0,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_NO
+ },
+ {
+ T_ATM_ABSENT,
+ 0,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_NO
+ },
+ T_YES
+ },
+ },
+ { /* bearer */
+ T_ATM_ANY
+ },
+ { /* bhli */
+ T_ATM_ABSENT
+ },
+ { /* blli */
+ T_ATM_PRESENT,
+ T_ATM_ABSENT,
+ {
+ {
+ T_ATM_SIMPLE_ID,
+ },
+ {
+ T_ATM_ABSENT
+ }
+ }
+ },
+ { /* llc */
+ T_ATM_PRESENT,
+ {
+ T_ATM_LLC_SHARING,
+ IPATM_LLC_LEN,
+ IPATM_LLC_HDR
+ }
+ },
+ { /* called */
+ T_ATM_ANY
+ },
+ { /* calling */
+ T_ATM_ANY
+ },
+ { /* qos */
+ T_ATM_PRESENT,
+ {
+ T_ATM_NETWORK_CODING,
+ {
+ T_ATM_QOS_CLASS_0,
+ },
+ {
+ T_ATM_QOS_CLASS_0
+ }
+ }
+ },
+ { /* transit */
+ T_ATM_ANY
+ },
+ { /* cause */
+ T_ATM_ABSENT
+ },
+ },
+ NULL
+},
+{
+ { NULL, /* nif */
+ CMAPI_CPCS, /* api */
+ 0, /* api_init */
+ 0, /* headin */
+ 0, /* headout */
+ { /* aal */
+ T_ATM_PRESENT,
+ ATM_AAL5
+ },
+ { /* traffic */
+ T_ATM_PRESENT,
+ {
+ {
+ T_ATM_ABSENT,
+ 0,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_NO
+ },
+ {
+ T_ATM_ABSENT,
+ 0,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_NO
+ },
+ T_YES
+ },
+ },
+ { /* bearer */
+ T_ATM_ANY
+ },
+ { /* bhli */
+ T_ATM_ABSENT
+ },
+ { /* blli */
+ T_ATM_ABSENT,
+ T_ATM_ABSENT
+ },
+ { /* llc */
+ T_ATM_ABSENT
+ },
+ { /* called */
+ T_ATM_ANY
+ },
+ { /* calling */
+ T_ATM_ANY
+ },
+ { /* qos */
+ T_ATM_PRESENT,
+ {
+ T_ATM_NETWORK_CODING,
+ {
+ T_ATM_QOS_CLASS_0,
+ },
+ {
+ T_ATM_QOS_CLASS_0
+ }
+ }
+ },
+ { /* transit */
+ T_ATM_ANY
+ },
+ { /* cause */
+ T_ATM_ABSENT
+ },
+ },
+ NULL
+},
+{
+ { NULL, /* nif */
+ CMAPI_CPCS, /* api */
+ 0, /* api_init */
+ 0, /* headin */
+ 0, /* headout */
+ { /* aal */
+ T_ATM_PRESENT,
+ ATM_AAL3_4
+ },
+ { /* traffic */
+ T_ATM_PRESENT,
+ {
+ {
+ T_ATM_ABSENT,
+ 0,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_NO
+ },
+ {
+ T_ATM_ABSENT,
+ 0,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_ATM_ABSENT,
+ T_NO
+ },
+ T_YES
+ },
+ },
+ { /* bearer */
+ T_ATM_ANY
+ },
+ { /* bhli */
+ T_ATM_ABSENT
+ },
+ { /* blli */
+ T_ATM_ABSENT,
+ T_ATM_ABSENT
+ },
+ { /* llc */
+ T_ATM_ABSENT
+ },
+ { /* called */
+ T_ATM_ANY
+ },
+ { /* calling */
+ T_ATM_ANY
+ },
+ { /* qos */
+ T_ATM_PRESENT,
+ {
+ T_ATM_NETWORK_CODING,
+ {
+ T_ATM_QOS_CLASS_0,
+ },
+ {
+ T_ATM_QOS_CLASS_0
+ }
+ }
+ },
+ { /* transit */
+ T_ATM_ANY
+ },
+ { /* cause */
+ T_ATM_ABSENT
+ },
+ },
+ NULL
+},
+};
+
+static struct t_atm_cause ipatm_cause = {
+ T_ATM_ITU_CODING,
+ T_ATM_LOC_USER,
+ T_ATM_CAUSE_UNSPECIFIED_NORMAL,
+ {0, 0, 0, 0}
+};
+
+
+/*
+ * Initialize ipatm processing
+ *
+ * This will be called during module loading. We'll just register
+ * ourselves and wait for the packets to start flying.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 startup was successful
+ * errno startup failed - reason indicated
+ *
+ */
+static int
+ipatm_start()
+{
+ struct atm_pif *pip;
+ struct atm_nif *nip;
+ int err, s, i;
+
+ /*
+ * Verify software version
+ */
+ if (atm_version != ATM_VERSION) {
+ log(LOG_ERR, "version mismatch: ipatm=%d.%d kernel=%d.%d\n",
+ ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
+ ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
+ return (EINVAL);
+ }
+
+ /*
+ * Register ourselves as a network convergence module
+ */
+ err = atm_netconv_register(&ipatm_ncm);
+ if (err)
+ goto done;
+
+ /*
+ * Register ourselves as an ATM endpoint
+ */
+ err = atm_endpoint_register(&ipatm_endpt);
+ if (err)
+ goto done;
+
+ /*
+ * Get current system configuration
+ */
+ s = splnet();
+ for (pip = atm_interface_head; pip; pip = pip->pif_next) {
+ /*
+ * Process each network interface
+ */
+ for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
+ struct ifnet *ifp = (struct ifnet *)nip;
+ struct in_ifaddr *ia;
+
+ /*
+ * Attach interface
+ */
+ err = ipatm_nifstat(NCM_ATTACH, nip, 0);
+ if (err) {
+ (void) splx(s);
+ goto done;
+ }
+
+ /*
+ * If IP address has been set, register it
+ */
+ TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
+ if (ia->ia_ifp == ifp)
+ break;
+ }
+ if (ia) {
+ err = ipatm_nifstat(NCM_SETADDR, nip, (int)ia);
+ if (err) {
+ (void) splx(s);
+ goto done;
+ }
+ }
+ }
+ }
+ (void) splx(s);
+
+ /*
+ * Fill in union fields
+ */
+ ipatm_aal5llc.aal.v.aal5.forward_max_SDU_size =
+ ATM_NIF_MTU + IPATM_LLC_LEN;
+ ipatm_aal5llc.aal.v.aal5.backward_max_SDU_size =
+ ATM_NIF_MTU + IPATM_LLC_LEN;
+ ipatm_aal5llc.aal.v.aal5.SSCS_type = T_ATM_NULL;
+ ipatm_aal5llc.blli.v.layer_2_protocol.ID.simple_ID = T_ATM_BLLI2_I8802;
+
+ ipatm_aal5null.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
+ ipatm_aal5null.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
+ ipatm_aal5null.aal.v.aal5.SSCS_type = T_ATM_NULL;
+
+ ipatm_aal4null.aal.v.aal4.forward_max_SDU_size = ATM_NIF_MTU;
+ ipatm_aal4null.aal.v.aal4.backward_max_SDU_size = ATM_NIF_MTU;
+ ipatm_aal4null.aal.v.aal4.SSCS_type = T_ATM_NULL;
+ ipatm_aal4null.aal.v.aal4.mid_low = 0;
+ ipatm_aal4null.aal.v.aal4.mid_high = 1023;
+
+ /*
+ * Listen for incoming calls
+ */
+ for (i = 0;
+ i < (sizeof(ipatm_listeners) / sizeof(struct ipatm_listener));
+ i++) {
+ struct attr_aal *aalp = &ipatm_listeners[i].attr.aal;
+ int maxsdu = ATM_NIF_MTU;
+
+ /*
+ * Fill in union fields
+ */
+ if (ipatm_listeners[i].attr.blli.tag_l2 == T_ATM_PRESENT) {
+ struct t_atm_blli *bp = &ipatm_listeners[i].attr.blli.v;
+
+ bp->layer_2_protocol.ID.simple_ID = T_ATM_BLLI2_I8802;
+ maxsdu += IPATM_LLC_LEN;
+ }
+ if (aalp->type == ATM_AAL5) {
+ aalp->v.aal5.forward_max_SDU_size = maxsdu;
+ aalp->v.aal5.backward_max_SDU_size = maxsdu;
+ aalp->v.aal5.SSCS_type = T_ATM_NULL;
+ } else {
+ aalp->v.aal4.forward_max_SDU_size = maxsdu;
+ aalp->v.aal4.backward_max_SDU_size = maxsdu;
+ aalp->v.aal4.SSCS_type = T_ATM_NULL;
+ aalp->v.aal4.mid_low = 0;
+ aalp->v.aal4.mid_high = 1023;
+ }
+
+ /*
+ * Now start listening
+ */
+ if (err = atm_cm_listen(&ipatm_endpt, (void *)i,
+ &ipatm_listeners[i].attr,
+ &ipatm_listeners[i].conn))
+ goto done;
+ }
+
+ /*
+ * Start background VCC idle timer
+ */
+ atm_timeout(&ipatm_itimer, IPATM_IDLE_TIME, ipatm_itimeout);
+
+done:
+ return (err);
+}
+
+
+/*
+ * Halt ipatm processing
+ *
+ * This will be called just prior to unloading the module from
+ * memory. All IP VCCs must be terminated before the protocol can
+ * be shutdown.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 shutdown was successful
+ * errno shutdown failed - reason indicated
+ *
+ */
+static int
+ipatm_stop()
+{
+ struct ip_nif *inp;
+ int err = 0, i;
+ int s = splnet();
+
+ /*
+ * Any VCCs still open??
+ */
+ if (ipatm_vccnt) {
+
+ /* Yes, can't stop now */
+ err = EBUSY;
+ goto done;
+ }
+
+ /*
+ * Kill VCC idle timer
+ */
+ (void) atm_untimeout(&ipatm_itimer);
+
+ /*
+ * Stop listening for incoming calls
+ */
+ for (i = 0;
+ i < (sizeof(ipatm_listeners) / sizeof(struct ipatm_listener));
+ i++) {
+ if (ipatm_listeners[i].conn != NULL) {
+ (void) atm_cm_release(ipatm_listeners[i].conn,
+ &ipatm_cause);
+ }
+ }
+
+ /*
+ * Detach all our interfaces
+ */
+ while (inp = ipatm_nif_head) {
+ (void) ipatm_nifstat(NCM_DETACH, inp->inf_nif, 0);
+ }
+
+ /*
+ * De-register from system
+ */
+ (void) atm_netconv_deregister(&ipatm_ncm);
+ (void) atm_endpoint_deregister(&ipatm_endpt);
+
+ /*
+ * Free up our storage pools
+ */
+ atm_release_pool(&ipatm_vcpool);
+ atm_release_pool(&ipatm_nifpool);
+
+done:
+ (void) splx(s);
+ return (err);
+}
+
+
+#ifdef ATM_IP_MODULE
+/*
+ *******************************************************************
+ *
+ * Loadable Module Support
+ *
+ *******************************************************************
+ */
+static int ipatm_doload __P((void));
+static int ipatm_dounload __P((void));
+
+/*
+ * Generic module load processing
+ *
+ * This function is called by an OS-specific function when this
+ * module is being loaded.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 load was successful
+ * errno load failed - reason indicated
+ *
+ */
+static int
+ipatm_doload()
+{
+ int err = 0;
+
+ /*
+ * Start us up
+ */
+ err = ipatm_start();
+ if (err)
+ /* Problems, clean up */
+ (void)ipatm_stop();
+
+ return (err);
+}
+
+
+/*
+ * Generic module unload processing
+ *
+ * This function is called by an OS-specific function when this
+ * module is being unloaded.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 unload was successful
+ * errno unload failed - reason indicated
+ *
+ */
+static int
+ipatm_dounload()
+{
+ int err = 0;
+
+ /*
+ * OK, try to clean up our mess
+ */
+ err = ipatm_stop();
+
+ return (err);
+}
+
+
+#ifdef sun
+/*
+ * Loadable driver description
+ */
+struct vdldrv ipatm_drv = {
+ VDMAGIC_PSEUDO, /* Pseudo Driver */
+ "ipatm_mod", /* name */
+ NULL, /* dev_ops */
+ NULL, /* bdevsw */
+ NULL, /* cdevsw */
+ 0, /* blockmajor */
+ 0 /* charmajor */
+};
+
+
+/*
+ * Loadable module support entry point
+ *
+ * This is the routine called by the vd driver for all loadable module
+ * functions for this pseudo driver. This routine name must be specified
+ * on the modload(1) command. This routine will be called whenever the
+ * modload(1), modunload(1) or modstat(1) commands are issued for this
+ * module.
+ *
+ * Arguments:
+ * cmd vd command code
+ * vdp pointer to vd driver's structure
+ * vdi pointer to command-specific vdioctl_* structure
+ * vds pointer to status structure (VDSTAT only)
+ *
+ * Returns:
+ * 0 command was successful
+ * errno command failed - reason indicated
+ *
+ */
+int
+ipatm_mod(cmd, vdp, vdi, vds)
+ int cmd;
+ struct vddrv *vdp;
+ caddr_t vdi;
+ struct vdstat *vds;
+{
+ int err = 0;
+
+ switch (cmd) {
+
+ case VDLOAD:
+ /*
+ * Module Load
+ *
+ * We dont support any user configuration
+ */
+ err = ipatm_doload();
+ if (err == 0)
+ /* Let vd driver know about us */
+ vdp->vdd_vdtab = (struct vdlinkage *)&ipatm_drv;
+ break;
+
+ case VDUNLOAD:
+ /*
+ * Module Unload
+ */
+ err = ipatm_dounload();
+ break;
+
+ case VDSTAT:
+ /*
+ * Module Status
+ */
+
+ /* Not much to say at the moment */
+
+ break;
+
+ default:
+ log(LOG_ERR, "ipatm_mod: Unknown vd command 0x%x\n", cmd);
+ err = EINVAL;
+ }
+
+ return (err);
+}
+#endif /* sun */
+
+#ifdef __FreeBSD__
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+
+/*
+ * Loadable miscellaneous module description
+ */
+MOD_MISC(ipatm);
+
+
+/*
+ * Loadable module support "load" entry point
+ *
+ * This is the routine called by the lkm driver whenever the
+ * modload(1) command is issued for this module.
+ *
+ * Arguments:
+ * lkmtp pointer to lkm drivers's structure
+ * cmd lkm command code
+ *
+ * Returns:
+ * 0 command was successful
+ * errno command failed - reason indicated
+ *
+ */
+static int
+ipatm_load(lkmtp, cmd)
+ struct lkm_table *lkmtp;
+ int cmd;
+{
+ return(ipatm_doload());
+}
+
+
+/*
+ * Loadable module support "unload" entry point
+ *
+ * This is the routine called by the lkm driver whenever the
+ * modunload(1) command is issued for this module.
+ *
+ * Arguments:
+ * lkmtp pointer to lkm drivers's structure
+ * cmd lkm command code
+ *
+ * Returns:
+ * 0 command was successful
+ * errno command failed - reason indicated
+ *
+ */
+static int
+ipatm_unload(lkmtp, cmd)
+ struct lkm_table *lkmtp;
+ int cmd;
+{
+ return(ipatm_dounload());
+}
+
+
+/*
+ * Loadable module support entry point
+ *
+ * This is the routine called by the lkm driver for all loadable module
+ * functions for this driver. This routine name must be specified
+ * on the modload(1) command. This routine will be called whenever the
+ * modload(1), modunload(1) or modstat(1) commands are issued for this
+ * module.
+ *
+ * Arguments:
+ * lkmtp pointer to lkm drivers's structure
+ * cmd lkm command code
+ * ver lkm version
+ *
+ * Returns:
+ * 0 command was successful
+ * errno command failed - reason indicated
+ *
+ */
+int
+ipatm_mod(lkmtp, cmd, ver)
+ struct lkm_table *lkmtp;
+ int cmd;
+ int ver;
+{
+ MOD_DISPATCH(ipatm, lkmtp, cmd, ver,
+ ipatm_load, ipatm_unload, lkm_nullcmd);
+}
+#endif /* __FreeBSD__ */
+
+#else /* !ATM_IP_MODULE */
+
+/*
+ *******************************************************************
+ *
+ * Kernel Compiled Module Support
+ *
+ *******************************************************************
+ */
+static void ipatm_doload __P((void *));
+
+SYSINIT(atmipatm, SI_SUB_PROTO_END, SI_ORDER_ANY, ipatm_doload, NULL)
+
+/*
+ * Kernel initialization
+ *
+ * Arguments:
+ * arg Not used
+ *
+ * Returns:
+ * none
+ *
+ */
+static void
+ipatm_doload(void *arg)
+{
+ int err = 0;
+
+ /*
+ * Start us up
+ */
+ err = ipatm_start();
+ if (err) {
+ /* Problems, clean up */
+ (void)ipatm_stop();
+
+ log(LOG_ERR, "IP over ATM unable to initialize (%d)!!\n", err);
+ }
+ return;
+}
+#endif /* ATM_IP_MODULE */
+
OpenPOWER on IntegriCloud