xref: /original-bsd/sys/netns/ns_error.c (revision 785337c1)
1 /*
2  * Copyright (c) 1984, 1985, 1986 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	7.2 (Berkeley) 10/28/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 
144 	/*
145 	 * Locate ns_err structure in mbuf, and check
146 	 * that not corrupted and of at least minimum length.
147 	 */
148 #ifdef NS_ERRPRINTFS
149 	if (ns_errprintfs) {
150 		printf("ns_err_input from ");
151 		ns_printhost(&epidp->ns_ep_idp.idp_sna);
152 		printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len));
153 	}
154 #endif
155 	i = sizeof (struct ns_epidp);
156  	if ((m->m_off > MMAXOFF || m->m_len < i) &&
157  		(m = m_pullup(m, i)) == 0)  {
158 		ns_errstat.ns_es_tooshort++;
159 		return;
160 	}
161 	ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp);
162 	type = ntohs(ep->ns_err_num);
163 	param = ntohs(ep->ns_err_param);
164 	ns_errstat.ns_es_inhist[ns_err_x(type)]++;
165 
166 #ifdef NS_ERRPRINTFS
167 	/*
168 	 * Message type specific processing.
169 	 */
170 	if (ns_errprintfs)
171 		printf("ns_err_input, type %d param %d\n", type, param);
172 #endif
173 	if (type >= NS_ERR_TOO_BIG) {
174 		goto badcode;
175 	}
176 	ns_errstat.ns_es_outhist[ns_err_x(type)]++;
177 	switch (type) {
178 
179 	case NS_ERR_UNREACH_HOST:
180 		code = PRC_UNREACH_NET;
181 		goto deliver;
182 
183 	case NS_ERR_TOO_OLD:
184 		code = PRC_TIMXCEED_INTRANS;
185 		goto deliver;
186 
187 	case NS_ERR_TOO_BIG:
188 		code = PRC_MSGSIZE;
189 		goto deliver;
190 
191 	case NS_ERR_FULLUP:
192 		code = PRC_QUENCH;
193 		goto deliver;
194 
195 	case NS_ERR_NOSOCK:
196 		code = PRC_UNREACH_PORT;
197 		goto deliver;
198 
199 	case NS_ERR_UNSPEC_T:
200 	case NS_ERR_BADSUM_T:
201 	case NS_ERR_BADSUM:
202 	case NS_ERR_UNSPEC:
203 		code = PRC_PARAMPROB;
204 		goto deliver;
205 
206 	deliver:
207 		/*
208 		 * Problem with datagram; advise higher level routines.
209 		 */
210 #ifdef NS_ERRPRINTFS
211 		if (ns_errprintfs)
212 			printf("deliver to protocol %d\n",
213 				       ep->ns_err_idp.idp_pt);
214 #endif
215 		switch(ep->ns_err_idp.idp_pt) {
216 		case NSPROTO_SPP:
217 			spp_ctlinput(code, (caddr_t)ep);
218 			break;
219 
220 		default:
221 			idp_ctlinput(code, (caddr_t)ep);
222 		}
223 
224 		goto free;
225 
226 	default:
227 	badcode:
228 		ns_errstat.ns_es_badcode++;
229 		goto free;
230 
231 	}
232 free:
233 	m_freem(m);
234 }
235 
236 #ifdef notdef
237 u_long
238 nstime()
239 {
240 	int s = splclock();
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 #endif
248 
249 ns_echo(idp)
250 register struct idp *idp;
251 {
252 	struct mbuf *m = dtom(idp);
253 	register struct echo {
254 	    struct idp	ec_idp;
255 	    u_short		ec_op; /* Operation, 1 = request, 2 = reply */
256 	} *ec = (struct echo *)idp;
257 	struct ns_addr temp;
258 
259 	if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK);
260 	if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC);
261 
262 	ec->ec_op = htons(2);
263 
264 	temp = idp->idp_dna;
265 	idp->idp_dna = idp->idp_sna;
266 	idp->idp_sna = temp;
267 
268 	if (idp->idp_sum != 0xffff) {
269 		idp->idp_sum = 0;
270 		idp->idp_sum = ns_cksum(m,
271 		    (int)(((ntohs(idp->idp_len) - 1)|1)+1));
272 	}
273 	(void) ns_output(m, (struct route *)0, NS_FORWARDING);
274 	return(0);
275 }
276