summaryrefslogtreecommitdiffstats
path: root/sys/netatm/atm_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netatm/atm_usrreq.c')
-rw-r--r--sys/netatm/atm_usrreq.c711
1 files changed, 711 insertions, 0 deletions
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 <netatm/kern_include.h>
+
+
+/*
+ * 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);
+}
+
OpenPOWER on IntegriCloud