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