summaryrefslogtreecommitdiff
path: root/sys/netns/ns_error.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netns/ns_error.c')
-rw-r--r--sys/netns/ns_error.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/sys/netns/ns_error.c b/sys/netns/ns_error.c
new file mode 100644
index 00000000000..eb4a03999c8
--- /dev/null
+++ b/sys/netns/ns_error.c
@@ -0,0 +1,325 @@
+/* $NetBSD: ns_error.c,v 1.5 1994/06/29 06:41:36 cgd Exp $ */
+
+/*
+ * Copyright (c) 1984, 1988, 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_error.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+
+#include <net/route.h>
+
+#include <netns/ns.h>
+#include <netns/ns_pcb.h>
+#include <netns/idp.h>
+#include <netns/ns_error.h>
+
+#ifdef lint
+#define NS_ERRPRINTFS 1
+#endif
+
+#ifdef NS_ERRPRINTFS
+/*
+ * NS_ERR routines: error generation, receive packet processing, and
+ * routines to turnaround packets back to the originator.
+ */
+int ns_errprintfs = 0;
+#endif
+
+ns_err_x(c)
+{
+ register u_short *w, *lim, *base = ns_errstat.ns_es_codes;
+ u_short x = c;
+
+ /*
+ * zero is a legit error code, handle specially
+ */
+ if (x == 0)
+ return (0);
+ lim = base + NS_ERR_MAX - 1;
+ for (w = base + 1; w < lim; w++) {
+ if (*w == 0)
+ *w = x;
+ if (*w == x)
+ break;
+ }
+ return (w - base);
+}
+
+/*
+ * Generate an error packet of type error
+ * in response to bad packet.
+ */
+
+ns_error(om, type, param)
+ struct mbuf *om;
+ int type;
+{
+ register struct ns_epidp *ep;
+ struct mbuf *m;
+ struct idp *nip;
+ register struct idp *oip = mtod(om, struct idp *);
+ extern int idpcksum;
+
+ /*
+ * If this packet was sent to the echo port,
+ * and nobody was there, just echo it.
+ * (Yes, this is a wart!)
+ */
+ if (type == NS_ERR_NOSOCK &&
+ oip->idp_dna.x_port == htons(2) &&
+ (type = ns_echo(om))==0)
+ return;
+
+#ifdef NS_ERRPRINTFS
+ if (ns_errprintfs)
+ printf("ns_err_error(%x, %d, %d)\n", oip, type, param);
+#endif
+ /*
+ * Don't Generate error packets in response to multicasts.
+ */
+ if (oip->idp_dna.x_host.c_host[0] & 1)
+ goto freeit;
+
+ ns_errstat.ns_es_error++;
+ /*
+ * Make sure that the old IDP packet had 30 bytes of data to return;
+ * if not, don't bother. Also don't EVER error if the old
+ * packet protocol was NS_ERR.
+ */
+ if (oip->idp_len < sizeof(struct idp)) {
+ ns_errstat.ns_es_oldshort++;
+ goto freeit;
+ }
+ if (oip->idp_pt == NSPROTO_ERROR) {
+ ns_errstat.ns_es_oldns_err++;
+ goto freeit;
+ }
+
+ /*
+ * First, formulate ns_err message
+ */
+ m = m_gethdr(M_DONTWAIT, MT_HEADER);
+ if (m == NULL)
+ goto freeit;
+ m->m_len = sizeof(*ep);
+ MH_ALIGN(m, m->m_len);
+ ep = mtod(m, struct ns_epidp *);
+ if ((u_int)type > NS_ERR_TOO_BIG)
+ panic("ns_err_error");
+ ns_errstat.ns_es_outhist[ns_err_x(type)]++;
+ ep->ns_ep_errp.ns_err_num = htons((u_short)type);
+ ep->ns_ep_errp.ns_err_param = htons((u_short)param);
+ bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42);
+ nip = &ep->ns_ep_idp;
+ nip->idp_len = sizeof(*ep);
+ nip->idp_len = htons((u_short)nip->idp_len);
+ nip->idp_pt = NSPROTO_ERROR;
+ nip->idp_tc = 0;
+ nip->idp_dna = oip->idp_sna;
+ nip->idp_sna = oip->idp_dna;
+ if (idpcksum) {
+ nip->idp_sum = 0;
+ nip->idp_sum = ns_cksum(m, sizeof(*ep));
+ } else
+ nip->idp_sum = 0xffff;
+ (void) ns_output(m, (struct route *)0, 0);
+
+freeit:
+ m_freem(om);
+}
+
+ns_printhost(p)
+register struct ns_addr *p;
+{
+
+ printf("<net:%x%x,host:%x%x%x,port:%x>",
+ p->x_net.s_net[0],
+ p->x_net.s_net[1],
+ p->x_host.s_host[0],
+ p->x_host.s_host[1],
+ p->x_host.s_host[2],
+ p->x_port);
+
+}
+
+/*
+ * Process a received NS_ERR message.
+ */
+ns_err_input(m)
+ struct mbuf *m;
+{
+ register struct ns_errp *ep;
+ register struct ns_epidp *epidp = mtod(m, struct ns_epidp *);
+ register int i;
+ int type, code, param;
+
+ /*
+ * Locate ns_err structure in mbuf, and check
+ * that not corrupted and of at least minimum length.
+ */
+#ifdef NS_ERRPRINTFS
+ if (ns_errprintfs) {
+ printf("ns_err_input from ");
+ ns_printhost(&epidp->ns_ep_idp.idp_sna);
+ printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len));
+ }
+#endif
+ i = sizeof (struct ns_epidp);
+ if (((m->m_flags & M_EXT) || m->m_len < i) &&
+ (m = m_pullup(m, i)) == 0) {
+ ns_errstat.ns_es_tooshort++;
+ return;
+ }
+ ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp);
+ type = ntohs(ep->ns_err_num);
+ param = ntohs(ep->ns_err_param);
+ ns_errstat.ns_es_inhist[ns_err_x(type)]++;
+
+#ifdef NS_ERRPRINTFS
+ /*
+ * Message type specific processing.
+ */
+ if (ns_errprintfs)
+ printf("ns_err_input, type %d param %d\n", type, param);
+#endif
+ if (type >= NS_ERR_TOO_BIG) {
+ goto badcode;
+ }
+ ns_errstat.ns_es_outhist[ns_err_x(type)]++;
+ switch (type) {
+
+ case NS_ERR_UNREACH_HOST:
+ code = PRC_UNREACH_NET;
+ goto deliver;
+
+ case NS_ERR_TOO_OLD:
+ code = PRC_TIMXCEED_INTRANS;
+ goto deliver;
+
+ case NS_ERR_TOO_BIG:
+ code = PRC_MSGSIZE;
+ goto deliver;
+
+ case NS_ERR_FULLUP:
+ code = PRC_QUENCH;
+ goto deliver;
+
+ case NS_ERR_NOSOCK:
+ code = PRC_UNREACH_PORT;
+ goto deliver;
+
+ case NS_ERR_UNSPEC_T:
+ case NS_ERR_BADSUM_T:
+ case NS_ERR_BADSUM:
+ case NS_ERR_UNSPEC:
+ code = PRC_PARAMPROB;
+ goto deliver;
+
+ deliver:
+ /*
+ * Problem with datagram; advise higher level routines.
+ */
+#ifdef NS_ERRPRINTFS
+ if (ns_errprintfs)
+ printf("deliver to protocol %d\n",
+ ep->ns_err_idp.idp_pt);
+#endif
+ switch(ep->ns_err_idp.idp_pt) {
+ case NSPROTO_SPP:
+ spp_ctlinput(code, (caddr_t)ep);
+ break;
+
+ default:
+ idp_ctlinput(code, (caddr_t)ep);
+ }
+
+ goto freeit;
+
+ default:
+ badcode:
+ ns_errstat.ns_es_badcode++;
+ goto freeit;
+
+ }
+freeit:
+ m_freem(m);
+}
+
+#ifdef notdef
+u_long
+nstime()
+{
+ int s = splclock();
+ u_long t;
+
+ t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000;
+ splx(s);
+ return (htonl(t));
+}
+#endif
+
+ns_echo(m)
+struct mbuf *m;
+{
+ register struct idp *idp = mtod(m, struct idp *);
+ register struct echo {
+ struct idp ec_idp;
+ u_short ec_op; /* Operation, 1 = request, 2 = reply */
+ } *ec = (struct echo *)idp;
+ struct ns_addr temp;
+
+ if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK);
+ if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC);
+
+ ec->ec_op = htons(2);
+
+ temp = idp->idp_dna;
+ idp->idp_dna = idp->idp_sna;
+ idp->idp_sna = temp;
+
+ if (idp->idp_sum != 0xffff) {
+ idp->idp_sum = 0;
+ idp->idp_sum = ns_cksum(m,
+ (int)(((ntohs(idp->idp_len) - 1)|1)+1));
+ }
+ (void) ns_output(m, (struct route *)0, NS_FORWARDING);
+ return(0);
+}