xref: /csrg-svn/sys/netns/ns_error.c (revision 63231)
123206Smckusick /*
2*63231Sbostic  * Copyright (c) 1984, 1988, 1993
3*63231Sbostic  *	The Regents of the University of California.  All rights reserved.
423206Smckusick  *
544502Sbostic  * %sccs.include.redist.c%
633371Ssklower  *
7*63231Sbostic  *	@(#)ns_error.c	8.1 (Berkeley) 06/10/93
823206Smckusick  */
921483Ssklower 
1056534Sbostic #include <sys/param.h>
1156534Sbostic #include <sys/systm.h>
1256534Sbostic #include <sys/malloc.h>
1356534Sbostic #include <sys/mbuf.h>
1456534Sbostic #include <sys/protosw.h>
1556534Sbostic #include <sys/socket.h>
1656534Sbostic #include <sys/time.h>
1756534Sbostic #include <sys/kernel.h>
1821483Ssklower 
1956534Sbostic #include <net/route.h>
2021483Ssklower 
2156534Sbostic #include <netns/ns.h>
2256534Sbostic #include <netns/ns_pcb.h>
2356534Sbostic #include <netns/idp.h>
2456534Sbostic #include <netns/ns_error.h>
2521483Ssklower 
2624226Ssklower #ifdef lint
2724226Ssklower #define NS_ERRPRINTFS 1
2824226Ssklower #endif
2924226Ssklower 
3021483Ssklower #ifdef NS_ERRPRINTFS
3121483Ssklower /*
3221483Ssklower  * NS_ERR routines: error generation, receive packet processing, and
3321746Ssklower  * routines to turnaround packets back to the originator.
3421483Ssklower  */
3521483Ssklower int	ns_errprintfs = 0;
3621483Ssklower #endif
3721483Ssklower 
3833429Smckusick ns_err_x(c)
3933411Ssklower {
4033411Ssklower 	register u_short *w, *lim, *base = ns_errstat.ns_es_codes;
4133411Ssklower 	u_short x = c;
4233411Ssklower 
4333411Ssklower 	/*
4433411Ssklower 	 * zero is a legit error code, handle specially
4533411Ssklower 	 */
4633411Ssklower 	if (x == 0)
4733411Ssklower 		return (0);
4833411Ssklower 	lim = base + NS_ERR_MAX - 1;
4933411Ssklower 	for (w = base + 1; w < lim; w++) {
5033411Ssklower 		if (*w == 0)
5133411Ssklower 			*w = x;
5233411Ssklower 		if (*w == x)
5333411Ssklower 			break;
5433411Ssklower 	}
5533411Ssklower 	return (w - base);
5633411Ssklower }
5733411Ssklower 
5821483Ssklower /*
5921483Ssklower  * Generate an error packet of type error
6021483Ssklower  * in response to bad packet.
6121483Ssklower  */
6221483Ssklower 
6321483Ssklower ns_error(om, type, param)
6421483Ssklower 	struct mbuf *om;
6521483Ssklower 	int type;
6621483Ssklower {
6721483Ssklower 	register struct ns_epidp *ep;
6821483Ssklower 	struct mbuf *m;
6921483Ssklower 	struct idp *nip;
7021483Ssklower 	register struct idp *oip = mtod(om, struct idp *);
7121483Ssklower 	extern int idpcksum;
7221483Ssklower 
7321746Ssklower 	/*
7421746Ssklower 	 * If this packet was sent to the echo port,
7521746Ssklower 	 * and nobody was there, just echo it.
7621746Ssklower 	 * (Yes, this is a wart!)
7721746Ssklower 	 */
7837473Ssklower 	if (type == NS_ERR_NOSOCK &&
7937473Ssklower 	    oip->idp_dna.x_port == htons(2) &&
8037473Ssklower 	    (type = ns_echo(om))==0)
8121746Ssklower 		return;
8221746Ssklower 
8321483Ssklower #ifdef NS_ERRPRINTFS
8421483Ssklower 	if (ns_errprintfs)
8521483Ssklower 		printf("ns_err_error(%x, %d, %d)\n", oip, type, param);
8621483Ssklower #endif
8723980Ssklower 	/*
8823980Ssklower 	 * Don't Generate error packets in response to multicasts.
8923980Ssklower 	 */
9023980Ssklower 	if (oip->idp_dna.x_host.c_host[0] & 1)
9137473Ssklower 		goto freeit;
9223980Ssklower 
9321483Ssklower 	ns_errstat.ns_es_error++;
9421483Ssklower 	/*
9521483Ssklower 	 * Make sure that the old IDP packet had 30 bytes of data to return;
9621483Ssklower 	 * if not, don't bother.  Also don't EVER error if the old
9721483Ssklower 	 * packet protocol was NS_ERR.
9821483Ssklower 	 */
9921483Ssklower 	if (oip->idp_len < sizeof(struct idp)) {
10021483Ssklower 		ns_errstat.ns_es_oldshort++;
10137473Ssklower 		goto freeit;
10221483Ssklower 	}
10321483Ssklower 	if (oip->idp_pt == NSPROTO_ERROR) {
10421483Ssklower 		ns_errstat.ns_es_oldns_err++;
10537473Ssklower 		goto freeit;
10621483Ssklower 	}
10721483Ssklower 
10821483Ssklower 	/*
10921483Ssklower 	 * First, formulate ns_err message
11021483Ssklower 	 */
11137473Ssklower 	m = m_gethdr(M_DONTWAIT, MT_HEADER);
11221483Ssklower 	if (m == NULL)
11337473Ssklower 		goto freeit;
11421483Ssklower 	m->m_len = sizeof(*ep);
11537473Ssklower 	MH_ALIGN(m, m->m_len);
11621483Ssklower 	ep = mtod(m, struct ns_epidp *);
11721483Ssklower 	if ((u_int)type > NS_ERR_TOO_BIG)
11821483Ssklower 		panic("ns_err_error");
11921483Ssklower 	ns_errstat.ns_es_outhist[ns_err_x(type)]++;
12024226Ssklower 	ep->ns_ep_errp.ns_err_num = htons((u_short)type);
12124226Ssklower 	ep->ns_ep_errp.ns_err_param = htons((u_short)param);
12221483Ssklower 	bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42);
12321483Ssklower 	nip = &ep->ns_ep_idp;
12421483Ssklower 	nip->idp_len = sizeof(*ep);
12521483Ssklower 	nip->idp_len = htons((u_short)nip->idp_len);
12621483Ssklower 	nip->idp_pt = NSPROTO_ERROR;
12721483Ssklower 	nip->idp_tc = 0;
12821483Ssklower 	nip->idp_dna = oip->idp_sna;
12921483Ssklower 	nip->idp_sna = oip->idp_dna;
13021483Ssklower 	if (idpcksum) {
13121483Ssklower 		nip->idp_sum = 0;
13237473Ssklower 		nip->idp_sum = ns_cksum(m, sizeof(*ep));
13321483Ssklower 	} else
13421483Ssklower 		nip->idp_sum = 0xffff;
13537473Ssklower 	(void) ns_output(m, (struct route *)0, 0);
13621483Ssklower 
13737473Ssklower freeit:
13837473Ssklower 	m_freem(om);
13921483Ssklower }
14021483Ssklower 
14121483Ssklower ns_printhost(p)
14221483Ssklower register struct ns_addr *p;
14321483Ssklower {
14421483Ssklower 
14521483Ssklower 	printf("<net:%x%x,host:%x%x%x,port:%x>",
14621483Ssklower 			p->x_net.s_net[0],
14721483Ssklower 			p->x_net.s_net[1],
14821483Ssklower 			p->x_host.s_host[0],
14921483Ssklower 			p->x_host.s_host[1],
15021483Ssklower 			p->x_host.s_host[2],
15121483Ssklower 			p->x_port);
15221483Ssklower 
15321483Ssklower }
15421483Ssklower 
15521483Ssklower /*
15621483Ssklower  * Process a received NS_ERR message.
15721483Ssklower  */
15821483Ssklower ns_err_input(m)
15921483Ssklower 	struct mbuf *m;
16021483Ssklower {
16121483Ssklower 	register struct ns_errp *ep;
16221483Ssklower 	register struct ns_epidp *epidp = mtod(m, struct ns_epidp *);
16321483Ssklower 	register int i;
16421483Ssklower 	int type, code, param;
16521483Ssklower 
16621483Ssklower 	/*
16721483Ssklower 	 * Locate ns_err structure in mbuf, and check
16821483Ssklower 	 * that not corrupted and of at least minimum length.
16921483Ssklower 	 */
17021483Ssklower #ifdef NS_ERRPRINTFS
17121483Ssklower 	if (ns_errprintfs) {
17221483Ssklower 		printf("ns_err_input from ");
17321483Ssklower 		ns_printhost(&epidp->ns_ep_idp.idp_sna);
17421483Ssklower 		printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len));
17521483Ssklower 	}
17621483Ssklower #endif
17721483Ssklower 	i = sizeof (struct ns_epidp);
17837473Ssklower  	if (((m->m_flags & M_EXT) || m->m_len < i) &&
17921483Ssklower  		(m = m_pullup(m, i)) == 0)  {
18021483Ssklower 		ns_errstat.ns_es_tooshort++;
18121483Ssklower 		return;
18221483Ssklower 	}
18321483Ssklower 	ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp);
18421483Ssklower 	type = ntohs(ep->ns_err_num);
18521483Ssklower 	param = ntohs(ep->ns_err_param);
18623980Ssklower 	ns_errstat.ns_es_inhist[ns_err_x(type)]++;
18721483Ssklower 
18821483Ssklower #ifdef NS_ERRPRINTFS
18921483Ssklower 	/*
19021483Ssklower 	 * Message type specific processing.
19121483Ssklower 	 */
19221483Ssklower 	if (ns_errprintfs)
19321483Ssklower 		printf("ns_err_input, type %d param %d\n", type, param);
19421483Ssklower #endif
19521483Ssklower 	if (type >= NS_ERR_TOO_BIG) {
19621483Ssklower 		goto badcode;
19721483Ssklower 	}
19821483Ssklower 	ns_errstat.ns_es_outhist[ns_err_x(type)]++;
19921483Ssklower 	switch (type) {
20021483Ssklower 
20121483Ssklower 	case NS_ERR_UNREACH_HOST:
20221483Ssklower 		code = PRC_UNREACH_NET;
20321483Ssklower 		goto deliver;
20421483Ssklower 
20521483Ssklower 	case NS_ERR_TOO_OLD:
20621483Ssklower 		code = PRC_TIMXCEED_INTRANS;
20721483Ssklower 		goto deliver;
20821483Ssklower 
20921483Ssklower 	case NS_ERR_TOO_BIG:
21021483Ssklower 		code = PRC_MSGSIZE;
21121483Ssklower 		goto deliver;
21221483Ssklower 
21321483Ssklower 	case NS_ERR_FULLUP:
21421483Ssklower 		code = PRC_QUENCH;
21521483Ssklower 		goto deliver;
21621483Ssklower 
21721483Ssklower 	case NS_ERR_NOSOCK:
21821483Ssklower 		code = PRC_UNREACH_PORT;
21921483Ssklower 		goto deliver;
22021483Ssklower 
22121483Ssklower 	case NS_ERR_UNSPEC_T:
22221483Ssklower 	case NS_ERR_BADSUM_T:
22321483Ssklower 	case NS_ERR_BADSUM:
22421483Ssklower 	case NS_ERR_UNSPEC:
22521483Ssklower 		code = PRC_PARAMPROB;
22621483Ssklower 		goto deliver;
22721483Ssklower 
22821483Ssklower 	deliver:
22921483Ssklower 		/*
23021483Ssklower 		 * Problem with datagram; advise higher level routines.
23121483Ssklower 		 */
23221483Ssklower #ifdef NS_ERRPRINTFS
23321483Ssklower 		if (ns_errprintfs)
23421483Ssklower 			printf("deliver to protocol %d\n",
23521483Ssklower 				       ep->ns_err_idp.idp_pt);
23621483Ssklower #endif
23721483Ssklower 		switch(ep->ns_err_idp.idp_pt) {
23821483Ssklower 		case NSPROTO_SPP:
23921483Ssklower 			spp_ctlinput(code, (caddr_t)ep);
24021483Ssklower 			break;
24121483Ssklower 
24221483Ssklower 		default:
24321483Ssklower 			idp_ctlinput(code, (caddr_t)ep);
24421483Ssklower 		}
24521483Ssklower 
24637473Ssklower 		goto freeit;
24721483Ssklower 
24821483Ssklower 	default:
24921483Ssklower 	badcode:
25021483Ssklower 		ns_errstat.ns_es_badcode++;
25137473Ssklower 		goto freeit;
25221483Ssklower 
25321483Ssklower 	}
25437473Ssklower freeit:
25521483Ssklower 	m_freem(m);
25621483Ssklower }
25721746Ssklower 
25828956Skarels #ifdef notdef
25921483Ssklower u_long
26021483Ssklower nstime()
26121483Ssklower {
26229924Skarels 	int s = splclock();
26321483Ssklower 	u_long t;
26421483Ssklower 
26521483Ssklower 	t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000;
26621483Ssklower 	splx(s);
26721483Ssklower 	return (htonl(t));
26821483Ssklower }
26928956Skarels #endif
27021746Ssklower 
27137473Ssklower ns_echo(m)
27237473Ssklower struct mbuf *m;
27321746Ssklower {
27437473Ssklower 	register struct idp *idp = mtod(m, struct idp *);
27521746Ssklower 	register struct echo {
27621746Ssklower 	    struct idp	ec_idp;
27721746Ssklower 	    u_short		ec_op; /* Operation, 1 = request, 2 = reply */
27821746Ssklower 	} *ec = (struct echo *)idp;
27921746Ssklower 	struct ns_addr temp;
28021746Ssklower 
28121746Ssklower 	if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK);
28221746Ssklower 	if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC);
28321746Ssklower 
28421746Ssklower 	ec->ec_op = htons(2);
28521746Ssklower 
28621746Ssklower 	temp = idp->idp_dna;
28721746Ssklower 	idp->idp_dna = idp->idp_sna;
28821746Ssklower 	idp->idp_sna = temp;
28921746Ssklower 
29021746Ssklower 	if (idp->idp_sum != 0xffff) {
29121746Ssklower 		idp->idp_sum = 0;
29228956Skarels 		idp->idp_sum = ns_cksum(m,
29328956Skarels 		    (int)(((ntohs(idp->idp_len) - 1)|1)+1));
29421746Ssklower 	}
29526389Skarels 	(void) ns_output(m, (struct route *)0, NS_FORWARDING);
29621746Ssklower 	return(0);
29721746Ssklower }
298