diff options
author | Robert Watson <rwatson@FreeBSD.org> | 2007-01-12 15:07:51 +0000 |
---|---|---|
committer | Robert Watson <rwatson@FreeBSD.org> | 2007-01-12 15:07:51 +0000 |
commit | ca9f93ff42d497b79f16bb76bc773a51069c1dce (patch) | |
tree | 0c7da38e01fe89ae2fb1dd585f10f4540df68ca0 /sys/netatalk/ddp_input.c | |
parent | af07bd5661b8450b779ff14d00f7186f62751bba (diff) | |
download | src-ca9f93ff42d497b79f16bb76bc773a51069c1dce.tar.gz src-ca9f93ff42d497b79f16bb76bc773a51069c1dce.zip |
Clean up DDP layer netatalk code:
- General style(9) cleanup -- white space, braces, line wraps, etc.
- Annotate a lack of synchronization the global route cache if the input
routine is invoked with parallelism.
- Remove unused debugging code.
Notes
Notes:
svn path=/head/; revision=165974
Diffstat (limited to 'sys/netatalk/ddp_input.c')
-rw-r--r-- | sys/netatalk/ddp_input.c | 636 |
1 files changed, 288 insertions, 348 deletions
diff --git a/sys/netatalk/ddp_input.c b/sys/netatalk/ddp_input.c index c8f9e420355e..7e15cb190845 100644 --- a/sys/netatalk/ddp_input.c +++ b/sys/netatalk/ddp_input.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Copyright (c) 1990,1994 Regents of The University of Michigan. + * Copyright (c) 1990, 1994 Regents of The University of Michigan. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, @@ -88,10 +88,9 @@ at2intr(struct mbuf *m) { /* - * Phase 2 packet handling + * Phase 2 packet handling . */ ddp_input(m, m->m_pkthdr.rcvif, NULL, 2); - return; } void @@ -102,7 +101,8 @@ at1intr(struct mbuf *m) /* * Phase 1 packet handling */ - if (m->m_len < SZ_ELAPHDR && ((m = m_pullup(m, SZ_ELAPHDR)) == NULL)) { + if (m->m_len < SZ_ELAPHDR && ((m = m_pullup(m, SZ_ELAPHDR)) == + NULL)) { ddpstat.ddps_tooshort++; return; } @@ -113,392 +113,332 @@ at1intr(struct mbuf *m) elhp = mtod(m, struct elaphdr *); m_adj(m, SZ_ELAPHDR); - if (elhp->el_type == ELAP_DDPEXTEND) { - ddp_input(m, m->m_pkthdr.rcvif, NULL, 1); - } else { + if (elhp->el_type != ELAP_DDPEXTEND) { bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR); ddp_input(m, m->m_pkthdr.rcvif, &elh, 1); - } - return; + } else + ddp_input(m, m->m_pkthdr.rcvif, NULL, 1); } static void -ddp_input(m, ifp, elh, phase) - struct mbuf *m; - struct ifnet *ifp; - struct elaphdr *elh; - int phase; +ddp_input(struct mbuf *m, struct ifnet *ifp, struct elaphdr *elh, int phase) { - struct sockaddr_at from, to; - struct ddpshdr *dsh, ddps; - struct at_ifaddr *aa; - struct ddpehdr *deh = NULL, ddpe; - struct ddpcb *ddp; - int dlen, mlen; - u_short cksum = 0; - - bzero((caddr_t)&from, sizeof(struct sockaddr_at)); - bzero((caddr_t)&to, sizeof(struct sockaddr_at)); - if (elh != NULL) { - /* - * Extract the information in the short header. - * netowrk information is defaulted to ATADDR_ANYNET - * and node information comes from the elh info. - * We must be phase 1. - */ - ddpstat.ddps_short++; + struct sockaddr_at from, to; + struct ddpshdr *dsh, ddps; + struct at_ifaddr *aa; + struct ddpehdr *deh = NULL, ddpe; + struct ddpcb *ddp; + int dlen, mlen; + u_short cksum = 0; + + bzero((caddr_t)&from, sizeof(struct sockaddr_at)); + bzero((caddr_t)&to, sizeof(struct sockaddr_at)); + if (elh != NULL) { + /* + * Extract the information in the short header. Network + * information is defaulted to ATADDR_ANYNET and node + * information comes from the elh info. We must be phase 1. + */ + ddpstat.ddps_short++; - if (m->m_len < sizeof(struct ddpshdr) && - ((m = m_pullup(m, sizeof(struct ddpshdr))) == NULL)) { - ddpstat.ddps_tooshort++; - return; - } + if (m->m_len < sizeof(struct ddpshdr) && + ((m = m_pullup(m, sizeof(struct ddpshdr))) == NULL)) { + ddpstat.ddps_tooshort++; + return; + } - dsh = mtod(m, struct ddpshdr *); - bcopy((caddr_t)dsh, (caddr_t)&ddps, sizeof(struct ddpshdr)); - ddps.dsh_bytes = ntohl(ddps.dsh_bytes); - dlen = ddps.dsh_len; + dsh = mtod(m, struct ddpshdr *); + bcopy((caddr_t)dsh, (caddr_t)&ddps, sizeof(struct ddpshdr)); + ddps.dsh_bytes = ntohl(ddps.dsh_bytes); + dlen = ddps.dsh_len; + + to.sat_addr.s_net = ATADDR_ANYNET; + to.sat_addr.s_node = elh->el_dnode; + to.sat_port = ddps.dsh_dport; + from.sat_addr.s_net = ATADDR_ANYNET; + from.sat_addr.s_node = elh->el_snode; + from.sat_port = ddps.dsh_sport; + + /* + * Make sure that we point to the phase1 ifaddr info and that + * it's valid for this packet. + */ + for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { + if ((aa->aa_ifp == ifp) + && ((aa->aa_flags & AFA_PHASE2) == 0) + && ((to.sat_addr.s_node == + AA_SAT(aa)->sat_addr.s_node) || + (to.sat_addr.s_node == ATADDR_BCAST))) + break; + } + /* + * maybe we got a broadcast not meant for us.. ditch it. + */ + if (aa == NULL) { + m_freem(m); + return; + } + } else { + /* + * There was no 'elh' passed on. This could still be either + * phase1 or phase2. We have a long header, but we may be + * running on a phase 1 net. Extract out all the info + * regarding this packet's src & dst. + */ + ddpstat.ddps_long++; - to.sat_addr.s_net = ATADDR_ANYNET; - to.sat_addr.s_node = elh->el_dnode; - to.sat_port = ddps.dsh_dport; - from.sat_addr.s_net = ATADDR_ANYNET; - from.sat_addr.s_node = elh->el_snode; - from.sat_port = ddps.dsh_sport; + if (m->m_len < sizeof(struct ddpehdr) && + ((m = m_pullup(m, sizeof(struct ddpehdr))) == NULL)) { + ddpstat.ddps_tooshort++; + return; + } - /* - * Make sure that we point to the phase1 ifaddr info - * and that it's valid for this packet. - */ - for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { - if ((aa->aa_ifp == ifp) - && ((aa->aa_flags & AFA_PHASE2) == 0) - && ((to.sat_addr.s_node == AA_SAT(aa)->sat_addr.s_node) - || (to.sat_addr.s_node == ATADDR_BCAST))) { - break; - } - } - /* - * maybe we got a broadcast not meant for us.. ditch it. - */ - if (aa == NULL) { - m_freem(m); - return; + deh = mtod(m, struct ddpehdr *); + bcopy((caddr_t)deh, (caddr_t)&ddpe, sizeof(struct ddpehdr)); + ddpe.deh_bytes = ntohl(ddpe.deh_bytes); + dlen = ddpe.deh_len; + + if ((cksum = ddpe.deh_sum) == 0) + ddpstat.ddps_nosum++; + + from.sat_addr.s_net = ddpe.deh_snet; + from.sat_addr.s_node = ddpe.deh_snode; + from.sat_port = ddpe.deh_sport; + to.sat_addr.s_net = ddpe.deh_dnet; + to.sat_addr.s_node = ddpe.deh_dnode; + to.sat_port = ddpe.deh_dport; + + if (to.sat_addr.s_net == ATADDR_ANYNET) { + /* + * The TO address doesn't specify a net, so by + * definition it's for this net. Try find ifaddr + * info with the right phase, the right interface, + * and either to our node, a broadcast, or looped + * back (though that SHOULD be covered in the other + * cases). + * + * XXX If we have multiple interfaces, then the first + * with this node number will match (which may NOT be + * what we want, but it's probably safe in 99.999% of + * cases. + */ + for (aa = at_ifaddr_list; aa != NULL; + aa = aa->aa_next) { + if (phase == 1 && (aa->aa_flags & + AFA_PHASE2)) + continue; + if (phase == 2 && (aa->aa_flags & + AFA_PHASE2) == 0) + continue; + if ((aa->aa_ifp == ifp) && + ((to.sat_addr.s_node == + AA_SAT(aa)->sat_addr.s_node) || + (to.sat_addr.s_node == ATADDR_BCAST) || + (ifp->if_flags & IFF_LOOPBACK))) + break; + } + } else { + /* + * A destination network was given. We just try to + * find which ifaddr info matches it. + */ + for (aa = at_ifaddr_list; aa != NULL; + aa = aa->aa_next) { + /* + * This is a kludge. Accept packets that are + * for any router on a local netrange. + */ + if (to.sat_addr.s_net == aa->aa_firstnet && + to.sat_addr.s_node == 0) + break; + /* + * Don't use ifaddr info for which we are + * totally outside the netrange, and it's not + * a startup packet. Startup packets are + * always implicitly allowed on to the next + * test. + */ + if (((ntohs(to.sat_addr.s_net) < + ntohs(aa->aa_firstnet)) || + (ntohs(to.sat_addr.s_net) > + ntohs(aa->aa_lastnet))) && + ((ntohs(to.sat_addr.s_net) < 0xff00) || + (ntohs(to.sat_addr.s_net) > 0xfffe))) + continue; + + /* + * Don't record a match either if we just + * don't have a match in the node address. + * This can have if the interface is in + * promiscuous mode for example. + */ + if ((to.sat_addr.s_node != + AA_SAT(aa)->sat_addr.s_node) && + (to.sat_addr.s_node != ATADDR_BCAST)) + continue; + break; + } + } } - } else { + /* - * There was no 'elh' passed on. This could still be - * either phase1 or phase2. - * We have a long header, but we may be running on a phase 1 net. - * Extract out all the info regarding this packet's src & dst. + * Adjust the length, removing any padding that may have been added + * at a link layer. We do this before we attempt to forward a + * packet, possibly on a different media. */ - ddpstat.ddps_long++; - - if (m->m_len < sizeof(struct ddpehdr) && - ((m = m_pullup(m, sizeof(struct ddpehdr))) == NULL)) { - ddpstat.ddps_tooshort++; - return; - } - - deh = mtod(m, struct ddpehdr *); - bcopy((caddr_t)deh, (caddr_t)&ddpe, sizeof(struct ddpehdr)); - ddpe.deh_bytes = ntohl(ddpe.deh_bytes); - dlen = ddpe.deh_len; - - if ((cksum = ddpe.deh_sum) == 0) { - ddpstat.ddps_nosum++; + mlen = m->m_pkthdr.len; + if (mlen < dlen) { + ddpstat.ddps_toosmall++; + m_freem(m); + return; } + if (mlen > dlen) + m_adj(m, dlen - mlen); - from.sat_addr.s_net = ddpe.deh_snet; - from.sat_addr.s_node = ddpe.deh_snode; - from.sat_port = ddpe.deh_sport; - to.sat_addr.s_net = ddpe.deh_dnet; - to.sat_addr.s_node = ddpe.deh_dnode; - to.sat_port = ddpe.deh_dport; - - if (to.sat_addr.s_net == ATADDR_ANYNET) { - /* - * The TO address doesn't specify a net, - * So by definition it's for this net. - * Try find ifaddr info with the right phase, - * the right interface, and either to our node, a broadcast, - * or looped back (though that SHOULD be covered in the other - * cases). - * - * XXX If we have multiple interfaces, then the first with - * this node number will match (which may NOT be what we want, - * but it's probably safe in 99.999% of cases. - */ - for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { - if (phase == 1 && (aa->aa_flags & AFA_PHASE2)) { - continue; - } - if (phase == 2 && (aa->aa_flags & AFA_PHASE2) == 0) { - continue; + /* + * If it isn't for a net on any of our interfaces, or it IS for a net + * on a different interface than it came in on, (and it is not looped + * back) then consider if we should forward it. As we are not really + * a router this is a bit cheeky, but it may be useful some day. + */ + if ((aa == NULL) || ((to.sat_addr.s_node == ATADDR_BCAST) && + (aa->aa_ifp != ifp) && ((ifp->if_flags & IFF_LOOPBACK) == 0))) { + /* + * If we've explicitly disabled it, don't route anything. + */ + if (ddp_forward == 0) { + m_freem(m); + return; } - if ((aa->aa_ifp == ifp) - && ((to.sat_addr.s_node == AA_SAT(aa)->sat_addr.s_node) - || (to.sat_addr.s_node == ATADDR_BCAST) - || (ifp->if_flags & IFF_LOOPBACK))) { - break; + + /* + * If the cached forwarding route is still valid, use it. + * + * XXXRW: Access to the cached route may not be properly + * synchronized for parallel input handling. + */ + if (forwro.ro_rt && + (satosat(&forwro.ro_dst)->sat_addr.s_net != + to.sat_addr.s_net || + satosat(&forwro.ro_dst)->sat_addr.s_node != + to.sat_addr.s_node)) { + RTFREE(forwro.ro_rt); + forwro.ro_rt = NULL; } - } - } else { - /* - * A destination network was given. We just try to find - * which ifaddr info matches it. - */ - for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { + /* - * This is a kludge. Accept packets that are - * for any router on a local netrange. + * If we don't have a cached one (any more) or it's useless, + * then get a new route. + * + * XXX this could cause a 'route leak'. Check this! */ - if (to.sat_addr.s_net == aa->aa_firstnet && - to.sat_addr.s_node == 0) { - break; + if (forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp == NULL) { + forwro.ro_dst.sa_len = sizeof(struct sockaddr_at); + forwro.ro_dst.sa_family = AF_APPLETALK; + satosat(&forwro.ro_dst)->sat_addr.s_net = + to.sat_addr.s_net; + satosat(&forwro.ro_dst)->sat_addr.s_node = + to.sat_addr.s_node; + rtalloc(&forwro); } - /* - * Don't use ifaddr info for which we are totally outside the - * netrange, and it's not a startup packet. - * Startup packets are always implicitly allowed on to - * the next test. + + /* + * If it's not going to get there on this hop, and it's + * already done too many hops, then throw it away. */ - if (((ntohs(to.sat_addr.s_net) < ntohs(aa->aa_firstnet)) - || (ntohs(to.sat_addr.s_net) > ntohs(aa->aa_lastnet))) - && ((ntohs(to.sat_addr.s_net) < 0xff00) - || (ntohs(to.sat_addr.s_net) > 0xfffe))) { - continue; + if ((to.sat_addr.s_net != + satosat(&forwro.ro_dst)->sat_addr.s_net) && + (ddpe.deh_hops == DDP_MAXHOPS)) { + m_freem(m); + return; } /* - * Don't record a match either if we just don't have a match - * in the node address. This can have if the interface - * is in promiscuous mode for example. + * A ddp router might use the same interface to forward the + * packet, which this would not effect. Don't allow packets + * to cross from one interface to another however. */ - if ((to.sat_addr.s_node != AA_SAT(aa)->sat_addr.s_node) - && (to.sat_addr.s_node != ATADDR_BCAST)) { - continue; + if (ddp_firewall && ((forwro.ro_rt == NULL) || + (forwro.ro_rt->rt_ifp != ifp))) { + m_freem(m); + return; } - break; - } - } - } - - /* - * Adjust the length, removing any padding that may have been added - * at a link layer. We do this before we attempt to forward a packet, - * possibly on a different media. - */ - mlen = m->m_pkthdr.len; - if (mlen < dlen) { - ddpstat.ddps_toosmall++; - m_freem(m); - return; - } - if (mlen > dlen) { - m_adj(m, dlen - mlen); - } - - /* - * If it aint for a net on any of our interfaces, - * or it IS for a net on a different interface than it came in on, - * (and it is not looped back) then consider if we should forward it. - * As we are not really a router this is a bit cheeky, but it may be - * useful some day. - */ - if ((aa == NULL) - || ((to.sat_addr.s_node == ATADDR_BCAST) - && (aa->aa_ifp != ifp) - && ((ifp->if_flags & IFF_LOOPBACK) == 0))) { - /* - * If we've explicitly disabled it, don't route anything - */ - if (ddp_forward == 0) { - m_freem(m); - return; - } - /* - * If the cached forwarding route is still valid, use it. - */ - if (forwro.ro_rt - && (satosat(&forwro.ro_dst)->sat_addr.s_net != to.sat_addr.s_net - || satosat(&forwro.ro_dst)->sat_addr.s_node != to.sat_addr.s_node)) { - RTFREE(forwro.ro_rt); - forwro.ro_rt = NULL; + + /* + * Adjust the header. If it was a short header then it would + * have not gotten here, so we can assume there is room to + * drop the header in. + * + * XXX what about promiscuous mode, etc... + */ + ddpe.deh_hops++; + ddpe.deh_bytes = htonl(ddpe.deh_bytes); + /* XXX deh? */ + bcopy((caddr_t)&ddpe, (caddr_t)deh, sizeof(u_short)); + if (ddp_route(m, &forwro)) + ddpstat.ddps_cantforward++; + else + ddpstat.ddps_forward++; + return; } /* - * If we don't have a cached one (any more) or it's useless, - * Then get a new route. - * XXX this could cause a 'route leak'. check this! + * It was for us, and we have an ifaddr to use with it. */ - if (forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp == NULL) { - forwro.ro_dst.sa_len = sizeof(struct sockaddr_at); - forwro.ro_dst.sa_family = AF_APPLETALK; - satosat(&forwro.ro_dst)->sat_addr.s_net = to.sat_addr.s_net; - satosat(&forwro.ro_dst)->sat_addr.s_node = to.sat_addr.s_node; - rtalloc(&forwro); - } + from.sat_len = sizeof(struct sockaddr_at); + from.sat_family = AF_APPLETALK; /* - * If it's not going to get there on this hop, and it's - * already done too many hops, then throw it away. - */ - if ((to.sat_addr.s_net != satosat(&forwro.ro_dst)->sat_addr.s_net) - && (ddpe.deh_hops == DDP_MAXHOPS)) { - m_freem(m); - return; - } - - /* - * A ddp router might use the same interface - * to forward the packet, which this would not effect. - * Don't allow packets to cross from one interface to another however. + * We are no longer interested in the link layer so cut it off. */ - if (ddp_firewall - && ((forwro.ro_rt == NULL) - || (forwro.ro_rt->rt_ifp != ifp))) { - m_freem(m); - return; - } + if (elh == NULL) { + if (ddp_cksum && cksum && cksum != + at_cksum(m, sizeof(int))) { + ddpstat.ddps_badsum++; + m_freem(m); + return; + } + m_adj(m, sizeof(struct ddpehdr)); + } else + m_adj(m, sizeof(struct ddpshdr)); - /* - * Adjust the header. - * If it was a short header then it would have not gotten here, - * so we can assume there is room to drop the header in. - * XXX what about promiscuous mode, etc... + /* + * Search for ddp protocol control blocks that match these addresses. */ - ddpe.deh_hops++; - ddpe.deh_bytes = htonl(ddpe.deh_bytes); - bcopy((caddr_t)&ddpe, (caddr_t)deh, sizeof(u_short)); /* XXX deh? */ - if (ddp_route(m, &forwro)) { - ddpstat.ddps_cantforward++; - } else { - ddpstat.ddps_forward++; - } - return; - } - - /* - * It was for us, and we have an ifaddr to use with it. - */ - from.sat_len = sizeof(struct sockaddr_at); - from.sat_family = AF_APPLETALK; - - /* - * We are no longer interested in the link layer. - * so cut it off. - */ - if (elh != NULL) { - m_adj(m, sizeof(struct ddpshdr)); - } else { - if (ddp_cksum && cksum && cksum != at_cksum(m, sizeof(int))) { - ddpstat.ddps_badsum++; - m_freem(m); - return; - } - m_adj(m, sizeof(struct ddpehdr)); - } - - /* - * Search for ddp protocol control blocks that match these - * addresses. - */ - DDP_LIST_SLOCK(); - if ((ddp = ddp_search(&from, &to, aa)) == NULL) { - goto out; - } + DDP_LIST_SLOCK(); + if ((ddp = ddp_search(&from, &to, aa)) == NULL) + goto out; #ifdef MAC - SOCK_LOCK(ddp->ddp_socket); - if (mac_check_socket_deliver(ddp->ddp_socket, m) != 0) { + SOCK_LOCK(ddp->ddp_socket); + if (mac_check_socket_deliver(ddp->ddp_socket, m) != 0) { + SOCK_UNLOCK(ddp->ddp_socket); + goto out; + } SOCK_UNLOCK(ddp->ddp_socket); - goto out; - } - SOCK_UNLOCK(ddp->ddp_socket); #endif - /* - * If we found one, deliver the packet to the socket - */ - SOCKBUF_LOCK(&ddp->ddp_socket->so_rcv); - if (sbappendaddr_locked(&ddp->ddp_socket->so_rcv, (struct sockaddr *)&from, - m, NULL) == 0) { - SOCKBUF_UNLOCK(&ddp->ddp_socket->so_rcv); /* - * If the socket is full (or similar error) dump the packet. + * If we found one, deliver the packet to the socket */ - ddpstat.ddps_nosockspace++; - goto out; - } - /* - * And wake up whatever might be waiting for it - */ - sorwakeup_locked(ddp->ddp_socket); - m = NULL; -out: - DDP_LIST_SUNLOCK(); - if (m != NULL) - m_freem(m); -} - -#if 0 -/* As if we haven't got enough of this sort of think floating -around the kernel :) */ - -#define BPXLEN 48 -#define BPALEN 16 -#include <ctype.h> -char hexdig[] = "0123456789ABCDEF"; - -static void -bprint(char *data, int len) -{ - char xout[ BPXLEN ], aout[ BPALEN ]; - int i = 0; - - bzero(xout, BPXLEN); - bzero(aout, BPALEN); - - for (;;) { - if (len < 1) { - if (i != 0) { - printf("%s\t%s\n", xout, aout); - } - printf("%s\n", "(end)"); - break; - } - - xout[ (i*3) ] = hexdig[ (*data & 0xf0) >> 4 ]; - xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ]; - - if ((u_char)*data < 0x7f && (u_char)*data > 0x20) { - aout[ i ] = *data; - } else { - aout[ i ] = '.'; - } - - xout[ (i*3) + 2 ] = ' '; - - i++; - len--; - data++; - - if (i > BPALEN - 2) { - printf("%s\t%s\n", xout, aout); - bzero(xout, BPXLEN); - bzero(aout, BPALEN); - i = 0; - continue; + SOCKBUF_LOCK(&ddp->ddp_socket->so_rcv); + if (sbappendaddr_locked(&ddp->ddp_socket->so_rcv, + (struct sockaddr *)&from, m, NULL) == 0) { + SOCKBUF_UNLOCK(&ddp->ddp_socket->so_rcv); + /* + * If the socket is full (or similar error) dump the packet. + */ + ddpstat.ddps_nosockspace++; + goto out; } - } -} -static void -m_printm(struct mbuf *m) -{ - for (; m; m = m->m_next) { - bprint(mtod(m, char *), m->m_len); - } + /* + * And wake up whatever might be waiting for it + */ + sorwakeup_locked(ddp->ddp_socket); + m = NULL; +out: + DDP_LIST_SUNLOCK(); + if (m != NULL) + m_freem(m); } -#endif |