ddp_input.c revision 1.3.6.1 1 /* $NetBSD: ddp_input.c,v 1.3.6.1 1998/12/11 04:53:06 kenh 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 (at) 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 s = splimp();
79 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
80 if (aa->aa_ifp == ifp && (aa->aa_flags & AFA_PHASE2))
81 break;
82 }
83 splx(s);
84 if (aa == NULL) { /* ifp not an appletalk interface */
85 m_freem(m);
86 continue;
87 }
88 ddp_input(m, ifp, (struct elaphdr *) NULL, 2);
89 }
90
91 for (;;) {
92 s = splimp();
93
94 IF_DEQUEUE(&atintrq1, m);
95
96 splx(s);
97
98 if (m == 0) /* no more queued packets */
99
100 break;
101 ifp = m->m_pkthdr.rcvif;
102 s = splimp();
103 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
104 if (aa->aa_ifp == ifp &&
105 (aa->aa_flags & AFA_PHASE2) == 0)
106 break;
107 }
108 splx(s);
109 if (aa == NULL) { /* ifp not an appletalk interface */
110 m_freem(m);
111 continue;
112 }
113 if (m->m_len < SZ_ELAPHDR &&
114 ((m = m_pullup(m, SZ_ELAPHDR)) == 0)) {
115 ddpstat.ddps_tooshort++;
116 continue;
117 }
118 elhp = mtod(m, struct elaphdr *);
119 m_adj(m, SZ_ELAPHDR);
120
121 if (elhp->el_type == ELAP_DDPEXTEND) {
122 ddp_input(m, ifp, (struct elaphdr *) NULL, 1);
123 } else {
124 bcopy((caddr_t) elhp, (caddr_t) & elh, SZ_ELAPHDR);
125 ddp_input(m, ifp, &elh, 1);
126 }
127 }
128 }
129
130 struct route forwro;
131
132 void
133 ddp_input(m, ifp, elh, phase)
134 struct mbuf *m;
135 struct ifnet *ifp;
136 struct elaphdr *elh;
137 int phase;
138 {
139 struct sockaddr_at from, to;
140 struct ddpshdr *dsh, ddps;
141 struct at_ifaddr *aa = NULL;
142 struct ddpehdr *deh = NULL, ddpe;
143 struct ddpcb *ddp;
144 int dlen, mlen, s;
145 u_short cksum = 0;
146
147 bzero((caddr_t) & from, sizeof(struct sockaddr_at));
148 if (elh) {
149 ddpstat.ddps_short++;
150
151 if (m->m_len < sizeof(struct ddpshdr) &&
152 ((m = m_pullup(m, sizeof(struct ddpshdr))) == 0)) {
153 ddpstat.ddps_tooshort++;
154 return;
155 }
156 dsh = mtod(m, struct ddpshdr *);
157 bcopy((caddr_t) dsh, (caddr_t) & ddps, sizeof(struct ddpshdr));
158 ddps.dsh_bytes = ntohl(ddps.dsh_bytes);
159 dlen = ddps.dsh_len;
160
161 to.sat_addr.s_net = ATADDR_ANYNET;
162 to.sat_addr.s_node = elh->el_dnode;
163 to.sat_port = ddps.dsh_dport;
164 from.sat_addr.s_net = ATADDR_ANYNET;
165 from.sat_addr.s_node = elh->el_snode;
166 from.sat_port = ddps.dsh_sport;
167
168 s = splimp();
169 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) {
170 if (aa->aa_ifp == ifp &&
171 (aa->aa_flags & AFA_PHASE2) == 0 &&
172 (AA_SAT(aa)->sat_addr.s_node ==
173 to.sat_addr.s_node ||
174 to.sat_addr.s_node == ATADDR_BCAST))
175 break;
176 }
177 if (aa == NULL) {
178 m_freem(m);
179 splx(s);
180 return;
181 }
182 ifa_addref(&aa->aa_ifa);
183 splx(s);
184 } else {
185 ddpstat.ddps_long++;
186
187 if (m->m_len < sizeof(struct ddpehdr) &&
188 ((m = m_pullup(m, sizeof(struct ddpehdr))) == 0)) {
189 ddpstat.ddps_tooshort++;
190 return;
191 }
192 deh = mtod(m, struct ddpehdr *);
193 bcopy((caddr_t) deh, (caddr_t) & ddpe, sizeof(struct ddpehdr));
194 ddpe.deh_bytes = ntohl(ddpe.deh_bytes);
195 dlen = ddpe.deh_len;
196
197 if ((cksum = ddpe.deh_sum) == 0) {
198 ddpstat.ddps_nosum++;
199 }
200 from.sat_addr.s_net = ddpe.deh_snet;
201 from.sat_addr.s_node = ddpe.deh_snode;
202 from.sat_port = ddpe.deh_sport;
203 to.sat_addr.s_net = ddpe.deh_dnet;
204 to.sat_addr.s_node = ddpe.deh_dnode;
205 to.sat_port = ddpe.deh_dport;
206
207 s = splimp();
208 if (to.sat_addr.s_net == ATADDR_ANYNET) {
209 for (aa = at_ifaddr.tqh_first; aa;
210 aa = aa->aa_list.tqe_next) {
211 if (phase == 1 && (aa->aa_flags & AFA_PHASE2))
212 continue;
213
214 if (phase == 2 &&
215 (aa->aa_flags & AFA_PHASE2) == 0)
216 continue;
217
218 if (aa->aa_ifp == ifp &&
219 (AA_SAT(aa)->sat_addr.s_node ==
220 to.sat_addr.s_node ||
221 to.sat_addr.s_node == ATADDR_BCAST ||
222 (ifp->if_flags & IFF_LOOPBACK)))
223 break;
224 }
225 } else {
226 for (aa = at_ifaddr.tqh_first; aa;
227 aa = aa->aa_list.tqe_next) {
228 if (to.sat_addr.s_net == aa->aa_firstnet &&
229 to.sat_addr.s_node == 0)
230 break;
231
232 if ((ntohs(to.sat_addr.s_net) <
233 ntohs(aa->aa_firstnet) ||
234 ntohs(to.sat_addr.s_net) >
235 ntohs(aa->aa_lastnet)) &&
236 (ntohs(to.sat_addr.s_net) < 0xff00 ||
237 ntohs(to.sat_addr.s_net) > 0xfffe))
238 continue;
239
240 if (to.sat_addr.s_node !=
241 AA_SAT(aa)->sat_addr.s_node &&
242 to.sat_addr.s_node != ATADDR_BCAST)
243 continue;
244
245 break;
246 }
247 }
248 if (aa)
249 ifa_addref(&aa->aa_ifa);
250 splx(s);
251 }
252
253 /*
254 * Adjust the length, removing any padding that may have been added
255 * at a link layer. We do this before we attempt to forward a packet,
256 * possibly on a different media.
257 */
258 mlen = m->m_pkthdr.len;
259 if (mlen < dlen) {
260 ddpstat.ddps_toosmall++;
261 ifa_delref(&aa->aa_ifa);
262 m_freem(m);
263 return;
264 }
265 if (mlen > dlen) {
266 m_adj(m, dlen - mlen);
267 }
268 /*
269 * XXX Should we deliver broadcasts locally, also, or rely on the
270 * link layer to give us a copy? For the moment, the latter.
271 */
272 if (aa == NULL || (to.sat_addr.s_node == ATADDR_BCAST &&
273 aa->aa_ifp != ifp && (ifp->if_flags & IFF_LOOPBACK) == 0)) {
274 if (ddp_forward == 0) {
275 if (aa)
276 ifa_delref(&aa->aa_ifa);
277 m_freem(m);
278 return;
279 }
280 if (forwro.ro_rt &&
281 (satosat(&forwro.ro_dst)->sat_addr.s_net !=
282 to.sat_addr.s_net ||
283 satosat(&forwro.ro_dst)->sat_addr.s_node !=
284 to.sat_addr.s_node)) {
285 RTFREE(forwro.ro_rt);
286 forwro.ro_rt = (struct rtentry *) 0;
287 }
288 if (forwro.ro_rt == (struct rtentry *) 0 ||
289 forwro.ro_rt->rt_ifp == (struct ifnet *) 0) {
290 bzero(&forwro.ro_dst, sizeof(struct sockaddr_at));
291 forwro.ro_dst.sa_len = sizeof(struct sockaddr_at);
292 forwro.ro_dst.sa_family = AF_APPLETALK;
293 satosat(&forwro.ro_dst)->sat_addr.s_net =
294 to.sat_addr.s_net;
295 satosat(&forwro.ro_dst)->sat_addr.s_node =
296 to.sat_addr.s_node;
297 rtalloc(&forwro);
298 }
299 if (to.sat_addr.s_net !=
300 satosat(&forwro.ro_dst)->sat_addr.s_net &&
301 ddpe.deh_hops == DDP_MAXHOPS) {
302 if (aa)
303 ifa_delref(&aa->aa_ifa);
304 m_freem(m);
305 return;
306 }
307 if (ddp_firewall &&
308 (forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp != ifp)) {
309 if (aa)
310 ifa_delref(&aa->aa_ifa);
311 m_freem(m);
312 return;
313 }
314 ddpe.deh_hops++;
315 ddpe.deh_bytes = htonl(ddpe.deh_bytes);
316 bcopy((caddr_t) & ddpe, (caddr_t) deh, sizeof(u_short));/*XXX*/
317 if (ddp_route(m, &forwro)) {
318 ddpstat.ddps_cantforward++;
319 } else {
320 ddpstat.ddps_forward++;
321 }
322 if (aa)
323 ifa_delref(&aa->aa_ifa);
324 return;
325 }
326 from.sat_len = sizeof(struct sockaddr_at);
327 from.sat_family = AF_APPLETALK;
328
329 if (elh) {
330 m_adj(m, sizeof(struct ddpshdr));
331 } else {
332 if (ddp_cksum && cksum && cksum != at_cksum(m, sizeof(int))) {
333 ddpstat.ddps_badsum++;
334 if (aa)
335 ifa_delref(&aa->aa_ifa);
336 m_freem(m);
337 return;
338 }
339 m_adj(m, sizeof(struct ddpehdr));
340 }
341
342 if ((ddp = ddp_search(&from, &to, aa)) == NULL) {
343 if (aa)
344 ifa_delref(&aa->aa_ifa);
345 m_freem(m);
346 return;
347 }
348 if (aa)
349 ifa_delref(&aa->aa_ifa);
350 if (sbappendaddr(&ddp->ddp_socket->so_rcv, (struct sockaddr *) & from,
351 m, (struct mbuf *) 0) == 0) {
352 ddpstat.ddps_nosockspace++;
353 m_freem(m);
354 return;
355 }
356 sorwakeup(ddp->ddp_socket);
357 }
358
359 #if 0
360
361 #define BPXLEN 48
362 #define BPALEN 16
363 #include <ctype.h>
364 char hexdig[] = "0123456789ABCDEF";
365
366 static void
367 bprint(data, len)
368 char *data;
369 int len;
370 {
371 char xout[BPXLEN], aout[BPALEN];
372 int i = 0;
373
374 bzero(xout, BPXLEN);
375 bzero(aout, BPALEN);
376
377 for (;;) {
378 if (len < 1) {
379 if (i != 0) {
380 printf("%s\t%s\n", xout, aout);
381 }
382 printf("%s\n", "(end)");
383 break;
384 }
385 xout[(i * 3)] = hexdig[(*data & 0xf0) >> 4];
386 xout[(i * 3) + 1] = hexdig[*data & 0x0f];
387
388 if ((u_char) * data < 0x7f && (u_char) * data > 0x20) {
389 aout[i] = *data;
390 } else {
391 aout[i] = '.';
392 }
393
394 xout[(i * 3) + 2] = ' ';
395
396 i++;
397 len--;
398 data++;
399
400 if (i > BPALEN - 2) {
401 printf("%s\t%s\n", xout, aout);
402 bzero(xout, BPXLEN);
403 bzero(aout, BPALEN);
404 i = 0;
405 continue;
406 }
407 }
408 }
409
410 static void
411 m_printm(m)
412 struct mbuf *m;
413 {
414 for (; m; m = m->m_next)
415 bprint(mtod(m, char *), m->m_len);
416 }
417 #endif
418