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