1139827Simp/*- 2165974Srwatson * Copyright (c) 1990, 1991 Regents of The University of Michigan. 315885Sjulian * All Rights Reserved. 415885Sjulian * 515885Sjulian * Permission to use, copy, modify, and distribute this software and 615885Sjulian * its documentation for any purpose and without fee is hereby granted, 715885Sjulian * provided that the above copyright notice appears in all copies and 815885Sjulian * that both that copyright notice and this permission notice appear 915885Sjulian * in supporting documentation, and that the name of The University 1015885Sjulian * of Michigan not be used in advertising or publicity pertaining to 1115885Sjulian * distribution of the software without specific, written prior 1215885Sjulian * permission. This software is supplied as is without expressed or 1315885Sjulian * implied warranties of any kind. 1415885Sjulian * 1515885Sjulian * Research Systems Unix Group 1615885Sjulian * The University of Michigan 1715885Sjulian * c/o Mike Clark 1815885Sjulian * 535 W. William Street 1915885Sjulian * Ann Arbor, Michigan 2015885Sjulian * +1-313-763-0525 2115885Sjulian * netatalk@itd.umich.edu 2215885Sjulian */ 2315885Sjulian 2460889Sarchie/* $FreeBSD$ */ 2560889Sarchie 2615885Sjulian#include <sys/param.h> 2715885Sjulian#include <sys/systm.h> 2815885Sjulian#include <sys/mbuf.h> 2915885Sjulian#include <sys/socket.h> 3023396Sjulian#include <sys/socketvar.h> 3115885Sjulian 3215885Sjulian#include <net/if.h> 3315885Sjulian#include <net/route.h> 3415885Sjulian 3515885Sjulian#undef s_net 3615885Sjulian 3718207Sbde#include <netatalk/at.h> 3818207Sbde#include <netatalk/at_var.h> 3918207Sbde#include <netatalk/ddp.h> 4018207Sbde#include <netatalk/ddp_var.h> 4115885Sjulian#include <netatalk/at_extern.h> 4215885Sjulian 43163606Srwatson#include <security/mac/mac_framework.h> 44163606Srwatson 4515885Sjulianint ddp_cksum = 1; 4615885Sjulian 4715885Sjulianint 48127288Srwatsonddp_output(struct mbuf *m, struct socket *so) 4915885Sjulian{ 50165974Srwatson struct ddpehdr *deh; 51165974Srwatson struct ddpcb *ddp = sotoddpcb(so); 5215885Sjulian 53101937Srwatson#ifdef MAC 54172930Srwatson mac_socket_create_mbuf(so, m); 55101937Srwatson#endif 56101937Srwatson 57243882Sglebius M_PREPEND(m, sizeof(struct ddpehdr), M_NOWAIT); 58165974Srwatson if (m == NULL) 59127288Srwatson return (ENOBUFS); 6015885Sjulian 61165974Srwatson deh = mtod(m, struct ddpehdr *); 62165974Srwatson deh->deh_pad = 0; 63165974Srwatson deh->deh_hops = 0; 6415885Sjulian 65165974Srwatson deh->deh_len = m->m_pkthdr.len; 6615885Sjulian 67165974Srwatson deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net; 68165974Srwatson deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node; 69165974Srwatson deh->deh_dport = ddp->ddp_fsat.sat_port; 70165974Srwatson deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net; 71165974Srwatson deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node; 72165974Srwatson deh->deh_sport = ddp->ddp_lsat.sat_port; 7315885Sjulian 74165974Srwatson /* 75165974Srwatson * The checksum calculation is done after all of the other bytes have 76165974Srwatson * been filled in. 77165974Srwatson */ 78165974Srwatson if (ddp_cksum) 79165974Srwatson deh->deh_sum = at_cksum(m, sizeof(int)); 80165974Srwatson else 81165974Srwatson deh->deh_sum = 0; 82165974Srwatson deh->deh_bytes = htonl(deh->deh_bytes); 8315885Sjulian 8438114Sjulian#ifdef NETATALK_DEBUG 85165974Srwatson printf ("ddp_output: from %d.%d:%d to %d.%d:%d\n", 8638114Sjulian ntohs(deh->deh_snet), deh->deh_snode, deh->deh_sport, 8738114Sjulian ntohs(deh->deh_dnet), deh->deh_dnode, deh->deh_dport); 8838114Sjulian#endif 89165974Srwatson return (ddp_route(m, &ddp->ddp_route)); 9015885Sjulian} 9115885Sjulian 9215885Sjulianu_short 93127288Srwatsonat_cksum(struct mbuf *m, int skip) 9415885Sjulian{ 95165974Srwatson u_char *data, *end; 96165974Srwatson u_long cksum = 0; 9715885Sjulian 98165974Srwatson for (; m; m = m->m_next) { 99165974Srwatson for (data = mtod(m, u_char *), end = data + m->m_len; 100165974Srwatson data < end; data++) { 101165974Srwatson if (skip) { 102165974Srwatson skip--; 103165974Srwatson continue; 104165974Srwatson } 105165974Srwatson cksum = (cksum + *data) << 1; 106165974Srwatson if (cksum & 0x00010000) 107165974Srwatson cksum++; 108165974Srwatson cksum &= 0x0000ffff; 109165974Srwatson } 11015885Sjulian } 11115885Sjulian 112165974Srwatson if (cksum == 0) 113165974Srwatson cksum = 0x0000ffff; 114165974Srwatson return ((u_short)cksum); 11515885Sjulian} 11615885Sjulian 11715885Sjulianint 118127288Srwatsonddp_route(struct mbuf *m, struct route *ro) 11915885Sjulian{ 120165974Srwatson struct sockaddr_at gate; 121165974Srwatson struct elaphdr *elh; 122165974Srwatson struct mbuf *m0; 123165974Srwatson struct at_ifaddr *aa = NULL; 124165974Srwatson struct ifnet *ifp = NULL; 125165974Srwatson u_short net; 12615885Sjulian 12736908Sjulian#if 0 128165974Srwatson /* Check for net zero, node zero ("myself") */ 129165974Srwatson if (satosat(&ro->ro_dst)->sat_addr.s_net == ATADDR_ANYNET 130165974Srwatson && satosat(&ro->ro_dst)->sat_addr.s_node == ATADDR_ANYNODE) { 131165974Srwatson /* Find the loopback interface */ 132165974Srwatson } 13336908Sjulian#endif 13436908Sjulian 135165974Srwatson /* 136165974Srwatson * If we have a route, find the ifa that refers to this route. I.e 137165974Srwatson * the ifa used to get to the gateway. 138165974Srwatson */ 139165974Srwatson if ((ro->ro_rt == NULL) || (ro->ro_rt->rt_ifa == NULL) || 140165974Srwatson ((ifp = ro->ro_rt->rt_ifa->ifa_ifp) == NULL)) 141165974Srwatson rtalloc(ro); 142165974Srwatson if ((ro->ro_rt != NULL) && (ro->ro_rt->rt_ifa) && 143165974Srwatson (ifp = ro->ro_rt->rt_ifa->ifa_ifp)) { 144165974Srwatson net = ntohs(satosat(ro->ro_rt->rt_gateway)->sat_addr.s_net); 145194619Srwatson AT_IFADDR_RLOCK(); 146194913Srwatson TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) { 147165974Srwatson if (((net == 0) || (aa->aa_ifp == ifp)) && 148165974Srwatson net >= ntohs(aa->aa_firstnet) && 149165974Srwatson net <= ntohs(aa->aa_lastnet)) 150165974Srwatson break; 151165974Srwatson } 152194619Srwatson if (aa != NULL) 153194619Srwatson ifa_ref(&aa->aa_ifa); 154194619Srwatson AT_IFADDR_RUNLOCK(); 155165974Srwatson } else { 156165974Srwatson m_freem(m); 15738114Sjulian#ifdef NETATALK_DEBUG 158165974Srwatson if (ro->ro_rt == NULL) 159165974Srwatson printf ("ddp_route: no ro_rt.\n"); 160165974Srwatson else if (ro->ro_rt->rt_ifa == NULL) 161165974Srwatson printf ("ddp_route: no ro_rt->rt_ifa\n"); 162165974Srwatson else 163165974Srwatson printf ("ddp_route: no ro_rt->rt_ifa->ifa_ifp\n"); 16438114Sjulian#endif 165165974Srwatson return (ENETUNREACH); 166165974Srwatson } 16728845Sjulian 168165974Srwatson if (aa == NULL) { 16938114Sjulian#ifdef NETATALK_DEBUG 170165974Srwatson printf("ddp_route: no atalk address found for %s\n", 171165974Srwatson ifp->if_xname); 17238114Sjulian#endif 173165974Srwatson m_freem(m); 174165974Srwatson return (ENETUNREACH); 175165974Srwatson } 17615885Sjulian 177165974Srwatson /* 178165974Srwatson * If the destination address is on a directly attached node use 179165974Srwatson * that, else use the official gateway. 180165974Srwatson */ 181165974Srwatson if (ntohs(satosat(&ro->ro_dst)->sat_addr.s_net) >= 182127288Srwatson ntohs(aa->aa_firstnet) && 183127288Srwatson ntohs(satosat(&ro->ro_dst)->sat_addr.s_net) <= 184165974Srwatson ntohs(aa->aa_lastnet)) 185165974Srwatson gate = *satosat(&ro->ro_dst); 186165974Srwatson else 187165974Srwatson gate = *satosat(ro->ro_rt->rt_gateway); 18837521Sjulian 189165974Srwatson /* 190165974Srwatson * There are several places in the kernel where data is added to an 191165974Srwatson * mbuf without ensuring that the mbuf pointer is aligned. This is 192165974Srwatson * bad for transition routing, since phase 1 and phase 2 packets end 193165974Srwatson * up poorly aligned due to the three byte elap header. 194173784Srwatson * 195173784Srwatson * XXXRW: kern/4184 suggests that an m_pullup() of (m) should take 196173784Srwatson * place here to address possible alignment issues. 197173784Srwatson * 198173784Srwatson * XXXRW: This appears not to handle M_PKTHDR properly, as it doesn't 199173784Srwatson * move the existing header from the old packet to the new one. 200173784Srwatson * Posibly should call M_MOVE_PKTHDR()? This would also allow 201173784Srwatson * removing mac_mbuf_copy(). 202165974Srwatson */ 203165974Srwatson if (!(aa->aa_flags & AFA_PHASE2)) { 204243882Sglebius MGET(m0, M_NOWAIT, MT_DATA); 205165974Srwatson if (m0 == NULL) { 206194619Srwatson ifa_free(&aa->aa_ifa); 207165974Srwatson m_freem(m); 208165974Srwatson printf("ddp_route: no buffers\n"); 209165974Srwatson return (ENOBUFS); 210165974Srwatson } 211101937Srwatson#ifdef MAC 212172930Srwatson mac_mbuf_copy(m, m0); 213101937Srwatson#endif 214165974Srwatson m0->m_next = m; 215165974Srwatson /* XXX perhaps we ought to align the header? */ 216165974Srwatson m0->m_len = SZ_ELAPHDR; 217165974Srwatson m = m0; 21815885Sjulian 219165974Srwatson elh = mtod(m, struct elaphdr *); 220165974Srwatson elh->el_snode = satosat(&aa->aa_addr)->sat_addr.s_node; 221165974Srwatson elh->el_type = ELAP_DDPEXTEND; 222165974Srwatson elh->el_dnode = gate.sat_addr.s_node; 223165974Srwatson } 224263478Sglebius counter_u64_add(ro->ro_rt->rt_pksent, 1); 22515885Sjulian 22638114Sjulian#ifdef NETATALK_DEBUG 227165974Srwatson printf ("ddp_route: from %d.%d to %d.%d, via %d.%d (%s)\n", 228165974Srwatson ntohs(satosat(&aa->aa_addr)->sat_addr.s_net), 229165974Srwatson satosat(&aa->aa_addr)->sat_addr.s_node, 230165974Srwatson ntohs(satosat(&ro->ro_dst)->sat_addr.s_net), 231165974Srwatson satosat(&ro->ro_dst)->sat_addr.s_node, 232165974Srwatson ntohs(gate.sat_addr.s_net), gate.sat_addr.s_node, ifp->if_xname); 23338114Sjulian#endif 23438114Sjulian 235165974Srwatson /* Short-circuit the output if we're sending this to ourself. */ 236165974Srwatson if ((satosat(&aa->aa_addr)->sat_addr.s_net == 237165974Srwatson satosat(&ro->ro_dst)->sat_addr.s_net) && 238165974Srwatson (satosat(&aa->aa_addr)->sat_addr.s_node == 239194619Srwatson satosat(&ro->ro_dst)->sat_addr.s_node)) { 240194619Srwatson ifa_free(&aa->aa_ifa); 241165974Srwatson return (if_simloop(ifp, m, gate.sat_family, 0)); 242194619Srwatson } 243194619Srwatson ifa_free(&aa->aa_ifa); 24438114Sjulian 245165974Srwatson /* XXX */ 246165974Srwatson return ((*ifp->if_output)(ifp, m, (struct sockaddr *)&gate, NULL)); 24715885Sjulian} 248