added my responsibility for the `cpm' port
[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 *
42524852 33 * from: @(#)ns_error.c 7.8 (Berkeley) 6/28/90
4c45483e 34 * $Id: ns_error.c,v 1.4 1993/11/07 17:50:25 wollman Exp $
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
8ace4366
GW
57struct ns_errstat ns_errstat;
58
15637ed4
RG
59#ifdef NS_ERRPRINTFS
60/*
61 * NS_ERR routines: error generation, receive packet processing, and
62 * routines to turnaround packets back to the originator.
63 */
64int ns_errprintfs = 0;
65#endif
66
4c45483e 67int
15637ed4 68ns_err_x(c)
4c45483e 69 int c;
15637ed4
RG
70{
71 register u_short *w, *lim, *base = ns_errstat.ns_es_codes;
72 u_short x = c;
73
74 /*
75 * zero is a legit error code, handle specially
76 */
77 if (x == 0)
78 return (0);
79 lim = base + NS_ERR_MAX - 1;
80 for (w = base + 1; w < lim; w++) {
81 if (*w == 0)
82 *w = x;
83 if (*w == x)
84 break;
85 }
86 return (w - base);
87}
88
89/*
90 * Generate an error packet of type error
91 * in response to bad packet.
92 */
4c45483e 93void
15637ed4
RG
94ns_error(om, type, param)
95 struct mbuf *om;
96 int type;
4c45483e 97 int param;
15637ed4
RG
98{
99 register struct ns_epidp *ep;
100 struct mbuf *m;
101 struct idp *nip;
102 register struct idp *oip = mtod(om, struct idp *);
103 extern int idpcksum;
104
105 /*
106 * If this packet was sent to the echo port,
107 * and nobody was there, just echo it.
108 * (Yes, this is a wart!)
109 */
110 if (type == NS_ERR_NOSOCK &&
111 oip->idp_dna.x_port == htons(2) &&
112 (type = ns_echo(om))==0)
113 return;
114
115#ifdef NS_ERRPRINTFS
116 if (ns_errprintfs)
117 printf("ns_err_error(%x, %d, %d)\n", oip, type, param);
118#endif
119 /*
120 * Don't Generate error packets in response to multicasts.
121 */
122 if (oip->idp_dna.x_host.c_host[0] & 1)
123 goto freeit;
124
125 ns_errstat.ns_es_error++;
126 /*
127 * Make sure that the old IDP packet had 30 bytes of data to return;
128 * if not, don't bother. Also don't EVER error if the old
129 * packet protocol was NS_ERR.
130 */
131 if (oip->idp_len < sizeof(struct idp)) {
132 ns_errstat.ns_es_oldshort++;
133 goto freeit;
134 }
135 if (oip->idp_pt == NSPROTO_ERROR) {
136 ns_errstat.ns_es_oldns_err++;
137 goto freeit;
138 }
139
140 /*
141 * First, formulate ns_err message
142 */
143 m = m_gethdr(M_DONTWAIT, MT_HEADER);
144 if (m == NULL)
145 goto freeit;
146 m->m_len = sizeof(*ep);
147 MH_ALIGN(m, m->m_len);
148 ep = mtod(m, struct ns_epidp *);
149 if ((u_int)type > NS_ERR_TOO_BIG)
150 panic("ns_err_error");
151 ns_errstat.ns_es_outhist[ns_err_x(type)]++;
152 ep->ns_ep_errp.ns_err_num = htons((u_short)type);
153 ep->ns_ep_errp.ns_err_param = htons((u_short)param);
154 bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42);
155 nip = &ep->ns_ep_idp;
156 nip->idp_len = sizeof(*ep);
157 nip->idp_len = htons((u_short)nip->idp_len);
158 nip->idp_pt = NSPROTO_ERROR;
159 nip->idp_tc = 0;
160 nip->idp_dna = oip->idp_sna;
161 nip->idp_sna = oip->idp_dna;
162 if (idpcksum) {
163 nip->idp_sum = 0;
164 nip->idp_sum = ns_cksum(m, sizeof(*ep));
165 } else
166 nip->idp_sum = 0xffff;
167 (void) ns_output(m, (struct route *)0, 0);
168
169freeit:
170 m_freem(om);
171}
172
4c45483e 173void
15637ed4 174ns_printhost(p)
4c45483e 175 register struct ns_addr *p;
15637ed4
RG
176{
177
178 printf("<net:%x%x,host:%x%x%x,port:%x>",
179 p->x_net.s_net[0],
180 p->x_net.s_net[1],
181 p->x_host.s_host[0],
182 p->x_host.s_host[1],
183 p->x_host.s_host[2],
184 p->x_port);
185
186}
187
188/*
189 * Process a received NS_ERR message.
190 */
4c45483e 191void
15637ed4
RG
192ns_err_input(m)
193 struct mbuf *m;
194{
195 register struct ns_errp *ep;
196 register struct ns_epidp *epidp = mtod(m, struct ns_epidp *);
197 register int i;
198 int type, code, param;
199
200 /*
201 * Locate ns_err structure in mbuf, and check
202 * that not corrupted and of at least minimum length.
203 */
204#ifdef NS_ERRPRINTFS
205 if (ns_errprintfs) {
206 printf("ns_err_input from ");
207 ns_printhost(&epidp->ns_ep_idp.idp_sna);
208 printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len));
209 }
210#endif
211 i = sizeof (struct ns_epidp);
212 if (((m->m_flags & M_EXT) || m->m_len < i) &&
213 (m = m_pullup(m, i)) == 0) {
214 ns_errstat.ns_es_tooshort++;
215 return;
216 }
217 ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp);
218 type = ntohs(ep->ns_err_num);
219 param = ntohs(ep->ns_err_param);
220 ns_errstat.ns_es_inhist[ns_err_x(type)]++;
221
222#ifdef NS_ERRPRINTFS
223 /*
224 * Message type specific processing.
225 */
226 if (ns_errprintfs)
227 printf("ns_err_input, type %d param %d\n", type, param);
228#endif
229 if (type >= NS_ERR_TOO_BIG) {
230 goto badcode;
231 }
232 ns_errstat.ns_es_outhist[ns_err_x(type)]++;
233 switch (type) {
234
235 case NS_ERR_UNREACH_HOST:
236 code = PRC_UNREACH_NET;
237 goto deliver;
238
239 case NS_ERR_TOO_OLD:
240 code = PRC_TIMXCEED_INTRANS;
241 goto deliver;
242
243 case NS_ERR_TOO_BIG:
244 code = PRC_MSGSIZE;
245 goto deliver;
246
247 case NS_ERR_FULLUP:
248 code = PRC_QUENCH;
249 goto deliver;
250
251 case NS_ERR_NOSOCK:
252 code = PRC_UNREACH_PORT;
253 goto deliver;
254
255 case NS_ERR_UNSPEC_T:
256 case NS_ERR_BADSUM_T:
257 case NS_ERR_BADSUM:
258 case NS_ERR_UNSPEC:
259 code = PRC_PARAMPROB;
260 goto deliver;
261
262 deliver:
263 /*
264 * Problem with datagram; advise higher level routines.
265 */
266#ifdef NS_ERRPRINTFS
267 if (ns_errprintfs)
268 printf("deliver to protocol %d\n",
269 ep->ns_err_idp.idp_pt);
270#endif
271 switch(ep->ns_err_idp.idp_pt) {
272 case NSPROTO_SPP:
273 spp_ctlinput(code, (caddr_t)ep);
274 break;
275
276 default:
277 idp_ctlinput(code, (caddr_t)ep);
278 }
279
280 goto freeit;
281
282 default:
283 badcode:
284 ns_errstat.ns_es_badcode++;
285 goto freeit;
286
287 }
288freeit:
289 m_freem(m);
290}
291
292#ifdef notdef
293u_long
294nstime()
295{
296 int s = splclock();
297 u_long t;
298
299 t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000;
300 splx(s);
301 return (htonl(t));
302}
303#endif
304
4c45483e 305int
15637ed4 306ns_echo(m)
4c45483e 307 struct mbuf *m;
15637ed4
RG
308{
309 register struct idp *idp = mtod(m, struct idp *);
310 register struct echo {
311 struct idp ec_idp;
312 u_short ec_op; /* Operation, 1 = request, 2 = reply */
313 } *ec = (struct echo *)idp;
314 struct ns_addr temp;
315
316 if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK);
317 if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC);
318
319 ec->ec_op = htons(2);
320
321 temp = idp->idp_dna;
322 idp->idp_dna = idp->idp_sna;
323 idp->idp_sna = temp;
324
325 if (idp->idp_sum != 0xffff) {
326 idp->idp_sum = 0;
327 idp->idp_sum = ns_cksum(m,
328 (int)(((ntohs(idp->idp_len) - 1)|1)+1));
329 }
330 (void) ns_output(m, (struct route *)0, NS_FORWARDING);
331 return(0);
332}