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