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