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