xref: /original-bsd/sys/netns/ns_error.c (revision 28301386)
1 /*
2  * Copyright (c) 1984, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)ns_error.c	7.6 (Berkeley) 06/29/88
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "mbuf.h"
23 #include "protosw.h"
24 #include "socket.h"
25 #include "time.h"
26 #include "kernel.h"
27 
28 #include "../net/route.h"
29 
30 #include "ns.h"
31 #include "ns_pcb.h"
32 #include "idp.h"
33 #include "ns_error.h"
34 
35 #ifdef lint
36 #define NS_ERRPRINTFS 1
37 #endif
38 
39 #ifdef NS_ERRPRINTFS
40 /*
41  * NS_ERR routines: error generation, receive packet processing, and
42  * routines to turnaround packets back to the originator.
43  */
44 int	ns_errprintfs = 0;
45 #endif
46 
47 ns_err_x(c)
48 {
49 	register u_short *w, *lim, *base = ns_errstat.ns_es_codes;
50 	u_short x = c;
51 
52 	/*
53 	 * zero is a legit error code, handle specially
54 	 */
55 	if (x == 0)
56 		return (0);
57 	lim = base + NS_ERR_MAX - 1;
58 	for (w = base + 1; w < lim; w++) {
59 		if (*w == 0)
60 			*w = x;
61 		if (*w == x)
62 			break;
63 	}
64 	return (w - base);
65 }
66 
67 /*
68  * Generate an error packet of type error
69  * in response to bad packet.
70  */
71 
72 ns_error(om, type, param)
73 	struct mbuf *om;
74 	int type;
75 {
76 	register struct ns_epidp *ep;
77 	struct mbuf *m;
78 	struct idp *nip;
79 	register struct idp *oip = mtod(om, struct idp *);
80 	extern int idpcksum;
81 
82 	/*
83 	 * If this packet was sent to the echo port,
84 	 * and nobody was there, just echo it.
85 	 * (Yes, this is a wart!)
86 	 */
87 	if (type==NS_ERR_NOSOCK &&
88 	    oip->idp_dna.x_port==htons(2) &&
89 	    (type = ns_echo(oip)==0))
90 		return;
91 
92 #ifdef NS_ERRPRINTFS
93 	if (ns_errprintfs)
94 		printf("ns_err_error(%x, %d, %d)\n", oip, type, param);
95 #endif
96 	/*
97 	 * Don't Generate error packets in response to multicasts.
98 	 */
99 	if (oip->idp_dna.x_host.c_host[0] & 1)
100 		goto free;
101 
102 	ns_errstat.ns_es_error++;
103 	/*
104 	 * Make sure that the old IDP packet had 30 bytes of data to return;
105 	 * if not, don't bother.  Also don't EVER error if the old
106 	 * packet protocol was NS_ERR.
107 	 */
108 	if (oip->idp_len < sizeof(struct idp)) {
109 		ns_errstat.ns_es_oldshort++;
110 		goto free;
111 	}
112 	if (oip->idp_pt == NSPROTO_ERROR) {
113 		ns_errstat.ns_es_oldns_err++;
114 		goto free;
115 	}
116 
117 	/*
118 	 * First, formulate ns_err message
119 	 */
120 	m = m_get(M_DONTWAIT, MT_HEADER);
121 	if (m == NULL)
122 		goto free;
123 	m->m_len = sizeof(*ep);
124 	m->m_off = MMAXOFF - m->m_len;
125 	ep = mtod(m, struct ns_epidp *);
126 	if ((u_int)type > NS_ERR_TOO_BIG)
127 		panic("ns_err_error");
128 	ns_errstat.ns_es_outhist[ns_err_x(type)]++;
129 	ep->ns_ep_errp.ns_err_num = htons((u_short)type);
130 	ep->ns_ep_errp.ns_err_param = htons((u_short)param);
131 	bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42);
132 	nip = &ep->ns_ep_idp;
133 	nip->idp_len = sizeof(*ep);
134 	nip->idp_len = htons((u_short)nip->idp_len);
135 	nip->idp_pt = NSPROTO_ERROR;
136 	nip->idp_tc = 0;
137 	nip->idp_dna = oip->idp_sna;
138 	nip->idp_sna = oip->idp_dna;
139 	if (idpcksum) {
140 		nip->idp_sum = 0;
141 		nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep));
142 	} else
143 		nip->idp_sum = 0xffff;
144 	(void) ns_output(dtom(nip), (struct route *)0, 0);
145 
146 free:
147 	m_freem(dtom(oip));
148 }
149 
150 ns_printhost(p)
151 register struct ns_addr *p;
152 {
153 
154 	printf("<net:%x%x,host:%x%x%x,port:%x>",
155 			p->x_net.s_net[0],
156 			p->x_net.s_net[1],
157 			p->x_host.s_host[0],
158 			p->x_host.s_host[1],
159 			p->x_host.s_host[2],
160 			p->x_port);
161 
162 }
163 
164 /*
165  * Process a received NS_ERR message.
166  */
167 ns_err_input(m)
168 	struct mbuf *m;
169 {
170 	register struct ns_errp *ep;
171 	register struct ns_epidp *epidp = mtod(m, struct ns_epidp *);
172 	register int i;
173 	int type, code, param;
174 
175 	/*
176 	 * Locate ns_err structure in mbuf, and check
177 	 * that not corrupted and of at least minimum length.
178 	 */
179 #ifdef NS_ERRPRINTFS
180 	if (ns_errprintfs) {
181 		printf("ns_err_input from ");
182 		ns_printhost(&epidp->ns_ep_idp.idp_sna);
183 		printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len));
184 	}
185 #endif
186 	i = sizeof (struct ns_epidp);
187  	if ((m->m_off > MMAXOFF || m->m_len < i) &&
188  		(m = m_pullup(m, i)) == 0)  {
189 		ns_errstat.ns_es_tooshort++;
190 		return;
191 	}
192 	ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp);
193 	type = ntohs(ep->ns_err_num);
194 	param = ntohs(ep->ns_err_param);
195 	ns_errstat.ns_es_inhist[ns_err_x(type)]++;
196 
197 #ifdef NS_ERRPRINTFS
198 	/*
199 	 * Message type specific processing.
200 	 */
201 	if (ns_errprintfs)
202 		printf("ns_err_input, type %d param %d\n", type, param);
203 #endif
204 	if (type >= NS_ERR_TOO_BIG) {
205 		goto badcode;
206 	}
207 	ns_errstat.ns_es_outhist[ns_err_x(type)]++;
208 	switch (type) {
209 
210 	case NS_ERR_UNREACH_HOST:
211 		code = PRC_UNREACH_NET;
212 		goto deliver;
213 
214 	case NS_ERR_TOO_OLD:
215 		code = PRC_TIMXCEED_INTRANS;
216 		goto deliver;
217 
218 	case NS_ERR_TOO_BIG:
219 		code = PRC_MSGSIZE;
220 		goto deliver;
221 
222 	case NS_ERR_FULLUP:
223 		code = PRC_QUENCH;
224 		goto deliver;
225 
226 	case NS_ERR_NOSOCK:
227 		code = PRC_UNREACH_PORT;
228 		goto deliver;
229 
230 	case NS_ERR_UNSPEC_T:
231 	case NS_ERR_BADSUM_T:
232 	case NS_ERR_BADSUM:
233 	case NS_ERR_UNSPEC:
234 		code = PRC_PARAMPROB;
235 		goto deliver;
236 
237 	deliver:
238 		/*
239 		 * Problem with datagram; advise higher level routines.
240 		 */
241 #ifdef NS_ERRPRINTFS
242 		if (ns_errprintfs)
243 			printf("deliver to protocol %d\n",
244 				       ep->ns_err_idp.idp_pt);
245 #endif
246 		switch(ep->ns_err_idp.idp_pt) {
247 		case NSPROTO_SPP:
248 			spp_ctlinput(code, (caddr_t)ep);
249 			break;
250 
251 		default:
252 			idp_ctlinput(code, (caddr_t)ep);
253 		}
254 
255 		goto free;
256 
257 	default:
258 	badcode:
259 		ns_errstat.ns_es_badcode++;
260 		goto free;
261 
262 	}
263 free:
264 	m_freem(m);
265 }
266 
267 #ifdef notdef
268 u_long
269 nstime()
270 {
271 	int s = splclock();
272 	u_long t;
273 
274 	t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000;
275 	splx(s);
276 	return (htonl(t));
277 }
278 #endif
279 
280 ns_echo(idp)
281 register struct idp *idp;
282 {
283 	struct mbuf *m = dtom(idp);
284 	register struct echo {
285 	    struct idp	ec_idp;
286 	    u_short		ec_op; /* Operation, 1 = request, 2 = reply */
287 	} *ec = (struct echo *)idp;
288 	struct ns_addr temp;
289 
290 	if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK);
291 	if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC);
292 
293 	ec->ec_op = htons(2);
294 
295 	temp = idp->idp_dna;
296 	idp->idp_dna = idp->idp_sna;
297 	idp->idp_sna = temp;
298 
299 	if (idp->idp_sum != 0xffff) {
300 		idp->idp_sum = 0;
301 		idp->idp_sum = ns_cksum(m,
302 		    (int)(((ntohs(idp->idp_len) - 1)|1)+1));
303 	}
304 	(void) ns_output(m, (struct route *)0, NS_FORWARDING);
305 	return(0);
306 }
307