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