The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netatalk/ddp_output.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1990,1991 Regents of The University of Michigan.
    3  * All Rights Reserved.
    4  *
    5  * Permission to use, copy, modify, and distribute this software and
    6  * its documentation for any purpose and without fee is hereby granted,
    7  * provided that the above copyright notice appears in all copies and
    8  * that both that copyright notice and this permission notice appear
    9  * in supporting documentation, and that the name of The University
   10  * of Michigan not be used in advertising or publicity pertaining to
   11  * distribution of the software without specific, written prior
   12  * permission. This software is supplied as is without expressed or
   13  * implied warranties of any kind.
   14  *
   15  *      Research Systems Unix Group
   16  *      The University of Michigan
   17  *      c/o Mike Clark
   18  *      535 W. William Street
   19  *      Ann Arbor, Michigan
   20  *      +1-313-763-0525
   21  *      netatalk@itd.umich.edu
   22  */
   23 
   24 /* $FreeBSD$ */
   25 
   26 #include "opt_mac.h"
   27 
   28 #include <sys/param.h>
   29 #include <sys/systm.h>
   30 #include <sys/mac.h>
   31 #include <sys/mbuf.h>
   32 #include <sys/socket.h>
   33 #include <sys/socketvar.h>
   34 
   35 #include <net/if.h>
   36 #include <net/route.h>
   37 
   38 #undef s_net
   39 
   40 #include <netatalk/at.h>
   41 #include <netatalk/at_var.h>
   42 #include <netatalk/ddp.h>
   43 #include <netatalk/ddp_var.h>
   44 #include <netatalk/at_extern.h>
   45 
   46 int     ddp_cksum = 1;
   47 
   48 int
   49 ddp_output(struct mbuf *m, struct socket *so)
   50 {
   51     struct ddpehdr      *deh;
   52     struct ddpcb *ddp = sotoddpcb(so);
   53 
   54 #ifdef MAC
   55     SOCK_LOCK(so);
   56     mac_create_mbuf_from_socket(so, m);
   57     SOCK_UNLOCK(so);
   58 #endif
   59 
   60     M_PREPEND(m, sizeof(struct ddpehdr), M_DONTWAIT);
   61     if (m == NULL)
   62         return (ENOBUFS);
   63 
   64     deh = mtod(m, struct ddpehdr *);
   65     deh->deh_pad = 0;
   66     deh->deh_hops = 0;
   67 
   68     deh->deh_len = m->m_pkthdr.len;
   69 
   70     deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net;
   71     deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node;
   72     deh->deh_dport = ddp->ddp_fsat.sat_port;
   73     deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net;
   74     deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node;
   75     deh->deh_sport = ddp->ddp_lsat.sat_port;
   76 
   77     /*
   78      * The checksum calculation is done after all of the other bytes have
   79      * been filled in.
   80      */
   81     if (ddp_cksum) {
   82         deh->deh_sum = at_cksum(m, sizeof(int));
   83     } else {
   84         deh->deh_sum = 0;
   85     }
   86     deh->deh_bytes = htonl(deh->deh_bytes);
   87 
   88 #ifdef NETATALK_DEBUG
   89     printf ("ddp_output: from %d.%d:%d to %d.%d:%d\n",
   90         ntohs(deh->deh_snet), deh->deh_snode, deh->deh_sport,
   91         ntohs(deh->deh_dnet), deh->deh_dnode, deh->deh_dport);
   92 #endif
   93     return (ddp_route(m, &ddp->ddp_route));
   94 }
   95 
   96 u_short
   97 at_cksum(struct mbuf *m, int skip)
   98 {
   99     u_char      *data, *end;
  100     u_long      cksum = 0;
  101 
  102     for (; m; m = m->m_next) {
  103         for (data = mtod(m, u_char *), end = data + m->m_len; data < end;
  104                 data++) {
  105             if (skip) {
  106                 skip--;
  107                 continue;
  108             }
  109             cksum = (cksum + *data) << 1;
  110             if (cksum & 0x00010000) {
  111                 cksum++;
  112             }
  113             cksum &= 0x0000ffff;
  114         }
  115     }
  116 
  117     if (cksum == 0) {
  118         cksum = 0x0000ffff;
  119     }
  120     return ((u_short)cksum);
  121 }
  122 
  123 int
  124 ddp_route(struct mbuf *m, struct route *ro)
  125 {
  126     struct sockaddr_at  gate;
  127     struct elaphdr      *elh;
  128     struct mbuf         *m0;
  129     struct at_ifaddr    *aa = NULL;
  130     struct ifnet        *ifp = NULL;
  131     u_short             net;
  132 
  133 #if 0
  134     /* Check for net zero, node zero ("myself") */
  135     if (satosat(&ro->ro_dst)->sat_addr.s_net == ATADDR_ANYNET
  136         && satosat(&ro->ro_dst)->sat_addr.s_node == ATADDR_ANYNODE) {
  137             /* Find the loopback interface */
  138     }
  139 #endif
  140 
  141     /*
  142      * if we have a route, find the ifa that refers to this route.
  143      * I.e The ifa used to get to the gateway.
  144      */
  145     if ((ro->ro_rt == NULL)
  146     || (ro->ro_rt->rt_ifa == NULL)
  147     || ((ifp = ro->ro_rt->rt_ifa->ifa_ifp) == NULL)) {
  148         rtalloc(ro);
  149     }
  150     if ((ro->ro_rt != NULL)
  151     && (ro->ro_rt->rt_ifa)
  152     && (ifp = ro->ro_rt->rt_ifa->ifa_ifp)) {
  153         net = ntohs(satosat(ro->ro_rt->rt_gateway)->sat_addr.s_net);
  154         for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
  155             if (((net == 0) || (aa->aa_ifp == ifp)) &&
  156                     net >= ntohs(aa->aa_firstnet) &&
  157                     net <= ntohs(aa->aa_lastnet)) {
  158                 break;
  159             }
  160         }
  161     } else {
  162         m_freem(m);
  163 #ifdef NETATALK_DEBUG
  164         if (ro->ro_rt == NULL)
  165             printf ("ddp_route: no ro_rt.\n");
  166         else if (ro->ro_rt->rt_ifa == NULL)
  167             printf ("ddp_route: no ro_rt->rt_ifa\n");
  168         else
  169             printf ("ddp_route: no ro_rt->rt_ifa->ifa_ifp\n");
  170 #endif
  171         return (ENETUNREACH);
  172     }
  173 
  174     if (aa == NULL) {
  175 #ifdef NETATALK_DEBUG
  176         printf("ddp_route: no atalk address found for %s\n", 
  177             ifp->if_xname);
  178 #endif
  179         m_freem(m);
  180         return (ENETUNREACH);
  181     }
  182 
  183     /*
  184      * if the destination address is on a directly attached node use that,
  185      * else use the official gateway.
  186      */
  187     if (ntohs(satosat(&ro->ro_dst)->sat_addr.s_net) >=
  188             ntohs(aa->aa_firstnet) &&
  189             ntohs(satosat(&ro->ro_dst)->sat_addr.s_net) <=
  190             ntohs(aa->aa_lastnet)) {
  191         gate = *satosat(&ro->ro_dst);
  192     } else {
  193         gate = *satosat(ro->ro_rt->rt_gateway);
  194     }
  195 
  196     /*
  197      * There are several places in the kernel where data is added to
  198      * an mbuf without ensuring that the mbuf pointer is aligned.
  199      * This is bad for transition routing, since phase 1 and phase 2
  200      * packets end up poorly aligned due to the three byte elap header.
  201      */
  202     if (!(aa->aa_flags & AFA_PHASE2)) {
  203         MGET(m0, M_DONTWAIT, MT_HEADER);
  204         if (m0 == NULL) {
  205             m_freem(m);
  206             printf("ddp_route: no buffers\n");
  207             return (ENOBUFS);
  208         }
  209 #ifdef MAC
  210         mac_create_mbuf_from_mbuf(m, m0);
  211 #endif
  212         m0->m_next = m;
  213         /* XXX perhaps we ought to align the header? */
  214         m0->m_len = SZ_ELAPHDR;
  215         m = m0;
  216 
  217         elh = mtod(m, struct elaphdr *);
  218         elh->el_snode = satosat(&aa->aa_addr)->sat_addr.s_node;
  219         elh->el_type = ELAP_DDPEXTEND;
  220         elh->el_dnode = gate.sat_addr.s_node;
  221     }
  222     ro->ro_rt->rt_use++;
  223 
  224 #ifdef NETATALK_DEBUG
  225     printf ("ddp_route: from %d.%d to %d.%d, via %d.%d (%s)\n",
  226         ntohs(satosat(&aa->aa_addr)->sat_addr.s_net),
  227         satosat(&aa->aa_addr)->sat_addr.s_node,
  228         ntohs(satosat(&ro->ro_dst)->sat_addr.s_net),
  229         satosat(&ro->ro_dst)->sat_addr.s_node,
  230         ntohs(gate.sat_addr.s_net),
  231         gate.sat_addr.s_node,
  232         ifp->if_xname);
  233 #endif
  234 
  235     /* short-circuit the output if we're sending this to ourself */
  236     if ((satosat(&aa->aa_addr)->sat_addr.s_net  == satosat(&ro->ro_dst)->sat_addr.s_net) &&
  237         (satosat(&aa->aa_addr)->sat_addr.s_node == satosat(&ro->ro_dst)->sat_addr.s_node))
  238     {
  239         return (if_simloop(ifp, m, gate.sat_family, 0));
  240     }
  241 
  242     return ((*ifp->if_output)(ifp,
  243         m, (struct sockaddr *)&gate, NULL)); /* XXX */
  244 }

Cache object: 18ccf305395a8a5d8019a64105d94888


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.