xref: /netbsd-src/sys/netatalk/ddp_input.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: ddp_input.c,v 1.2 1997/04/02 21:47:03 christos Exp $	 */
2 
3 /*
4  * Copyright (c) 1990,1994 Regents of The University of Michigan.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software and
8  * its documentation for any purpose and without fee is hereby granted,
9  * provided that the above copyright notice appears in all copies and
10  * that both that copyright notice and this permission notice appear
11  * in supporting documentation, and that the name of The University
12  * of Michigan not be used in advertising or publicity pertaining to
13  * distribution of the software without specific, written prior
14  * permission. This software is supplied as is without expressed or
15  * implied warranties of any kind.
16  *
17  * This product includes software developed by the University of
18  * California, Berkeley and its contributors.
19  *
20  *	Research Systems Unix Group
21  *	The University of Michigan
22  *	c/o Wesley Craig
23  *	535 W. William Street
24  *	Ann Arbor, Michigan
25  *	+1-313-764-2278
26  *	netatalk@umich.edu
27  */
28 
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <net/netisr.h>
34 #include <sys/mbuf.h>
35 #include <sys/socket.h>
36 #include <sys/socketvar.h>
37 #include <sys/syslog.h>
38 #include <net/if.h>
39 #include <net/route.h>
40 #include <net/if_ether.h>
41 #include <netinet/in.h>
42 
43 #include <netatalk/at.h>
44 #include <netatalk/at_var.h>
45 #include <netatalk/ddp.h>
46 #include <netatalk/ddp_var.h>
47 #include <netatalk/at_extern.h>
48 
49 int             ddp_forward = 1;
50 int             ddp_firewall = 0;
51 extern int      ddp_cksum;
52 void            ddp_input __P((struct mbuf *, struct ifnet *,
53     struct elaphdr *, int));
54 
55 /*
56  * Could probably merge these two code segments a little better...
57  */
58 void
59 atintr()
60 {
61 	struct elaphdr *elhp, elh;
62 	struct ifnet   *ifp;
63 	struct mbuf    *m;
64 	struct at_ifaddr *aa;
65 	int             s;
66 
67 	for (;;) {
68 		s = splimp();
69 
70 		IF_DEQUEUE(&atintrq2, m);
71 
72 		splx(s);
73 
74 		if (m == 0) {	/* no more queued packets */
75 			break;
76 		}
77 		ifp = m->m_pkthdr.rcvif;
78 		for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
79 			if (aa->aa_ifp == ifp && (aa->aa_flags & AFA_PHASE2))
80 				break;
81 		}
82 		if (aa == NULL) {	/* ifp not an appletalk interface */
83 			m_freem(m);
84 			continue;
85 		}
86 		ddp_input(m, ifp, (struct elaphdr *) NULL, 2);
87 	}
88 
89 	for (;;) {
90 		s = splimp();
91 
92 		IF_DEQUEUE(&atintrq1, m);
93 
94 		splx(s);
95 
96 		if (m == 0) /* no more queued packets */
97 
98 			break;
99 		ifp = m->m_pkthdr.rcvif;
100 		for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
101 			if (aa->aa_ifp == ifp &&
102 			    (aa->aa_flags & AFA_PHASE2) == 0)
103 				break;
104 		}
105 		if (aa == NULL) {	/* ifp not an appletalk interface */
106 			m_freem(m);
107 			continue;
108 		}
109 		if (m->m_len < SZ_ELAPHDR &&
110 		    ((m = m_pullup(m, SZ_ELAPHDR)) == 0)) {
111 			ddpstat.ddps_tooshort++;
112 			continue;
113 		}
114 		elhp = mtod(m, struct elaphdr *);
115 		m_adj(m, SZ_ELAPHDR);
116 
117 		if (elhp->el_type == ELAP_DDPEXTEND) {
118 			ddp_input(m, ifp, (struct elaphdr *) NULL, 1);
119 		} else {
120 			bcopy((caddr_t) elhp, (caddr_t) & elh, SZ_ELAPHDR);
121 			ddp_input(m, ifp, &elh, 1);
122 		}
123 	}
124 }
125 
126 struct route    forwro;
127 
128 void
129 ddp_input(m, ifp, elh, phase)
130 	struct mbuf    *m;
131 	struct ifnet   *ifp;
132 	struct elaphdr *elh;
133 	int             phase;
134 {
135 	struct sockaddr_at from, to;
136 	struct ddpshdr *dsh, ddps;
137 	struct at_ifaddr *aa;
138 	struct ddpehdr *deh = NULL, ddpe;
139 	struct ddpcb   *ddp;
140 	int             dlen, mlen;
141 	u_short         cksum = 0;
142 
143 	bzero((caddr_t) & from, sizeof(struct sockaddr_at));
144 	if (elh) {
145 		ddpstat.ddps_short++;
146 
147 		if (m->m_len < sizeof(struct ddpshdr) &&
148 		    ((m = m_pullup(m, sizeof(struct ddpshdr))) == 0)) {
149 			ddpstat.ddps_tooshort++;
150 			return;
151 		}
152 		dsh = mtod(m, struct ddpshdr *);
153 		bcopy((caddr_t) dsh, (caddr_t) & ddps, sizeof(struct ddpshdr));
154 		ddps.dsh_bytes = ntohl(ddps.dsh_bytes);
155 		dlen = ddps.dsh_len;
156 
157 		to.sat_addr.s_net = ATADDR_ANYNET;
158 		to.sat_addr.s_node = elh->el_dnode;
159 		to.sat_port = ddps.dsh_dport;
160 		from.sat_addr.s_net = ATADDR_ANYNET;
161 		from.sat_addr.s_node = elh->el_snode;
162 		from.sat_port = ddps.dsh_sport;
163 
164 		for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
165 			if (aa->aa_ifp == ifp &&
166 			    (aa->aa_flags & AFA_PHASE2) == 0 &&
167 			    (AA_SAT(aa)->sat_addr.s_node ==
168 			     to.sat_addr.s_node ||
169 			     to.sat_addr.s_node == ATADDR_BCAST))
170 				break;
171 		}
172 		if (aa == NULL) {
173 			m_freem(m);
174 			return;
175 		}
176 	} else {
177 		ddpstat.ddps_long++;
178 
179 		if (m->m_len < sizeof(struct ddpehdr) &&
180 		    ((m = m_pullup(m, sizeof(struct ddpehdr))) == 0)) {
181 			ddpstat.ddps_tooshort++;
182 			return;
183 		}
184 		deh = mtod(m, struct ddpehdr *);
185 		bcopy((caddr_t) deh, (caddr_t) & ddpe, sizeof(struct ddpehdr));
186 		ddpe.deh_bytes = ntohl(ddpe.deh_bytes);
187 		dlen = ddpe.deh_len;
188 
189 		if ((cksum = ddpe.deh_sum) == 0) {
190 			ddpstat.ddps_nosum++;
191 		}
192 		from.sat_addr.s_net = ddpe.deh_snet;
193 		from.sat_addr.s_node = ddpe.deh_snode;
194 		from.sat_port = ddpe.deh_sport;
195 		to.sat_addr.s_net = ddpe.deh_dnet;
196 		to.sat_addr.s_node = ddpe.deh_dnode;
197 		to.sat_port = ddpe.deh_dport;
198 
199 		if (to.sat_addr.s_net == ATADDR_ANYNET) {
200 			for (aa = at_ifaddr.tqh_first; aa;
201 			    aa = aa->aa_list.tqe_next) {
202 				if (phase == 1 && (aa->aa_flags & AFA_PHASE2))
203 					continue;
204 
205 				if (phase == 2 &&
206 				    (aa->aa_flags & AFA_PHASE2) == 0)
207 					continue;
208 
209 				if (aa->aa_ifp == ifp &&
210 				    (AA_SAT(aa)->sat_addr.s_node ==
211 				     to.sat_addr.s_node ||
212 				     to.sat_addr.s_node == ATADDR_BCAST ||
213 				     (ifp->if_flags & IFF_LOOPBACK)))
214 					break;
215 			}
216 		} else {
217 			for (aa = at_ifaddr.tqh_first; aa;
218 			    aa = aa->aa_list.tqe_next) {
219 				if (to.sat_addr.s_net == aa->aa_firstnet &&
220 				    to.sat_addr.s_node == 0)
221 					break;
222 
223 				if ((ntohs(to.sat_addr.s_net) <
224 				     ntohs(aa->aa_firstnet) ||
225 				     ntohs(to.sat_addr.s_net) >
226 				     ntohs(aa->aa_lastnet)) &&
227 				    (ntohs(to.sat_addr.s_net) < ntohs(0xff00) ||
228 				     ntohs(to.sat_addr.s_net) > ntohs(0xfffe)))
229 					continue;
230 
231 				if (to.sat_addr.s_node !=
232 				    AA_SAT(aa)->sat_addr.s_node &&
233 				    to.sat_addr.s_node != ATADDR_BCAST)
234 					continue;
235 
236 				break;
237 			}
238 		}
239 	}
240 
241 	/*
242          * Adjust the length, removing any padding that may have been added
243          * at a link layer.  We do this before we attempt to forward a packet,
244          * possibly on a different media.
245          */
246 	mlen = m->m_pkthdr.len;
247 	if (mlen < dlen) {
248 		ddpstat.ddps_toosmall++;
249 		m_freem(m);
250 		return;
251 	}
252 	if (mlen > dlen) {
253 		m_adj(m, dlen - mlen);
254 	}
255 	/*
256          * XXX Should we deliver broadcasts locally, also, or rely on the
257          * link layer to give us a copy?  For the moment, the latter.
258          */
259 	if (aa == NULL || (to.sat_addr.s_node == ATADDR_BCAST &&
260 		aa->aa_ifp != ifp && (ifp->if_flags & IFF_LOOPBACK) == 0)) {
261 		if (ddp_forward == 0) {
262 			m_freem(m);
263 			return;
264 		}
265 		if (forwro.ro_rt &&
266 		    (satosat(&forwro.ro_dst)->sat_addr.s_net !=
267 		     to.sat_addr.s_net ||
268 		     satosat(&forwro.ro_dst)->sat_addr.s_node !=
269 		     to.sat_addr.s_node)) {
270 			RTFREE(forwro.ro_rt);
271 			forwro.ro_rt = (struct rtentry *) 0;
272 		}
273 		if (forwro.ro_rt == (struct rtentry *) 0 ||
274 		    forwro.ro_rt->rt_ifp == (struct ifnet *) 0) {
275 			bzero(&forwro.ro_dst, sizeof(struct sockaddr_at));
276 			forwro.ro_dst.sa_len = sizeof(struct sockaddr_at);
277 			forwro.ro_dst.sa_family = AF_APPLETALK;
278 			satosat(&forwro.ro_dst)->sat_addr.s_net =
279 			    to.sat_addr.s_net;
280 			satosat(&forwro.ro_dst)->sat_addr.s_node =
281 			    to.sat_addr.s_node;
282 			rtalloc(&forwro);
283 		}
284 		if (to.sat_addr.s_net !=
285 		    satosat(&forwro.ro_dst)->sat_addr.s_net &&
286 		    ddpe.deh_hops == DDP_MAXHOPS) {
287 			m_freem(m);
288 			return;
289 		}
290 		if (ddp_firewall &&
291 		    (forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp != ifp)) {
292 			m_freem(m);
293 			return;
294 		}
295 		ddpe.deh_hops++;
296 		ddpe.deh_bytes = htonl(ddpe.deh_bytes);
297 		bcopy((caddr_t) & ddpe, (caddr_t) deh, sizeof(u_short));/*XXX*/
298 		if (ddp_route(m, &forwro)) {
299 			ddpstat.ddps_cantforward++;
300 		} else {
301 			ddpstat.ddps_forward++;
302 		}
303 		return;
304 	}
305 	from.sat_len = sizeof(struct sockaddr_at);
306 	from.sat_family = AF_APPLETALK;
307 
308 	if (elh) {
309 		m_adj(m, sizeof(struct ddpshdr));
310 	} else {
311 		if (ddp_cksum && cksum && cksum != at_cksum(m, sizeof(int))) {
312 			ddpstat.ddps_badsum++;
313 			m_freem(m);
314 			return;
315 		}
316 		m_adj(m, sizeof(struct ddpehdr));
317 	}
318 
319 	if ((ddp = ddp_search(&from, &to, aa)) == NULL) {
320 		m_freem(m);
321 		return;
322 	}
323 	if (sbappendaddr(&ddp->ddp_socket->so_rcv, (struct sockaddr *) & from,
324 			 m, (struct mbuf *) 0) == 0) {
325 		ddpstat.ddps_nosockspace++;
326 		m_freem(m);
327 		return;
328 	}
329 	sorwakeup(ddp->ddp_socket);
330 }
331 
332 #if 0
333 
334 #define BPXLEN	48
335 #define BPALEN	16
336 #include <ctype.h>
337 char            hexdig[] = "0123456789ABCDEF";
338 
339 static void
340 bprint(data, len)
341 	char *data;
342 	int len;
343 {
344 	char            xout[BPXLEN], aout[BPALEN];
345 	int             i = 0;
346 
347 	bzero(xout, BPXLEN);
348 	bzero(aout, BPALEN);
349 
350 	for (;;) {
351 		if (len < 1) {
352 			if (i != 0) {
353 				printf("%s\t%s\n", xout, aout);
354 			}
355 			printf("%s\n", "(end)");
356 			break;
357 		}
358 		xout[(i * 3)] = hexdig[(*data & 0xf0) >> 4];
359 		xout[(i * 3) + 1] = hexdig[*data & 0x0f];
360 
361 		if ((u_char) * data < 0x7f && (u_char) * data > 0x20) {
362 			aout[i] = *data;
363 		} else {
364 			aout[i] = '.';
365 		}
366 
367 		xout[(i * 3) + 2] = ' ';
368 
369 		i++;
370 		len--;
371 		data++;
372 
373 		if (i > BPALEN - 2) {
374 			printf("%s\t%s\n", xout, aout);
375 			bzero(xout, BPXLEN);
376 			bzero(aout, BPALEN);
377 			i = 0;
378 			continue;
379 		}
380 	}
381 }
382 
383 static void
384 m_printm(m)
385 	struct mbuf *m;
386 {
387 	for (; m; m = m->m_next)
388 		bprint(mtod(m, char *), m->m_len);
389 }
390 #endif
391