ddp_input.c revision 127289
1/*
2 * Copyright (c) 1990,1994 Regents of The University of Michigan.
3 * All Rights Reserved.  See COPYRIGHT.
4 *
5 * $FreeBSD: head/sys/netatalk/ddp_input.c 127289 2004-03-22 03:48:31Z rwatson $
6 */
7
8#include "opt_mac.h"
9
10#include <sys/param.h>
11#include <sys/kernel.h>
12#include <sys/lock.h>
13#include <sys/mac.h>
14#include <sys/mbuf.h>
15#include <sys/signalvar.h>
16#include <sys/socket.h>
17#include <sys/socketvar.h>
18#include <sys/sx.h>
19#include <sys/systm.h>
20#include <net/if.h>
21#include <net/route.h>
22
23#include <netatalk/at.h>
24#include <netatalk/at_var.h>
25#include <netatalk/ddp.h>
26#include <netatalk/ddp_var.h>
27#include <netatalk/at_extern.h>
28
29static volatile int	ddp_forward = 1;
30static volatile int	ddp_firewall = 0;
31static struct ddpstat	ddpstat;
32static struct route	forwro;
33
34static void     ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int);
35
36/*
37 * Could probably merge these two code segments a little better...
38 */
39void
40at2intr(struct mbuf *m)
41{
42	GIANT_REQUIRED;
43
44	/*
45	 * Phase 2 packet handling
46	 */
47	ddp_input(m, m->m_pkthdr.rcvif, NULL, 2);
48	return;
49}
50
51void
52at1intr(struct mbuf *m)
53{
54	struct elaphdr *elhp, elh;
55
56	/*
57	 * Phase 1 packet handling
58	 */
59	if (m->m_len < SZ_ELAPHDR && ((m = m_pullup(m, SZ_ELAPHDR)) == NULL)) {
60		ddpstat.ddps_tooshort++;
61		return;
62	}
63
64	/*
65	 * This seems a little dubious, but I don't know phase 1 so leave it.
66	 */
67	elhp = mtod(m, struct elaphdr *);
68	m_adj(m, SZ_ELAPHDR);
69
70	GIANT_REQUIRED;
71
72	if (elhp->el_type == ELAP_DDPEXTEND) {
73		ddp_input(m, m->m_pkthdr.rcvif, NULL, 1);
74	} else {
75		bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR);
76		ddp_input(m, m->m_pkthdr.rcvif, &elh, 1);
77	}
78	return;
79}
80
81static void
82ddp_input(m, ifp, elh, phase)
83    struct mbuf		*m;
84    struct ifnet	*ifp;
85    struct elaphdr	*elh;
86    int			phase;
87{
88    struct sockaddr_at	from, to;
89    struct ddpshdr	*dsh, ddps;
90    struct at_ifaddr	*aa;
91    struct ddpehdr	*deh = NULL, ddpe;
92    struct ddpcb	*ddp;
93    int			dlen, mlen;
94    u_short		cksum = 0;
95
96    bzero((caddr_t)&from, sizeof(struct sockaddr_at));
97    bzero((caddr_t)&to, sizeof(struct sockaddr_at));
98    if (elh) {
99	/*
100	 * Extract the information in the short header.
101	 * netowrk information is defaulted to ATADDR_ANYNET
102	 * and node information comes from the elh info.
103	 * We must be phase 1.
104	 */
105	ddpstat.ddps_short++;
106
107	if (m->m_len < sizeof(struct ddpshdr) &&
108		((m = m_pullup(m, sizeof(struct ddpshdr))) == NULL)) {
109	    ddpstat.ddps_tooshort++;
110	    return;
111	}
112
113	dsh = mtod(m, struct ddpshdr *);
114	bcopy((caddr_t)dsh, (caddr_t)&ddps, sizeof(struct ddpshdr));
115	ddps.dsh_bytes = ntohl(ddps.dsh_bytes);
116	dlen = ddps.dsh_len;
117
118	to.sat_addr.s_net = ATADDR_ANYNET;
119	to.sat_addr.s_node = elh->el_dnode;
120	to.sat_port = ddps.dsh_dport;
121	from.sat_addr.s_net = ATADDR_ANYNET;
122	from.sat_addr.s_node = elh->el_snode;
123	from.sat_port = ddps.dsh_sport;
124
125	/*
126	 * Make sure that we point to the phase1 ifaddr info
127	 * and that it's valid for this packet.
128	 */
129	for (aa = at_ifaddr; aa; aa = aa->aa_next) {
130	    if ((aa->aa_ifp == ifp)
131	    && ((aa->aa_flags & AFA_PHASE2) == 0)
132	    && ((to.sat_addr.s_node == AA_SAT(aa)->sat_addr.s_node)
133	      || (to.sat_addr.s_node == ATADDR_BCAST))) {
134		break;
135	    }
136	}
137	/*
138	 * maybe we got a broadcast not meant for us.. ditch it.
139	 */
140	if (aa == NULL) {
141	    m_freem(m);
142	    return;
143	}
144    } else {
145	/*
146	 * There was no 'elh' passed on. This could still be
147	 * either phase1 or phase2.
148	 * We have a long header, but we may be running on a phase 1 net.
149	 * Extract out all the info regarding this packet's src & dst.
150	 */
151	ddpstat.ddps_long++;
152
153	if (m->m_len < sizeof(struct ddpehdr) &&
154		((m = m_pullup(m, sizeof(struct ddpehdr))) == NULL)) {
155	    ddpstat.ddps_tooshort++;
156	    return;
157	}
158
159	deh = mtod(m, struct ddpehdr *);
160	bcopy((caddr_t)deh, (caddr_t)&ddpe, sizeof(struct ddpehdr));
161	ddpe.deh_bytes = ntohl(ddpe.deh_bytes);
162	dlen = ddpe.deh_len;
163
164	if ((cksum = ddpe.deh_sum) == 0) {
165	    ddpstat.ddps_nosum++;
166	}
167
168	from.sat_addr.s_net = ddpe.deh_snet;
169	from.sat_addr.s_node = ddpe.deh_snode;
170	from.sat_port = ddpe.deh_sport;
171	to.sat_addr.s_net = ddpe.deh_dnet;
172	to.sat_addr.s_node = ddpe.deh_dnode;
173	to.sat_port = ddpe.deh_dport;
174
175	if (to.sat_addr.s_net == ATADDR_ANYNET) {
176	    /*
177	     * The TO address doesn't specify a net,
178	     * So by definition it's for this net.
179	     * Try find ifaddr info with the right phase,
180	     * the right interface, and either to our node, a broadcast,
181	     * or looped back (though that SHOULD be covered in the other
182	     * cases).
183	     *
184	     * XXX If we have multiple interfaces, then the first with
185	     * this node number will match (which may NOT be what we want,
186	     * but it's probably safe in 99.999% of cases.
187	     */
188	    for (aa = at_ifaddr; aa; aa = aa->aa_next) {
189		if (phase == 1 && (aa->aa_flags & AFA_PHASE2)) {
190		    continue;
191		}
192		if (phase == 2 && (aa->aa_flags & AFA_PHASE2) == 0) {
193		    continue;
194		}
195		if ((aa->aa_ifp == ifp)
196		&& ((to.sat_addr.s_node == AA_SAT(aa)->sat_addr.s_node)
197		  || (to.sat_addr.s_node == ATADDR_BCAST)
198		  || (ifp->if_flags & IFF_LOOPBACK))) {
199		    break;
200		}
201	    }
202	} else {
203	    /*
204	     * A destination network was given. We just try to find
205	     * which ifaddr info matches it.
206	     */
207	    for (aa = at_ifaddr; aa; aa = aa->aa_next) {
208		/*
209		 * This is a kludge. Accept packets that are
210		 * for any router on a local netrange.
211		 */
212		if (to.sat_addr.s_net == aa->aa_firstnet &&
213			to.sat_addr.s_node == 0) {
214		    break;
215		}
216		/*
217		 * Don't use ifaddr info for which we are totally outside the
218		 * netrange, and it's not a startup packet.
219		 * Startup packets are always implicitly allowed on to
220		 * the next test.
221		 */
222		if (((ntohs(to.sat_addr.s_net) < ntohs(aa->aa_firstnet))
223		    || (ntohs(to.sat_addr.s_net) > ntohs(aa->aa_lastnet)))
224		 && ((ntohs(to.sat_addr.s_net) < 0xff00)
225		    || (ntohs(to.sat_addr.s_net) > 0xfffe))) {
226		    continue;
227		}
228
229		/*
230		 * Don't record a match either if we just don't have a match
231		 * in the node address. This can have if the interface
232		 * is in promiscuous mode for example.
233		 */
234		if ((to.sat_addr.s_node != AA_SAT(aa)->sat_addr.s_node)
235		&& (to.sat_addr.s_node != ATADDR_BCAST)) {
236		    continue;
237		}
238		break;
239	    }
240	}
241    }
242
243    /*
244     * Adjust the length, removing any padding that may have been added
245     * at a link layer.  We do this before we attempt to forward a packet,
246     * possibly on a different media.
247     */
248    mlen = m->m_pkthdr.len;
249    if (mlen < dlen) {
250	ddpstat.ddps_toosmall++;
251	m_freem(m);
252	return;
253    }
254    if (mlen > dlen) {
255	m_adj(m, dlen - mlen);
256    }
257
258    /*
259     * If it aint for a net on any of our interfaces,
260     * or it IS for a net on a different interface than it came in on,
261     * (and it is not looped back) then consider if we should forward it.
262     * As we are not really a router this is a bit cheeky, but it may be
263     * useful some day.
264     */
265    if ((aa == NULL)
266    || ((to.sat_addr.s_node == ATADDR_BCAST)
267      && (aa->aa_ifp != ifp)
268      && ((ifp->if_flags & IFF_LOOPBACK) == 0))) {
269	/*
270	 * If we've explicitly disabled it, don't route anything
271	 */
272	if (ddp_forward == 0) {
273	    m_freem(m);
274	    return;
275	}
276	/*
277	 * If the cached forwarding route is still valid, use it.
278	 */
279	if (forwro.ro_rt
280	&& (satosat(&forwro.ro_dst)->sat_addr.s_net != to.sat_addr.s_net
281	  || satosat(&forwro.ro_dst)->sat_addr.s_node != to.sat_addr.s_node)) {
282	    RTFREE(forwro.ro_rt);
283	    forwro.ro_rt = NULL;
284	}
285
286	/*
287	 * If we don't have a cached one (any more) or it's useless,
288	 * Then get a new route.
289	 * XXX this could cause a 'route leak'. check this!
290	 */
291	if (forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp == NULL) {
292	    forwro.ro_dst.sa_len = sizeof(struct sockaddr_at);
293	    forwro.ro_dst.sa_family = AF_APPLETALK;
294	    satosat(&forwro.ro_dst)->sat_addr.s_net = to.sat_addr.s_net;
295	    satosat(&forwro.ro_dst)->sat_addr.s_node = to.sat_addr.s_node;
296	    rtalloc(&forwro);
297	}
298
299	/*
300	 * If it's not going to get there on this hop, and it's
301	 * already done too many hops, then throw it away.
302	 */
303	if ((to.sat_addr.s_net != satosat(&forwro.ro_dst)->sat_addr.s_net)
304	&& (ddpe.deh_hops == DDP_MAXHOPS)) {
305	    m_freem(m);
306	    return;
307	}
308
309	/*
310	 * A ddp router might use the same interface
311	 * to forward the packet, which this would not effect.
312	 * Don't allow packets to cross from one interface to another however.
313	 */
314	if (ddp_firewall
315	&& ((forwro.ro_rt == NULL)
316	  || (forwro.ro_rt->rt_ifp != ifp))) {
317	    m_freem(m);
318	    return;
319	}
320
321	/*
322	 * Adjust the header.
323	 * If it was a short header then it would have not gotten here,
324	 * so we can assume there is room to drop the header in.
325	 * XXX what about promiscuous mode, etc...
326	 */
327	ddpe.deh_hops++;
328	ddpe.deh_bytes = htonl(ddpe.deh_bytes);
329	bcopy((caddr_t)&ddpe, (caddr_t)deh, sizeof(u_short)); /* XXX deh? */
330	if (ddp_route(m, &forwro)) {
331	    ddpstat.ddps_cantforward++;
332	} else {
333	    ddpstat.ddps_forward++;
334	}
335	return;
336    }
337
338    /*
339     * It was for us, and we have an ifaddr to use with it.
340     */
341    from.sat_len = sizeof(struct sockaddr_at);
342    from.sat_family = AF_APPLETALK;
343
344    /*
345     * We are no longer interested in the link layer.
346     * so cut it off.
347     */
348    if (elh) {
349	m_adj(m, sizeof(struct ddpshdr));
350    } else {
351	if (ddp_cksum && cksum && cksum != at_cksum(m, sizeof(int))) {
352	    ddpstat.ddps_badsum++;
353	    m_freem(m);
354	    return;
355	}
356	m_adj(m, sizeof(struct ddpehdr));
357    }
358
359    /*
360     * Search for ddp protocol control blocks that match these
361     * addresses.
362     */
363    if ((ddp = ddp_search(&from, &to, aa)) == NULL) {
364	m_freem(m);
365	return;
366    }
367
368#ifdef MAC
369    if (mac_check_socket_deliver(ddp->ddp_socket, m) != 0) {
370	m_freem(m);
371	return;
372    }
373#endif
374
375    /*
376     * If we found one, deliver th epacket to the socket
377     */
378    if (sbappendaddr(&ddp->ddp_socket->so_rcv, (struct sockaddr *)&from,
379	    m, NULL) == 0) {
380	/*
381	 * If the socket is full (or similar error) dump the packet.
382	 */
383	ddpstat.ddps_nosockspace++;
384	m_freem(m);
385	return;
386    }
387    /*
388     * And wake up whatever might be waiting for it
389     */
390    sorwakeup(ddp->ddp_socket);
391}
392
393#if 0
394/* As if we haven't got enough of this sort of think floating
395around the kernel :) */
396
397#define BPXLEN	48
398#define BPALEN	16
399#include <ctype.h>
400char	hexdig[] = "0123456789ABCDEF";
401
402static void
403bprint(char *data, int len)
404{
405    char	xout[ BPXLEN ], aout[ BPALEN ];
406    int		i = 0;
407
408    bzero(xout, BPXLEN);
409    bzero(aout, BPALEN);
410
411    for (;;) {
412	if (len < 1) {
413	    if (i != 0) {
414		printf("%s\t%s\n", xout, aout);
415	    }
416	    printf("%s\n", "(end)");
417	    break;
418	}
419
420	xout[ (i*3) ] = hexdig[ (*data & 0xf0) >> 4 ];
421	xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ];
422
423	if ((u_char)*data < 0x7f && (u_char)*data > 0x20) {
424	    aout[ i ] = *data;
425	} else {
426	    aout[ i ] = '.';
427	}
428
429	xout[ (i*3) + 2 ] = ' ';
430
431	i++;
432	len--;
433	data++;
434
435	if (i > BPALEN - 2) {
436	    printf("%s\t%s\n", xout, aout);
437	    bzero(xout, BPXLEN);
438	    bzero(aout, BPALEN);
439	    i = 0;
440	    continue;
441	}
442    }
443}
444
445static void
446m_printm(struct mbuf *m)
447{
448    for (; m; m = m->m_next) {
449	bprint(mtod(m, char *), m->m_len);
450    }
451}
452#endif
453