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