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