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