From c3dd1fa899d435ea4bf79897f646a93cb80c94ac Mon Sep 17 00:00:00 2001 From: phk Date: Tue, 15 Sep 1998 08:23:17 +0000 Subject: Add new files for HARP3 Host ATM Research Platform (HARP), Network Computing Services, Inc. This software was developed with the support of the Defense Advanced Research Projects Agency (DARPA). --- sys/netatm/atm_usrreq.c | 711 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 711 insertions(+) create mode 100644 sys/netatm/atm_usrreq.c (limited to 'sys/netatm/atm_usrreq.c') diff --git a/sys/netatm/atm_usrreq.c b/sys/netatm/atm_usrreq.c new file mode 100644 index 0000000..4231d1c --- /dev/null +++ b/sys/netatm/atm_usrreq.c @@ -0,0 +1,711 @@ +/* + * + * =================================== + * 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: atm_usrreq.c,v 1.7 1998/06/29 21:51:29 mks Exp $ + * + */ + +/* + * Core ATM Services + * ----------------- + * + * ATM DGRAM socket protocol processing + * + */ + +#ifndef lint +static char *RCSid = "@(#) $Id: atm_usrreq.c,v 1.7 1998/06/29 21:51:29 mks Exp $"; +#endif + +#include + + +/* + * Local functions + */ +static int atm_dgram_attach __P((struct socket *, int, struct proc *)); +static int atm_dgram_control __P((struct socket *, u_long, caddr_t, + struct ifnet *, struct proc *)); +static int atm_dgram_info __P((caddr_t)); + + +/* + * New-style socket request routines + */ +#if (defined(__FreeBSD__) && (BSD >= 199506)) +struct pr_usrreqs atm_dgram_usrreqs = { + atm_proto_notsupp1, /* pru_abort */ + pru_accept_notsupp, /* pru_accept */ + atm_dgram_attach, /* pru_attach */ + atm_proto_notsupp2, /* pru_bind */ + pru_connect_notsupp, /* pru_connect */ + pru_connect2_notsupp, /* pru_connect2 */ + atm_dgram_control, /* pru_control */ + atm_proto_notsupp1, /* pru_detach */ + atm_proto_notsupp1, /* pru_disconnect */ + pru_listen_notsupp, /* pru_listen */ + atm_proto_notsupp3, /* pru_peeraddr */ + pru_rcvd_notsupp, /* pru_rcvd */ + pru_rcvoob_notsupp, /* pru_rcvoob */ + atm_proto_notsupp4, /* pru_send */ + pru_sense_null, /* pru_sense */ + atm_proto_notsupp1, /* pru_shutdown */ + atm_proto_notsupp3, /* pru_sockaddr */ +}; +#endif + + +/* + * Handy common code macros + */ +#ifdef DIAGNOSTIC +#define ATM_INTRO() \ + int s, err = 0; \ + s = splnet(); \ + /* \ + * Stack queue should have been drained \ + */ \ + if (atm_stackq_head != NULL) \ + panic("atm_usrreq: stack queue not empty"); \ + ; +#else +#define ATM_INTRO() \ + int s, err = 0; \ + s = splnet(); \ + ; +#endif + +#define ATM_OUTRO() \ +done: \ + /* \ + * Drain any deferred calls \ + */ \ + STACK_DRAIN(); \ + (void) splx(s); \ + return (err); \ + ; + +#define ATM_RETERR(errno) { \ + err = errno; \ + goto done; \ +} + + +/* + * Attach protocol to socket + * + * Arguments: + * so pointer to socket + * proto protocol identifier + * p pointer to process + * + * Returns: + * 0 request processed + * errno error processing request - reason indicated + * + */ +static int +atm_dgram_attach(so, proto, p) + struct socket *so; + int proto; + struct proc *p; +{ + ATM_INTRO(); + + /* + * Nothing to do here for ioctl()-only sockets + */ + ATM_OUTRO(); +} + + +/* + * Process ioctl system calls + * + * Arguments: + * so pointer to socket + * cmd ioctl code + * data pointer to code specific parameter data area + * ifp pointer to ifnet structure if it's an interface ioctl + * p pointer to process + * + * Returns: + * 0 request processed + * errno error processing request - reason indicated + * + */ +static int +atm_dgram_control(so, cmd, data, ifp, p) + struct socket *so; + u_long cmd; + caddr_t data; + struct ifnet *ifp; + struct proc *p; +{ + ATM_INTRO(); + + /* + * First, figure out which ioctl we're dealing with and + * then process it based on the sub-op code + */ + switch (cmd) { + + case AIOCCFG: { + struct atmcfgreq *acp = (struct atmcfgreq *)data; + struct atm_pif *pip; + + if (p && (suser(p->p_ucred, &p->p_acflag) != 0)) + ATM_RETERR(EPERM); + + switch (acp->acr_opcode) { + + case AIOCS_CFG_ATT: + /* + * Attach signalling manager + */ + if ((pip = atm_pifname(acp->acr_att_intf)) == NULL) + ATM_RETERR(ENXIO); + err = atm_sigmgr_attach(pip, acp->acr_att_proto); + break; + + case AIOCS_CFG_DET: + /* + * Detach signalling manager + */ + if ((pip = atm_pifname(acp->acr_det_intf)) == NULL) + ATM_RETERR(ENXIO); + err = atm_sigmgr_detach(pip); + break; + + default: + err = EOPNOTSUPP; + } + break; + } + + case AIOCADD: { + struct atmaddreq *aap = (struct atmaddreq *)data; + Atm_endpoint *epp; + + if (p && (suser(p->p_ucred, &p->p_acflag) != 0)) + ATM_RETERR(EPERM); + + switch (aap->aar_opcode) { + + case AIOCS_ADD_PVC: + /* + * Add a PVC definition + */ + + /* + * Locate requested endpoint service + */ + epp = aap->aar_pvc_sap > ENDPT_MAX ? NULL : + atm_endpoints[aap->aar_pvc_sap]; + if (epp == NULL) + ATM_RETERR(ENOPROTOOPT); + + /* + * Let endpoint service handle it from here + */ + err = (*epp->ep_ioctl)(AIOCS_ADD_PVC, data, NULL); + break; + + case AIOCS_ADD_ARP: + /* + * Add an ARP mapping + */ + epp = atm_endpoints[ENDPT_IP]; + if (epp == NULL) + ATM_RETERR(ENOPROTOOPT); + + /* + * Let IP/ATM endpoint handle this + */ + err = (*epp->ep_ioctl) (AIOCS_ADD_ARP, data, NULL); + break; + + default: + err = EOPNOTSUPP; + } + break; + } + + case AIOCDEL: { + struct atmdelreq *adp = (struct atmdelreq *)data; + struct atm_pif *pip; + struct sigmgr *smp; + Atm_endpoint *epp; + + if (p && (suser(p->p_ucred, &p->p_acflag) != 0)) + ATM_RETERR(EPERM); + + switch (adp->adr_opcode) { + + case AIOCS_DEL_PVC: + case AIOCS_DEL_SVC: + /* + * Delete a PVC or SVC + */ + + /* + * Locate appropriate sigmgr + */ + if ((pip = atm_pifname(adp->adr_pvc_intf)) == NULL) + ATM_RETERR(ENXIO); + if ((smp = pip->pif_sigmgr) == NULL) + ATM_RETERR(ENOENT); + + /* + * Let sigmgr handle it from here + */ + err = (*smp->sm_ioctl)(adp->adr_opcode, data, + (caddr_t)pip->pif_siginst); + break; + + case AIOCS_DEL_ARP: + /* + * Delete an ARP mapping + */ + epp = atm_endpoints[ENDPT_IP]; + if (epp == NULL) + ATM_RETERR(ENOPROTOOPT); + + /* + * Let IP/ATM endpoint handle this + */ + err = (*epp->ep_ioctl) (AIOCS_DEL_ARP, data, NULL); + break; + + default: + err = EOPNOTSUPP; + } + break; + } + + case AIOCSET: { + struct atmsetreq *asp = (struct atmsetreq *)data; + struct atm_pif *pip; + struct atm_nif *nip; + struct sigmgr *smp; + struct ifnet *ifp2; + + if (p && (suser(p->p_ucred, &p->p_acflag) != 0)) + ATM_RETERR(EPERM); + + switch (asp->asr_opcode) { + + case AIOCS_SET_ASV: + /* + * Set an ARP server address + */ + + /* + * Locate appropriate sigmgr + */ + if ((nip = atm_nifname(asp->asr_arp_intf)) == NULL) + ATM_RETERR(ENXIO); + pip = nip->nif_pif; + if ((smp = pip->pif_sigmgr) == NULL) + ATM_RETERR(ENOENT); + + /* + * Let sigmgr handle it from here + */ + err = (*smp->sm_ioctl)(AIOCS_SET_ASV, data, + (caddr_t)nip); + break; + + case AIOCS_SET_MAC: + /* + * Set physical interface MAC/ESI address + */ + + /* + * Locate physical interface + */ + if ((pip = atm_pifname(asp->asr_mac_intf)) == NULL) + ATM_RETERR(ENXIO); + + /* + * Interface must be detached + */ + if (pip->pif_sigmgr != NULL) + ATM_RETERR(EADDRINUSE); + + /* + * Just plunk the address into the pif + */ + KM_COPY((caddr_t)&asp->asr_mac_addr, + (caddr_t)&pip->pif_macaddr, + sizeof(struct mac_addr)); + break; + + case AIOCS_SET_NIF: + /* + * Define network interfaces + */ + if ((pip = atm_pifname(asp->asr_nif_intf)) == NULL) + ATM_RETERR(ENXIO); + + /* + * Validate interface count - logical interfaces + * are differentiated by the atm address selector. + */ + if ((asp->asr_nif_cnt <= 0) || (asp->asr_nif_cnt > 256)) + ATM_RETERR(EINVAL); + + /* + * Make sure prefix name is unique + */ + TAILQ_FOREACH(ifp2, &ifnet, if_link) { + if (!strcmp(ifp2->if_name, asp->asr_nif_pref)) { + /* + * If this is for the interface we're + * (re-)defining, let it through + */ + for (nip = pip->pif_nif; nip; + nip = nip->nif_pnext) { + if (&nip->nif_if == ifp2) + break; + } + if (nip) + continue; + ATM_RETERR(EEXIST); + } + } + + /* + * Let interface handle it from here + */ + err = (*pip->pif_ioctl)(AIOCS_SET_NIF, data, + (caddr_t)pip); + break; + + case AIOCS_SET_PRF: + /* + * Set interface NSAP Prefix + */ + + /* + * Locate appropriate sigmgr + */ + if ((pip = atm_pifname(asp->asr_prf_intf)) == NULL) + ATM_RETERR(ENXIO); + if ((smp = pip->pif_sigmgr) == NULL) + ATM_RETERR(ENOENT); + + /* + * Let sigmgr handle it from here + */ + err = (*smp->sm_ioctl)(AIOCS_SET_PRF, data, + (caddr_t)pip->pif_siginst); + break; + + default: + err = EOPNOTSUPP; + } + break; + } + + case AIOCINFO: + err = atm_dgram_info(data); + break; + + default: + err = EOPNOTSUPP; + } + + ATM_OUTRO(); +} + + +/* + * Process AIOCINFO ioctl system calls + * + * Called at splnet. + * + * Arguments: + * data pointer to AIOCINFO parameter structure + * + * Returns: + * 0 request processed + * errno error processing request - reason indicated + * + */ +static int +atm_dgram_info(data) + caddr_t data; +{ + struct atminfreq *aip = (struct atminfreq *)data; + struct atm_pif *pip; + struct atm_nif *nip; + struct sigmgr *smp; + Atm_endpoint *epp; + int len = aip->air_buf_len; + int err = 0; + + switch (aip->air_opcode) { + + case AIOCS_INF_VST: + case AIOCS_INF_CFG: + /* + * Get vendor interface information + */ + if (aip->air_vinfo_intf[0] != '\0') { + /* + * Interface specified + */ + if ((pip = atm_pifname(aip->air_vinfo_intf))) { + err = (*pip->pif_ioctl)(aip->air_opcode, data, + (caddr_t)pip); + } else { + err = ENXIO; + } + } else { + /* + * Want info for every interface + */ + for (pip = atm_interface_head; pip; + pip = pip->pif_next) { + err = (*pip->pif_ioctl)(aip->air_opcode, data, + (caddr_t)pip); + if (err) + break; + } + } + break; + + case AIOCS_INF_IPM: + /* + * Get IP Map information + */ + epp = atm_endpoints[ENDPT_IP]; + if (epp) { + err = (*epp->ep_ioctl) (AIOCS_INF_IPM, data, NULL); + } else { + err = ENOPROTOOPT; + } + break; + + case AIOCS_INF_ARP: + /* + * Get ARP table information + */ + for (pip = atm_interface_head; pip; pip = pip->pif_next) { + if (smp = pip->pif_sigmgr) { + err = (*smp->sm_ioctl)(AIOCS_INF_ARP, + data, (caddr_t)pip->pif_siginst); + } + if (err) + break; + } + break; + + case AIOCS_INF_ASV: + /* + * Get ARP server information + */ + if (aip->air_asrv_intf[0] != '\0') { + /* + * Interface specified + */ + if ((nip = atm_nifname(aip->air_asrv_intf))) { + if (smp = nip->nif_pif->pif_sigmgr) { + err = (*smp->sm_ioctl)(AIOCS_INF_ASV, + data, (caddr_t)nip); + } + } else { + err = ENXIO; + } + } else { + /* + * Want info for all arp servers + */ + for (pip = atm_interface_head; pip; + pip = pip->pif_next) { + if (smp = pip->pif_sigmgr) { + err = (*smp->sm_ioctl)(AIOCS_INF_ASV, + data, NULL); + } + if (err) + break; + } + } + break; + + case AIOCS_INF_INT: + /* + * Get physical interface info + */ + if (aip->air_int_intf[0] != '\0') { + /* + * Interface specified + */ + if ((pip = atm_pifname(aip->air_int_intf))) { + err = (*pip->pif_ioctl)(AIOCS_INF_INT, + data, (caddr_t)pip); + } else { + err = ENXIO; + } + } else { + /* + * Want info for every physical interface + */ + for (pip = atm_interface_head; pip; + pip = pip->pif_next) { + err = (*pip->pif_ioctl)(AIOCS_INF_INT, + data, (caddr_t)pip); + if (err) + break; + } + } + break; + + case AIOCS_INF_VCC: + /* + * Get VCC information + */ + if (aip->air_vcc_intf[0] != '\0') { + /* + * Interface specified + */ + if ((pip = atm_pifname(aip->air_vcc_intf))) { + if (smp = pip->pif_sigmgr) { + err = (*smp->sm_ioctl)(AIOCS_INF_VCC, + data, + (caddr_t)pip->pif_siginst); + } + } else { + err = ENXIO; + } + } else { + /* + * Want info for every interface + */ + for (pip = atm_interface_head; pip; + pip = pip->pif_next) { + if (smp = pip->pif_sigmgr) { + err = (*smp->sm_ioctl)(AIOCS_INF_VCC, + data, + (caddr_t)pip->pif_siginst); + } + if (err) + break; + } + } + break; + + case AIOCS_INF_NIF: + /* + * Get network interface info + */ + if (aip->air_int_intf[0] != '\0') { + /* + * Interface specified + */ + if ((nip = atm_nifname(aip->air_int_intf))) { + pip = nip->nif_pif; + err = (*pip->pif_ioctl)(AIOCS_INF_NIF, + data, (caddr_t)nip); + } else { + err = ENXIO; + } + } else { + /* + * Want info for every network interface + */ + for (pip = atm_interface_head; pip; + pip = pip->pif_next) { + for (nip = pip->pif_nif; nip; + nip = nip->nif_pnext) { + err = (*pip->pif_ioctl)(AIOCS_INF_NIF, + data, (caddr_t)nip); + if (err) + break; + } + if (err) + break; + } + } + break; + + case AIOCS_INF_PIS: + /* + * Get physical interface statistics + */ + if (aip->air_physt_intf[0] != '\0') { + /* + * Interface specified + */ + if ((pip = atm_pifname(aip->air_physt_intf))) { + err = (*pip->pif_ioctl)(AIOCS_INF_PIS, + data, (caddr_t)pip); + } else { + err = ENXIO; + } + } else { + /* + * Want statistics for every physical interface + */ + for (pip = atm_interface_head; pip; + pip = pip->pif_next) { + err = (*pip->pif_ioctl)(AIOCS_INF_PIS, + data, (caddr_t)pip); + if (err) + break; + } + } + break; + + case AIOCS_INF_VER: + /* + * Get ATM software version + */ + if (len < sizeof(atm_version)) { + err = ENOSPC; + break; + } + if (err = copyout((caddr_t)&atm_version, + aip->air_buf_addr, + sizeof(atm_version))) { + break; + } + aip->air_buf_addr += sizeof(atm_version); + aip->air_buf_len -= sizeof(atm_version); + break; + + default: + err = EOPNOTSUPP; + } + + /* + * Calculate returned buffer length + */ + aip->air_buf_len = len - aip->air_buf_len; + + return (err); +} + -- cgit v1.1