ddp_input.c revision 165974
1/*- 2 * Copyright (c) 2004 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * Copyright (c) 1990, 1994 Regents of The University of Michigan. 27 * 28 * Permission to use, copy, modify, and distribute this software and 29 * its documentation for any purpose and without fee is hereby granted, 30 * provided that the above copyright notice appears in all copies and 31 * that both that copyright notice and this permission notice appear 32 * in supporting documentation, and that the name of The University 33 * of Michigan not be used in advertising or publicity pertaining to 34 * distribution of the software without specific, written prior 35 * permission. This software is supplied as is without expressed or 36 * implied warranties of any kind. 37 * 38 * This product includes software developed by the University of 39 * California, Berkeley and its contributors. 40 * 41 * Research Systems Unix Group 42 * The University of Michigan 43 * c/o Wesley Craig 44 * 535 W. William Street 45 * Ann Arbor, Michigan 46 * +1-313-764-2278 47 * netatalk@umich.edu 48 * 49 * $FreeBSD: head/sys/netatalk/ddp_input.c 165974 2007-01-12 15:07:51Z rwatson $ 50 */ 51 52#include "opt_mac.h" 53 54#include <sys/param.h> 55#include <sys/kernel.h> 56#include <sys/lock.h> 57#include <sys/mbuf.h> 58#include <sys/signalvar.h> 59#include <sys/socket.h> 60#include <sys/socketvar.h> 61#include <sys/sx.h> 62#include <sys/systm.h> 63#include <net/if.h> 64#include <net/route.h> 65 66#include <netatalk/at.h> 67#include <netatalk/at_var.h> 68#include <netatalk/ddp.h> 69#include <netatalk/ddp_var.h> 70#include <netatalk/ddp_pcb.h> 71#include <netatalk/at_extern.h> 72 73#include <security/mac/mac_framework.h> 74 75static volatile int ddp_forward = 1; 76static volatile int ddp_firewall = 0; 77static struct ddpstat ddpstat; 78 79static struct route forwro; 80 81static void ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int); 82 83/* 84 * Could probably merge these two code segments a little better... 85 */ 86void 87at2intr(struct mbuf *m) 88{ 89 90 /* 91 * Phase 2 packet handling . 92 */ 93 ddp_input(m, m->m_pkthdr.rcvif, NULL, 2); 94} 95 96void 97at1intr(struct mbuf *m) 98{ 99 struct elaphdr *elhp, elh; 100 101 /* 102 * Phase 1 packet handling 103 */ 104 if (m->m_len < SZ_ELAPHDR && ((m = m_pullup(m, SZ_ELAPHDR)) == 105 NULL)) { 106 ddpstat.ddps_tooshort++; 107 return; 108 } 109 110 /* 111 * This seems a little dubious, but I don't know phase 1 so leave it. 112 */ 113 elhp = mtod(m, struct elaphdr *); 114 m_adj(m, SZ_ELAPHDR); 115 116 if (elhp->el_type != ELAP_DDPEXTEND) { 117 bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR); 118 ddp_input(m, m->m_pkthdr.rcvif, &elh, 1); 119 } else 120 ddp_input(m, m->m_pkthdr.rcvif, NULL, 1); 121} 122 123static void 124ddp_input(struct mbuf *m, struct ifnet *ifp, struct elaphdr *elh, int phase) 125{ 126 struct sockaddr_at from, to; 127 struct ddpshdr *dsh, ddps; 128 struct at_ifaddr *aa; 129 struct ddpehdr *deh = NULL, ddpe; 130 struct ddpcb *ddp; 131 int dlen, mlen; 132 u_short cksum = 0; 133 134 bzero((caddr_t)&from, sizeof(struct sockaddr_at)); 135 bzero((caddr_t)&to, sizeof(struct sockaddr_at)); 136 if (elh != NULL) { 137 /* 138 * Extract the information in the short header. Network 139 * information is defaulted to ATADDR_ANYNET and node 140 * information comes from the elh info. We must be phase 1. 141 */ 142 ddpstat.ddps_short++; 143 144 if (m->m_len < sizeof(struct ddpshdr) && 145 ((m = m_pullup(m, sizeof(struct ddpshdr))) == NULL)) { 146 ddpstat.ddps_tooshort++; 147 return; 148 } 149 150 dsh = mtod(m, struct ddpshdr *); 151 bcopy((caddr_t)dsh, (caddr_t)&ddps, sizeof(struct ddpshdr)); 152 ddps.dsh_bytes = ntohl(ddps.dsh_bytes); 153 dlen = ddps.dsh_len; 154 155 to.sat_addr.s_net = ATADDR_ANYNET; 156 to.sat_addr.s_node = elh->el_dnode; 157 to.sat_port = ddps.dsh_dport; 158 from.sat_addr.s_net = ATADDR_ANYNET; 159 from.sat_addr.s_node = elh->el_snode; 160 from.sat_port = ddps.dsh_sport; 161 162 /* 163 * Make sure that we point to the phase1 ifaddr info and that 164 * it's valid for this packet. 165 */ 166 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { 167 if ((aa->aa_ifp == ifp) 168 && ((aa->aa_flags & AFA_PHASE2) == 0) 169 && ((to.sat_addr.s_node == 170 AA_SAT(aa)->sat_addr.s_node) || 171 (to.sat_addr.s_node == ATADDR_BCAST))) 172 break; 173 } 174 /* 175 * maybe we got a broadcast not meant for us.. ditch it. 176 */ 177 if (aa == NULL) { 178 m_freem(m); 179 return; 180 } 181 } else { 182 /* 183 * There was no 'elh' passed on. This could still be either 184 * phase1 or phase2. We have a long header, but we may be 185 * running on a phase 1 net. Extract out all the info 186 * regarding this packet's src & dst. 187 */ 188 ddpstat.ddps_long++; 189 190 if (m->m_len < sizeof(struct ddpehdr) && 191 ((m = m_pullup(m, sizeof(struct ddpehdr))) == NULL)) { 192 ddpstat.ddps_tooshort++; 193 return; 194 } 195 196 deh = mtod(m, struct ddpehdr *); 197 bcopy((caddr_t)deh, (caddr_t)&ddpe, sizeof(struct ddpehdr)); 198 ddpe.deh_bytes = ntohl(ddpe.deh_bytes); 199 dlen = ddpe.deh_len; 200 201 if ((cksum = ddpe.deh_sum) == 0) 202 ddpstat.ddps_nosum++; 203 204 from.sat_addr.s_net = ddpe.deh_snet; 205 from.sat_addr.s_node = ddpe.deh_snode; 206 from.sat_port = ddpe.deh_sport; 207 to.sat_addr.s_net = ddpe.deh_dnet; 208 to.sat_addr.s_node = ddpe.deh_dnode; 209 to.sat_port = ddpe.deh_dport; 210 211 if (to.sat_addr.s_net == ATADDR_ANYNET) { 212 /* 213 * The TO address doesn't specify a net, so by 214 * definition it's for this net. Try find ifaddr 215 * info with the right phase, the right interface, 216 * and either to our node, a broadcast, or looped 217 * back (though that SHOULD be covered in the other 218 * cases). 219 * 220 * XXX If we have multiple interfaces, then the first 221 * with this node number will match (which may NOT be 222 * what we want, but it's probably safe in 99.999% of 223 * cases. 224 */ 225 for (aa = at_ifaddr_list; aa != NULL; 226 aa = aa->aa_next) { 227 if (phase == 1 && (aa->aa_flags & 228 AFA_PHASE2)) 229 continue; 230 if (phase == 2 && (aa->aa_flags & 231 AFA_PHASE2) == 0) 232 continue; 233 if ((aa->aa_ifp == ifp) && 234 ((to.sat_addr.s_node == 235 AA_SAT(aa)->sat_addr.s_node) || 236 (to.sat_addr.s_node == ATADDR_BCAST) || 237 (ifp->if_flags & IFF_LOOPBACK))) 238 break; 239 } 240 } else { 241 /* 242 * A destination network was given. We just try to 243 * find which ifaddr info matches it. 244 */ 245 for (aa = at_ifaddr_list; aa != NULL; 246 aa = aa->aa_next) { 247 /* 248 * This is a kludge. Accept packets that are 249 * for any router on a local netrange. 250 */ 251 if (to.sat_addr.s_net == aa->aa_firstnet && 252 to.sat_addr.s_node == 0) 253 break; 254 /* 255 * Don't use ifaddr info for which we are 256 * totally outside the netrange, and it's not 257 * a startup packet. Startup packets are 258 * always implicitly allowed on to the next 259 * test. 260 */ 261 if (((ntohs(to.sat_addr.s_net) < 262 ntohs(aa->aa_firstnet)) || 263 (ntohs(to.sat_addr.s_net) > 264 ntohs(aa->aa_lastnet))) && 265 ((ntohs(to.sat_addr.s_net) < 0xff00) || 266 (ntohs(to.sat_addr.s_net) > 0xfffe))) 267 continue; 268 269 /* 270 * Don't record a match either if we just 271 * don't have a match in the node address. 272 * This can have if the interface is in 273 * promiscuous mode for example. 274 */ 275 if ((to.sat_addr.s_node != 276 AA_SAT(aa)->sat_addr.s_node) && 277 (to.sat_addr.s_node != ATADDR_BCAST)) 278 continue; 279 break; 280 } 281 } 282 } 283 284 /* 285 * Adjust the length, removing any padding that may have been added 286 * at a link layer. We do this before we attempt to forward a 287 * packet, possibly on a different media. 288 */ 289 mlen = m->m_pkthdr.len; 290 if (mlen < dlen) { 291 ddpstat.ddps_toosmall++; 292 m_freem(m); 293 return; 294 } 295 if (mlen > dlen) 296 m_adj(m, dlen - mlen); 297 298 /* 299 * If it isn't for a net on any of our interfaces, or it IS for a net 300 * on a different interface than it came in on, (and it is not looped 301 * back) then consider if we should forward it. As we are not really 302 * a router this is a bit cheeky, but it may be useful some day. 303 */ 304 if ((aa == NULL) || ((to.sat_addr.s_node == ATADDR_BCAST) && 305 (aa->aa_ifp != ifp) && ((ifp->if_flags & IFF_LOOPBACK) == 0))) { 306 /* 307 * If we've explicitly disabled it, don't route anything. 308 */ 309 if (ddp_forward == 0) { 310 m_freem(m); 311 return; 312 } 313 314 /* 315 * If the cached forwarding route is still valid, use it. 316 * 317 * XXXRW: Access to the cached route may not be properly 318 * synchronized for parallel input handling. 319 */ 320 if (forwro.ro_rt && 321 (satosat(&forwro.ro_dst)->sat_addr.s_net != 322 to.sat_addr.s_net || 323 satosat(&forwro.ro_dst)->sat_addr.s_node != 324 to.sat_addr.s_node)) { 325 RTFREE(forwro.ro_rt); 326 forwro.ro_rt = NULL; 327 } 328 329 /* 330 * If we don't have a cached one (any more) or it's useless, 331 * then get a new route. 332 * 333 * XXX this could cause a 'route leak'. Check this! 334 */ 335 if (forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp == NULL) { 336 forwro.ro_dst.sa_len = sizeof(struct sockaddr_at); 337 forwro.ro_dst.sa_family = AF_APPLETALK; 338 satosat(&forwro.ro_dst)->sat_addr.s_net = 339 to.sat_addr.s_net; 340 satosat(&forwro.ro_dst)->sat_addr.s_node = 341 to.sat_addr.s_node; 342 rtalloc(&forwro); 343 } 344 345 /* 346 * If it's not going to get there on this hop, and it's 347 * already done too many hops, then throw it away. 348 */ 349 if ((to.sat_addr.s_net != 350 satosat(&forwro.ro_dst)->sat_addr.s_net) && 351 (ddpe.deh_hops == DDP_MAXHOPS)) { 352 m_freem(m); 353 return; 354 } 355 356 /* 357 * A ddp router might use the same interface to forward the 358 * packet, which this would not effect. Don't allow packets 359 * to cross from one interface to another however. 360 */ 361 if (ddp_firewall && ((forwro.ro_rt == NULL) || 362 (forwro.ro_rt->rt_ifp != ifp))) { 363 m_freem(m); 364 return; 365 } 366 367 /* 368 * Adjust the header. If it was a short header then it would 369 * have not gotten here, so we can assume there is room to 370 * drop the header in. 371 * 372 * XXX what about promiscuous mode, etc... 373 */ 374 ddpe.deh_hops++; 375 ddpe.deh_bytes = htonl(ddpe.deh_bytes); 376 /* XXX deh? */ 377 bcopy((caddr_t)&ddpe, (caddr_t)deh, sizeof(u_short)); 378 if (ddp_route(m, &forwro)) 379 ddpstat.ddps_cantforward++; 380 else 381 ddpstat.ddps_forward++; 382 return; 383 } 384 385 /* 386 * It was for us, and we have an ifaddr to use with it. 387 */ 388 from.sat_len = sizeof(struct sockaddr_at); 389 from.sat_family = AF_APPLETALK; 390 391 /* 392 * We are no longer interested in the link layer so cut it off. 393 */ 394 if (elh == NULL) { 395 if (ddp_cksum && cksum && cksum != 396 at_cksum(m, sizeof(int))) { 397 ddpstat.ddps_badsum++; 398 m_freem(m); 399 return; 400 } 401 m_adj(m, sizeof(struct ddpehdr)); 402 } else 403 m_adj(m, sizeof(struct ddpshdr)); 404 405 /* 406 * Search for ddp protocol control blocks that match these addresses. 407 */ 408 DDP_LIST_SLOCK(); 409 if ((ddp = ddp_search(&from, &to, aa)) == NULL) 410 goto out; 411 412#ifdef MAC 413 SOCK_LOCK(ddp->ddp_socket); 414 if (mac_check_socket_deliver(ddp->ddp_socket, m) != 0) { 415 SOCK_UNLOCK(ddp->ddp_socket); 416 goto out; 417 } 418 SOCK_UNLOCK(ddp->ddp_socket); 419#endif 420 421 /* 422 * If we found one, deliver the packet to the socket 423 */ 424 SOCKBUF_LOCK(&ddp->ddp_socket->so_rcv); 425 if (sbappendaddr_locked(&ddp->ddp_socket->so_rcv, 426 (struct sockaddr *)&from, m, NULL) == 0) { 427 SOCKBUF_UNLOCK(&ddp->ddp_socket->so_rcv); 428 /* 429 * If the socket is full (or similar error) dump the packet. 430 */ 431 ddpstat.ddps_nosockspace++; 432 goto out; 433 } 434 435 /* 436 * And wake up whatever might be waiting for it 437 */ 438 sorwakeup_locked(ddp->ddp_socket); 439 m = NULL; 440out: 441 DDP_LIST_SUNLOCK(); 442 if (m != NULL) 443 m_freem(m); 444} 445