summaryrefslogtreecommitdiffstats
path: root/sys/netatm/ipatm/ipatm_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netatm/ipatm/ipatm_usrreq.c')
-rw-r--r--sys/netatm/ipatm/ipatm_usrreq.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/sys/netatm/ipatm/ipatm_usrreq.c b/sys/netatm/ipatm/ipatm_usrreq.c
new file mode 100644
index 0000000..1f1751c
--- /dev/null
+++ b/sys/netatm/ipatm/ipatm_usrreq.c
@@ -0,0 +1,394 @@
+/*
+ *
+ * ===================================
+ * 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_usrreq.c,v 1.6 1998/05/18 19:14:04 mks Exp $
+ *
+ */
+
+/*
+ * IP Over ATM Support
+ * -------------------
+ *
+ * Process user requests
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: ipatm_usrreq.c,v 1.6 1998/05/18 19:14:04 mks Exp $";
+#endif
+
+#include <netatm/kern_include.h>
+
+#include <netatm/ipatm/ipatm.h>
+#include <netatm/ipatm/ipatm_var.h>
+#include <netatm/ipatm/ipatm_serv.h>
+
+
+/*
+ * Process IP PF_ATM ioctls
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * code PF_ATM sub-operation code
+ * data pointer to code specific parameter data area
+ * arg1 pointer to code specific argument
+ *
+ * Returns:
+ * 0 request procesed
+ * errno error processing request - reason indicated
+ *
+ */
+int
+ipatm_ioctl(code, data, arg1)
+ int code;
+ caddr_t data;
+ caddr_t arg1;
+{
+ struct atmaddreq *aap;
+ struct atmdelreq *adp;
+ struct atminfreq *aip;
+ struct air_ip_vcc_rsp aivr;
+ struct atm_nif *nip;
+ struct ip_nif *inp;
+ struct ipvcc *ivp;
+ struct vccb *vcp;
+ struct ipatmpvc pv;
+ caddr_t cp;
+ struct in_addr ip;
+ int space, err = 0;
+
+
+ switch (code) {
+
+ case AIOCS_ADD_PVC:
+ /*
+ * Add an IP PVC
+ */
+ aap = (struct atmaddreq *)data;
+
+ /*
+ * Find the IP network interface
+ */
+ if ((nip = atm_nifname(aap->aar_pvc_intf)) == NULL) {
+ err = ENXIO;
+ break;
+ }
+
+ for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
+ if (inp->inf_nif == nip)
+ break;
+ }
+ if (inp == NULL) {
+ err = ENXIO;
+ break;
+ }
+
+ /*
+ * Validate PVC params
+ */
+ if (aap->aar_pvc_aal == ATM_AAL5) {
+ if ((aap->aar_pvc_encaps != ATM_ENC_LLC) &&
+ (aap->aar_pvc_encaps != ATM_ENC_NULL)) {
+ err = EINVAL;
+ break;
+ }
+ } else if (aap->aar_pvc_aal == ATM_AAL3_4) {
+ if (aap->aar_pvc_encaps != ATM_ENC_NULL) {
+ err = EINVAL;
+ break;
+ }
+ } else {
+ err = EINVAL;
+ break;
+ }
+
+ if (aap->aar_pvc_flags & PVC_DYN) {
+ /*
+ * For dynamic PVC destination addressing, the
+ * network interface must have support for this
+ */
+ if ((inp->inf_serv == NULL) ||
+ (inp->inf_serv->is_arp_pvcopen == NULL)) {
+ err = EDESTADDRREQ;
+ break;
+ }
+ } else {
+ u_long dst = ((struct sockaddr_in *)&aap->aar_pvc_dst)
+ ->sin_addr.s_addr;
+
+ if (dst == INADDR_ANY) {
+ err = EINVAL;
+ break;
+ }
+ }
+
+ /*
+ * Build connection request
+ */
+ pv.ipp_ipnif = inp;
+ pv.ipp_vpi = aap->aar_pvc_vpi;
+ pv.ipp_vci = aap->aar_pvc_vci;
+ pv.ipp_encaps = aap->aar_pvc_encaps;
+ pv.ipp_aal = aap->aar_pvc_aal;
+ if (aap->aar_pvc_flags & PVC_DYN) {
+ pv.ipp_dst.sin_addr.s_addr = INADDR_ANY;
+ } else
+ pv.ipp_dst = *(struct sockaddr_in *)&aap->aar_pvc_dst;
+
+ /*
+ * Open a new VCC
+ */
+ err = ipatm_openpvc(&pv, &ivp);
+ break;
+
+ case AIOCS_ADD_ARP:
+ /*
+ * Add an ARP mapping
+ */
+ aap = (struct atmaddreq *)data;
+
+ /*
+ * Validate IP address
+ */
+ if (aap->aar_arp_dst.sa_family != AF_INET) {
+ err = EAFNOSUPPORT;
+ break;
+ }
+ ip = SATOSIN(&aap->aar_arp_dst)->sin_addr;
+
+ if (aap->aar_arp_intf[0] == '\0') {
+ /*
+ * Find the IP network interface associated with
+ * the supplied IP address
+ */
+ for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
+ if (ipatm_chknif(ip, inp) == 0)
+ break;
+ }
+ if (inp == NULL) {
+ err = EADDRNOTAVAIL;
+ break;
+ }
+ } else {
+ /*
+ * Find the specified IP network interface
+ */
+ if ((nip = atm_nifname(aap->aar_arp_intf)) == NULL) {
+ err = ENXIO;
+ break;
+ }
+ for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
+ if (inp->inf_nif == nip)
+ break;
+ }
+ if (inp == NULL) {
+ err = ENXIO;
+ break;
+ }
+ }
+
+ if ((ip.s_addr == INADDR_ANY) ||
+#if (defined(BSD) && (BSD >= 199306))
+ in_broadcast(ip, &inp->inf_nif->nif_if) ||
+#else
+ in_broadcast(ip) ||
+#endif
+ IN_MULTICAST(ntohl(ip.s_addr))) {
+ err = EADDRNOTAVAIL;
+ break;
+ }
+
+ /*
+ * Notify the responsible ARP service
+ */
+ err = (*inp->inf_serv->is_ioctl)(code, data, inp->inf_isintf);
+ break;
+
+ case AIOCS_DEL_ARP:
+ /*
+ * Delete an ARP mapping
+ */
+ adp = (struct atmdelreq *)data;
+
+ /*
+ * Validate IP address
+ */
+ if (adp->adr_arp_dst.sa_family != AF_INET) {
+ err = EAFNOSUPPORT;
+ break;
+ }
+ ip = SATOSIN(&adp->adr_arp_dst)->sin_addr;
+
+ if (adp->adr_arp_intf[0] == '\0') {
+ /*
+ * Find the IP network interface associated with
+ * the supplied IP address
+ */
+ for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
+ if (ipatm_chknif(ip, inp) == 0)
+ break;
+ }
+ if (inp == NULL) {
+ err = EADDRNOTAVAIL;
+ break;
+ }
+ } else {
+ /*
+ * Find the specified IP network interface
+ */
+ if ((nip = atm_nifname(adp->adr_arp_intf)) == NULL) {
+ err = ENXIO;
+ break;
+ }
+ for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
+ if (inp->inf_nif == nip)
+ break;
+ }
+ if (inp == NULL) {
+ err = ENXIO;
+ break;
+ }
+ }
+
+ if ((ip.s_addr == INADDR_ANY) ||
+#if (defined(BSD) && (BSD >= 199306))
+ in_broadcast(ip, &inp->inf_nif->nif_if) ||
+#else
+ in_broadcast(ip) ||
+#endif
+ IN_MULTICAST(ntohl(ip.s_addr))) {
+ err = EADDRNOTAVAIL;
+ break;
+ }
+
+ /*
+ * Notify the responsible ARP service
+ */
+ err = (*inp->inf_serv->is_ioctl)(code, data, inp->inf_isintf);
+ break;
+
+ case AIOCS_INF_IPM:
+ /*
+ * Get IP VCC information
+ */
+ aip = (struct atminfreq *)data;
+
+ if (aip->air_ip_addr.sa_family != AF_INET)
+ break;
+ ip = SATOSIN(&aip->air_ip_addr)->sin_addr;
+
+ cp = aip->air_buf_addr;
+ space = aip->air_buf_len;
+
+ /*
+ * Loop through all our interfaces
+ */
+ for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
+ /*
+ * Check out each VCC
+ */
+ for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp;
+ ivp = Q_NEXT(ivp, struct ipvcc, iv_elem)) {
+
+ if ((ip.s_addr != INADDR_ANY) &&
+ (ip.s_addr != ivp->iv_dst.s_addr))
+ continue;
+
+ /*
+ * Make sure there's room in user buffer
+ */
+ if (space < sizeof(aivr)) {
+ err = ENOSPC;
+ break;
+ }
+
+ /*
+ * Fill in info to be returned
+ */
+ KM_ZERO((caddr_t)&aivr, sizeof(aivr));
+ SATOSIN(&aivr.aip_dst_addr)->sin_family =
+ AF_INET;
+ SATOSIN(&aivr.aip_dst_addr)->sin_addr.s_addr =
+ ivp->iv_dst.s_addr;
+ (void) sprintf(aivr.aip_intf, "%s%d",
+ inp->inf_nif->nif_if.if_name,
+ inp->inf_nif->nif_if.if_unit);
+ if ((ivp->iv_conn) &&
+ (ivp->iv_conn->co_connvc) &&
+ (vcp = ivp->iv_conn->co_connvc->cvc_vcc)) {
+ aivr.aip_vpi = vcp->vc_vpi;
+ aivr.aip_vci = vcp->vc_vci;
+ aivr.aip_sig_proto = vcp->vc_proto;
+ }
+ aivr.aip_flags = ivp->iv_flags;
+ aivr.aip_state = ivp->iv_state;
+
+ /*
+ * Copy data to user buffer and
+ * update buffer controls
+ */
+ err = copyout((caddr_t)&aivr, cp, sizeof(aivr));
+ if (err)
+ break;
+ cp += sizeof(aivr);
+ space -= sizeof(aivr);
+ }
+ if (err)
+ break;
+ }
+
+ /*
+ * Update buffer pointer/count
+ */
+ aip->air_buf_addr = cp;
+ aip->air_buf_len = space;
+ break;
+
+ default:
+ err = EOPNOTSUPP;
+ }
+
+ return (err);
+}
+
+
+/*
+ * Get Connection's Application/Owner Name
+ *
+ * Arguments:
+ * tok ipatm connection token (pointer to ipvcc)
+ *
+ * Returns:
+ * addr pointer to string containing our name
+ *
+ */
+caddr_t
+ipatm_getname(tok)
+ void *tok;
+{
+ return ("IP");
+}
+
OpenPOWER on IntegriCloud