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