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