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