diff options
Diffstat (limited to 'sys/netatm/ipatm/ipatm_load.c')
-rw-r--r-- | sys/netatm/ipatm/ipatm_load.c | 878 |
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 */ + |