summaryrefslogtreecommitdiff
path: root/sys/netns/ns_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netns/ns_output.c')
-rw-r--r--sys/netns/ns_output.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/sys/netns/ns_output.c b/sys/netns/ns_output.c
new file mode 100644
index 00000000000..4fc7320475d
--- /dev/null
+++ b/sys/netns/ns_output.c
@@ -0,0 +1,158 @@
+/* $NetBSD: ns_output.c,v 1.7 1995/06/13 08:37:07 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1984, 1985, 1986, 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ns_output.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#include <netns/idp.h>
+#include <netns/idp_var.h>
+
+int ns_hold_output = 0;
+int ns_copy_output = 0;
+int ns_output_cnt = 0;
+struct mbuf *ns_lastout;
+
+ns_output(m0, ro, flags)
+ struct mbuf *m0;
+ struct route *ro;
+ int flags;
+{
+ register struct idp *idp = mtod(m0, struct idp *);
+ register struct ifnet *ifp = 0;
+ int error = 0;
+ struct route idproute;
+ struct sockaddr_ns *dst;
+ extern int idpcksum;
+
+ if (ns_hold_output) {
+ if (ns_lastout) {
+ (void)m_free(ns_lastout);
+ }
+ ns_lastout = m_copy(m0, 0, (int)M_COPYALL);
+ }
+ /*
+ * Route packet.
+ */
+ if (ro == 0) {
+ ro = &idproute;
+ bzero((caddr_t)ro, sizeof (*ro));
+ }
+ dst = satosns(&ro->ro_dst);
+ if (ro->ro_rt == 0) {
+ dst->sns_family = AF_NS;
+ dst->sns_len = sizeof (*dst);
+ dst->sns_addr = idp->idp_dna;
+ dst->sns_addr.x_port = 0;
+ /*
+ * If routing to interface only,
+ * short circuit routing lookup.
+ */
+ if (flags & NS_ROUTETOIF) {
+ struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
+
+ if (ia == 0) {
+ error = ENETUNREACH;
+ goto bad;
+ }
+ ifp = ia->ia_ifp;
+ goto gotif;
+ }
+ rtalloc(ro);
+ } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) {
+ /*
+ * The old route has gone away; try for a new one.
+ */
+ rtfree(ro->ro_rt);
+ ro->ro_rt = NULL;
+ rtalloc(ro);
+ }
+ if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
+ error = ENETUNREACH;
+ goto bad;
+ }
+ ro->ro_rt->rt_use++;
+ if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST))
+ dst = satosns(ro->ro_rt->rt_gateway);
+gotif:
+
+ /*
+ * Look for multicast addresses and
+ * and verify user is allowed to send
+ * such a packet.
+ */
+ if (dst->sns_addr.x_host.c_host[0]&1) {
+ if ((ifp->if_flags & IFF_BROADCAST) == 0) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ if ((flags & NS_ALLOWBROADCAST) == 0) {
+ error = EACCES;
+ goto bad;
+ }
+ }
+
+ if (htons(idp->idp_len) <= ifp->if_mtu) {
+ ns_output_cnt++;
+ if (ns_copy_output) {
+ ns_watch_output(m0, ifp);
+ }
+ error = (*ifp->if_output)(ifp, m0, snstosa(dst), ro->ro_rt);
+ goto done;
+ } else error = EMSGSIZE;
+
+
+bad:
+ if (ns_copy_output) {
+ ns_watch_output(m0, ifp);
+ }
+ m_freem(m0);
+done:
+ if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) {
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = 0;
+ }
+ return (error);
+}