summaryrefslogtreecommitdiffstats
path: root/sys/netatm/ipatm/ipatm_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netatm/ipatm/ipatm_if.c')
-rw-r--r--sys/netatm/ipatm/ipatm_if.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/sys/netatm/ipatm/ipatm_if.c b/sys/netatm/ipatm/ipatm_if.c
new file mode 100644
index 0000000..ede2450
--- /dev/null
+++ b/sys/netatm/ipatm/ipatm_if.c
@@ -0,0 +1,335 @@
+/*
+ *
+ * ===================================
+ * 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_if.c,v 1.6 1998/03/24 20:51:47 mks Exp $
+ *
+ */
+
+/*
+ * IP Over ATM Support
+ * -------------------
+ *
+ * Interface Manager
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: ipatm_if.c,v 1.6 1998/03/24 20:51:47 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>
+
+
+/*
+ * Local functions
+ */
+static void ipatm_closenif __P((struct ip_nif *));
+
+
+/*
+ * Process Network Interface status change
+ *
+ * Called whenever a network interface status change is requested.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * cmd command code
+ * nip pointer to atm network interface control block
+ * arg command specific parameter
+ *
+ * Returns:
+ * 0 command successful
+ * errno command failed - reason indicated
+ *
+ */
+int
+ipatm_nifstat(cmd, nip, arg)
+ int cmd;
+ struct atm_nif *nip;
+ int arg;
+{
+ struct in_ifaddr *ia;
+ struct siginst *sip;
+ struct ip_nif *inp;
+ int err = 0;
+
+ /*
+ * Look for corresponding IP interface
+ */
+ for (inp = ipatm_nif_head; inp; inp = inp->inf_next) {
+ if (inp->inf_nif == nip)
+ break;
+ }
+
+ /*
+ * Process command
+ */
+ switch (cmd) {
+
+ case NCM_ATTACH:
+ /*
+ * Make sure i/f isn't already attached
+ */
+ if (inp != NULL) {
+ err = EEXIST;
+ break;
+ }
+
+ /*
+ * Get a new interface block
+ */
+ inp = (struct ip_nif *)atm_allocate(&ipatm_nifpool);
+ if (inp == NULL) {
+ err = ENOMEM;
+ break;
+ }
+ inp->inf_nif = nip;
+ inp->inf_state = IPNIF_ADDR;
+ inp->inf_arpnotify = ipatm_arpnotify;
+ inp->inf_ipinput = ipatm_ipinput;
+ inp->inf_createsvc = ipatm_createsvc;
+ LINK2TAIL(inp, struct ip_nif, ipatm_nif_head, inf_next);
+ break;
+
+ case NCM_DETACH:
+ /*
+ * Make sure i/f is attached
+ */
+ if (inp == NULL) {
+ err = ENODEV;
+ break;
+ }
+
+ /*
+ * Validate interface stuff
+ */
+ if (Q_HEAD(inp->inf_vcq, struct ipvcc))
+ panic("ipatm_nifstat: ipvcc queue not empty");
+
+ /*
+ * If we're active, close all our VCCs and tell the
+ * interface service about the deactivation
+ */
+ if (inp->inf_state == IPNIF_ACTIVE) {
+
+ ipatm_closenif(inp);
+
+ if (inp->inf_serv)
+ (void) (*inp->inf_serv->is_ifdact)(inp);
+ }
+
+ /*
+ * Clean up and free block
+ */
+ UNLINK(inp, struct ip_nif, ipatm_nif_head, inf_next);
+ atm_free((caddr_t)inp);
+ break;
+
+ case NCM_SETADDR:
+ /*
+ * We only care about IP addresses
+ */
+#if (defined(BSD) && (BSD >= 199103))
+ if (((struct ifaddr *)arg)->ifa_addr->sa_family != AF_INET)
+#else
+ if (((struct ifaddr *)arg)->ifa_addr.sa_family != AF_INET)
+#endif
+ break;
+
+ /*
+ * Make sure i/f is there
+ */
+ ia = (struct in_ifaddr *)arg;
+ if (inp == NULL)
+ panic("ipatm_nifstat: setaddr missing ip_nif");
+
+ /*
+ * Process new address
+ */
+ switch (inp->inf_state) {
+
+ case IPNIF_SIGMGR:
+ case IPNIF_ADDR:
+ inp->inf_addr = ia;
+
+ /*
+ * If signalling manager is not set, wait for it
+ */
+ sip = nip->nif_pif->pif_siginst;
+ if (sip == NULL) {
+ inp->inf_state = IPNIF_SIGMGR;
+ break;
+ }
+
+ /*
+ * Otherwise, everything's set
+ */
+ inp->inf_state = IPNIF_ACTIVE;
+
+ /*
+ * Tell interface service we're around
+ */
+ if (sip->si_ipserv) {
+ inp->inf_serv = sip->si_ipserv;
+ err = (*inp->inf_serv->is_ifact)(inp);
+ }
+
+ /*
+ * Reset state if there's been a problem
+ */
+ if (err) {
+ inp->inf_serv = NULL;
+ inp->inf_addr = NULL;
+ inp->inf_state = IPNIF_ADDR;
+ }
+ break;
+
+ case IPNIF_ACTIVE:
+ /*
+ * We dont support an address change
+ */
+ err = EEXIST;
+ break;
+ }
+ break;
+
+ case NCM_SIGATTACH:
+ /*
+ * Make sure i/f is attached
+ */
+ if (inp == NULL) {
+ err = ENODEV;
+ break;
+ }
+
+ /*
+ * Are we waiting for the sigmgr attach??
+ */
+ if (inp->inf_state != IPNIF_SIGMGR) {
+ /*
+ * No, nothing else to do
+ */
+ break;
+ }
+
+ /*
+ * OK, everything's set
+ */
+ inp->inf_state = IPNIF_ACTIVE;
+
+ /*
+ * Tell interface service we're around
+ */
+ sip = nip->nif_pif->pif_siginst;
+ if (sip->si_ipserv) {
+ inp->inf_serv = sip->si_ipserv;
+ err = (*inp->inf_serv->is_ifact)(inp);
+ }
+
+ /*
+ * Just report any problems, since a NCM_SIGDETACH will
+ * be coming down immediately
+ */
+ break;
+
+ case NCM_SIGDETACH:
+ /*
+ * Make sure i/f is attached
+ */
+ if (inp == NULL) {
+ err = ENODEV;
+ break;
+ }
+
+ /*
+ * Are we currently active??
+ */
+ if (inp->inf_state != IPNIF_ACTIVE) {
+ /*
+ * No, nothing else to do
+ */
+ break;
+ }
+
+ /*
+ * Close all the IP VCCs for this interface
+ */
+ ipatm_closenif(inp);
+
+ /*
+ * Tell interface service that i/f has gone down
+ */
+ if (inp->inf_serv)
+ (void) (*inp->inf_serv->is_ifdact)(inp);
+
+ /*
+ * Just have to wait for another sigattach
+ */
+ inp->inf_serv = NULL;
+ inp->inf_state = IPNIF_SIGMGR;
+ break;
+
+ default:
+ log(LOG_ERR, "ipatm_nifstat: unknown command %d\n", cmd);
+ }
+
+ return (err);
+}
+
+
+/*
+ * Close all VCCs on a Network Interface
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * inp pointer to IP network interface
+ *
+ * Returns:
+ * none
+ *
+ */
+static void
+ipatm_closenif(inp)
+ struct ip_nif *inp;
+{
+ struct ipvcc *ivp, *inext;
+
+ /*
+ * Close each IP VCC on this interface
+ */
+ for (ivp = Q_HEAD(inp->inf_vcq, struct ipvcc); ivp; ivp = inext) {
+
+ inext = Q_NEXT(ivp, struct ipvcc, iv_elem);
+
+ (void) ipatm_closevc(ivp, T_ATM_CAUSE_UNSPECIFIED_NORMAL);
+ }
+}
+
OpenPOWER on IntegriCloud