[BACK]Return to ddp_output.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netatalk

Annotation of src/sys/netatalk/ddp_output.c, Revision 1.17

1.17    ! martin      1: /*     $NetBSD: ddp_output.c,v 1.16 2012/01/31 09:53:44 hauke Exp $     */
1.1       christos    2:
                      3: /*
                      4:  * Copyright (c) 1990,1991 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:  */
1.3       lukem      28:
                     29: #include <sys/cdefs.h>
1.17    ! martin     30: __KERNEL_RCSID(0, "$NetBSD: ddp_output.c,v 1.16 2012/01/31 09:53:44 hauke Exp $");
1.1       christos   31:
                     32: #include <sys/param.h>
                     33: #include <sys/systm.h>
                     34: #include <sys/mbuf.h>
                     35: #include <sys/socket.h>
                     36: #include <sys/errno.h>
                     37: #include <sys/syslog.h>
                     38:
                     39: #include <net/if.h>
                     40: #include <net/route.h>
                     41: #include <net/if_ether.h>
                     42:
                     43: #include <netinet/in.h>
                     44: #undef s_net
                     45:
                     46: #include <netatalk/at.h>
                     47: #include <netatalk/at_var.h>
                     48: #include <netatalk/ddp.h>
                     49: #include <netatalk/ddp_var.h>
                     50: #include <netatalk/at_extern.h>
                     51:
                     52: int ddp_cksum = 1;
                     53:
                     54: int
                     55: ddp_output(struct mbuf *m,...)
                     56: {
                     57:        struct ddpcb   *ddp;
                     58:        struct ddpehdr *deh;
                     59:        va_list         ap;
                     60:
                     61:        va_start(ap, m);
                     62:        ddp = va_arg(ap, struct ddpcb *);
                     63:        va_end(ap);
                     64:
1.7       itojun     65:        M_PREPEND(m, sizeof(struct ddpehdr), M_DONTWAIT);
                     66:        if (!m)
                     67:                return (ENOBUFS);
1.1       christos   68:
                     69:        deh = mtod(m, struct ddpehdr *);
                     70:        deh->deh_pad = 0;
                     71:        deh->deh_hops = 0;
                     72:
                     73:        deh->deh_len = m->m_pkthdr.len;
                     74:
                     75:        deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net;
                     76:        deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node;
                     77:        deh->deh_dport = ddp->ddp_fsat.sat_port;
                     78:        deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net;
                     79:        deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node;
                     80:        deh->deh_sport = ddp->ddp_lsat.sat_port;
                     81:
                     82:        /*
                     83:          * The checksum calculation is done after all of the other bytes have
                     84:          * been filled in.
                     85:          */
1.11      dyoung     86:        if (ddp_cksum)
1.1       christos   87:                deh->deh_sum = at_cksum(m, sizeof(int));
1.11      dyoung     88:        else
1.1       christos   89:                deh->deh_sum = 0;
                     90:        deh->deh_bytes = htonl(deh->deh_bytes);
                     91:
1.11      dyoung     92:        return ddp_route(m, &ddp->ddp_route);
1.1       christos   93: }
                     94:
                     95: u_short
1.11      dyoung     96: at_cksum(struct mbuf *m, int skip)
1.1       christos   97: {
                     98:        u_char         *data, *end;
                     99:        u_long          cksum = 0;
                    100:
                    101:        for (; m; m = m->m_next) {
                    102:                for (data = mtod(m, u_char *), end = data + m->m_len;
                    103:                    data < end; data++) {
                    104:                        if (skip) {
                    105:                                skip--;
                    106:                                continue;
                    107:                        }
                    108:                        cksum = (cksum + *data) << 1;
1.11      dyoung    109:                        if (cksum & 0x00010000)
1.1       christos  110:                                cksum++;
                    111:                        cksum &= 0x0000ffff;
                    112:                }
                    113:        }
                    114:
                    115:        if (cksum == 0) {
                    116:                cksum = 0x0000ffff;
                    117:        }
1.11      dyoung    118:        return (u_short)cksum;
1.1       christos  119: }
                    120:
                    121: int
1.11      dyoung    122: ddp_route(struct mbuf *m, struct route *ro)
1.1       christos  123: {
1.12      dyoung    124:        struct rtentry *rt;
1.1       christos  125:        struct sockaddr_at gate;
                    126:        struct elaphdr *elh;
                    127:        struct at_ifaddr *aa = NULL;
                    128:        struct ifnet   *ifp = NULL;
1.16      hauke     129:        uint16_t        net;
                    130:        uint8_t         loopback = 0;
1.1       christos  131:
1.14      dyoung    132:        if ((rt = rtcache_validate(ro)) != NULL && (ifp = rt->rt_ifp) != NULL) {
1.16      hauke     133:                const struct sockaddr_at *dst = satocsat(rtcache_getdst(ro));
                    134:                uint16_t dnet = dst->sat_addr.s_net;
                    135:                uint8_t dnode = dst->sat_addr.s_node;
1.12      dyoung    136:                net = satosat(rt->rt_gateway)->sat_addr.s_net;
1.16      hauke     137:
1.11      dyoung    138:                TAILQ_FOREACH(aa, &at_ifaddr, aa_list) {
1.16      hauke     139:                        if (ntohs(net) >= ntohs(aa->aa_firstnet) &&
1.1       christos  140:                            ntohs(net) <= ntohs(aa->aa_lastnet)) {
1.16      hauke     141:                                /* Are we talking to ourselves? */
                    142:                                if (dnet == aa->aa_addr.sat_addr.s_net &&
                    143:                                    dnode == aa->aa_addr.sat_addr.s_node) {
                    144:                                        /* If to us, redirect to lo0. */
                    145:                                        ifp = lo0ifp;
                    146:                                }
                    147:                                /* Or is it a broadcast? */
                    148:                                else if (dnet == aa->aa_addr.sat_addr.s_net &&
                    149:                                        dnode == 255) {
                    150:                                        /* If broadcast, loop back a copy. */
                    151:                                        loopback = 1;
                    152:                                }
1.1       christos  153:                                break;
                    154:                        }
                    155:                }
                    156:        }
                    157:        if (aa == NULL) {
1.16      hauke     158: #ifdef NETATALKDEBUG
1.11      dyoung    159:                printf("%s: no address found\n", __func__);
1.16      hauke     160: #endif
1.1       christos  161:                m_freem(m);
1.11      dyoung    162:                return EINVAL;
1.1       christos  163:        }
                    164:        /*
                    165:          * There are several places in the kernel where data is added to
                    166:          * an mbuf without ensuring that the mbuf pointer is aligned.
                    167:          * This is bad for transition routing, since phase 1 and phase 2
                    168:          * packets end up poorly aligned due to the three byte elap header.
                    169:          */
                    170:        if (!(aa->aa_flags & AFA_PHASE2)) {
1.7       itojun    171:                M_PREPEND(m, SZ_ELAPHDR, M_DONTWAIT);
1.11      dyoung    172:                if (m == NULL)
                    173:                        return ENOBUFS;
1.1       christos  174:
                    175:                elh = mtod(m, struct elaphdr *);
                    176:                elh->el_snode = satosat(&aa->aa_addr)->sat_addr.s_node;
                    177:                elh->el_type = ELAP_DDPEXTEND;
1.11      dyoung    178:                if (ntohs(satocsat(rtcache_getdst(ro))->sat_addr.s_net) >=
1.1       christos  179:                    ntohs(aa->aa_firstnet) &&
1.11      dyoung    180:                    ntohs(satocsat(rtcache_getdst(ro))->sat_addr.s_net) <=
1.1       christos  181:                    ntohs(aa->aa_lastnet)) {
1.16      hauke     182:                        elh->el_dnode =
                    183:                            satocsat(rtcache_getdst(ro))->sat_addr.s_node;
1.1       christos  184:                } else {
                    185:                        elh->el_dnode =
1.12      dyoung    186:                            satosat(rt->rt_gateway)->sat_addr.s_node;
1.1       christos  187:                }
                    188:        }
1.11      dyoung    189:        if (ntohs(satocsat(rtcache_getdst(ro))->sat_addr.s_net) >=
1.1       christos  190:            ntohs(aa->aa_firstnet) &&
1.11      dyoung    191:            ntohs(satocsat(rtcache_getdst(ro))->sat_addr.s_net) <=
1.1       christos  192:            ntohs(aa->aa_lastnet)) {
1.11      dyoung    193:                gate = *satocsat(rtcache_getdst(ro));
1.1       christos  194:        } else {
1.12      dyoung    195:                gate = *satosat(rt->rt_gateway);
1.1       christos  196:        }
1.12      dyoung    197:        rt->rt_use++;
1.2       aidan     198:
                    199: #if IFA_STATS
                    200:        aa->aa_ifa.ifa_data.ifad_outbytes += m->m_pkthdr.len;
                    201: #endif
1.1       christos  202:
                    203:        /* XXX */
1.16      hauke     204:        if (loopback && rtcache_getdst(ro)->sa_family == AF_APPLETALK) {
                    205:                struct mbuf *copym = m_copypacket(m, M_DONTWAIT);
                    206:
                    207: #ifdef NETATALKDEBUG
                    208:                printf("Looping back (not AARP).\n");
                    209: #endif
                    210:                looutput(lo0ifp, copym, rtcache_getdst(ro), NULL);
                    211:        }
1.11      dyoung    212:        return (*ifp->if_output)(ifp, m, (struct sockaddr *)&gate, NULL);
1.1       christos  213: }

CVSweb <webmaster@jp.NetBSD.org>