ddp_output.c revision 165974
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: head/sys/netatalk/ddp_output.c 165974 2007-01-12 15:07:51Z rwatson $ */ 2560889Sarchie 26101937Srwatson#include "opt_mac.h" 27101937Srwatson 2815885Sjulian#include <sys/param.h> 2915885Sjulian#include <sys/systm.h> 3015885Sjulian#include <sys/mbuf.h> 3115885Sjulian#include <sys/socket.h> 3223396Sjulian#include <sys/socketvar.h> 3315885Sjulian 3415885Sjulian#include <net/if.h> 3515885Sjulian#include <net/route.h> 3615885Sjulian 3715885Sjulian#undef s_net 3815885Sjulian 3918207Sbde#include <netatalk/at.h> 4018207Sbde#include <netatalk/at_var.h> 4118207Sbde#include <netatalk/ddp.h> 4218207Sbde#include <netatalk/ddp_var.h> 4315885Sjulian#include <netatalk/at_extern.h> 4415885Sjulian 45163606Srwatson#include <security/mac/mac_framework.h> 46163606Srwatson 4715885Sjulianint ddp_cksum = 1; 4815885Sjulian 4915885Sjulianint 50127288Srwatsonddp_output(struct mbuf *m, struct socket *so) 5115885Sjulian{ 52165974Srwatson struct ddpehdr *deh; 53165974Srwatson struct ddpcb *ddp = sotoddpcb(so); 5415885Sjulian 55101937Srwatson#ifdef MAC 56165974Srwatson SOCK_LOCK(so); 57165974Srwatson mac_create_mbuf_from_socket(so, m); 58165974Srwatson SOCK_UNLOCK(so); 59101937Srwatson#endif 60101937Srwatson 61165974Srwatson M_PREPEND(m, sizeof(struct ddpehdr), M_DONTWAIT); 62165974Srwatson if (m == NULL) 63127288Srwatson return (ENOBUFS); 6415885Sjulian 65165974Srwatson deh = mtod(m, struct ddpehdr *); 66165974Srwatson deh->deh_pad = 0; 67165974Srwatson deh->deh_hops = 0; 6815885Sjulian 69165974Srwatson deh->deh_len = m->m_pkthdr.len; 7015885Sjulian 71165974Srwatson deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net; 72165974Srwatson deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node; 73165974Srwatson deh->deh_dport = ddp->ddp_fsat.sat_port; 74165974Srwatson deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net; 75165974Srwatson deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node; 76165974Srwatson deh->deh_sport = ddp->ddp_lsat.sat_port; 7715885Sjulian 78165974Srwatson /* 79165974Srwatson * The checksum calculation is done after all of the other bytes have 80165974Srwatson * been filled in. 81165974Srwatson */ 82165974Srwatson if (ddp_cksum) 83165974Srwatson deh->deh_sum = at_cksum(m, sizeof(int)); 84165974Srwatson else 85165974Srwatson deh->deh_sum = 0; 86165974Srwatson deh->deh_bytes = htonl(deh->deh_bytes); 8715885Sjulian 8838114Sjulian#ifdef NETATALK_DEBUG 89165974Srwatson printf ("ddp_output: from %d.%d:%d to %d.%d:%d\n", 9038114Sjulian ntohs(deh->deh_snet), deh->deh_snode, deh->deh_sport, 9138114Sjulian ntohs(deh->deh_dnet), deh->deh_dnode, deh->deh_dport); 9238114Sjulian#endif 93165974Srwatson return (ddp_route(m, &ddp->ddp_route)); 9415885Sjulian} 9515885Sjulian 9615885Sjulianu_short 97127288Srwatsonat_cksum(struct mbuf *m, int skip) 9815885Sjulian{ 99165974Srwatson u_char *data, *end; 100165974Srwatson u_long cksum = 0; 10115885Sjulian 102165974Srwatson for (; m; m = m->m_next) { 103165974Srwatson for (data = mtod(m, u_char *), end = data + m->m_len; 104165974Srwatson data < end; data++) { 105165974Srwatson if (skip) { 106165974Srwatson skip--; 107165974Srwatson continue; 108165974Srwatson } 109165974Srwatson cksum = (cksum + *data) << 1; 110165974Srwatson if (cksum & 0x00010000) 111165974Srwatson cksum++; 112165974Srwatson cksum &= 0x0000ffff; 113165974Srwatson } 11415885Sjulian } 11515885Sjulian 116165974Srwatson if (cksum == 0) 117165974Srwatson cksum = 0x0000ffff; 118165974Srwatson return ((u_short)cksum); 11915885Sjulian} 12015885Sjulian 12115885Sjulianint 122127288Srwatsonddp_route(struct mbuf *m, struct route *ro) 12315885Sjulian{ 124165974Srwatson struct sockaddr_at gate; 125165974Srwatson struct elaphdr *elh; 126165974Srwatson struct mbuf *m0; 127165974Srwatson struct at_ifaddr *aa = NULL; 128165974Srwatson struct ifnet *ifp = NULL; 129165974Srwatson u_short net; 13015885Sjulian 13136908Sjulian#if 0 132165974Srwatson /* Check for net zero, node zero ("myself") */ 133165974Srwatson if (satosat(&ro->ro_dst)->sat_addr.s_net == ATADDR_ANYNET 134165974Srwatson && satosat(&ro->ro_dst)->sat_addr.s_node == ATADDR_ANYNODE) { 135165974Srwatson /* Find the loopback interface */ 136165974Srwatson } 13736908Sjulian#endif 13836908Sjulian 139165974Srwatson /* 140165974Srwatson * If we have a route, find the ifa that refers to this route. I.e 141165974Srwatson * the ifa used to get to the gateway. 142165974Srwatson */ 143165974Srwatson if ((ro->ro_rt == NULL) || (ro->ro_rt->rt_ifa == NULL) || 144165974Srwatson ((ifp = ro->ro_rt->rt_ifa->ifa_ifp) == NULL)) 145165974Srwatson rtalloc(ro); 146165974Srwatson if ((ro->ro_rt != NULL) && (ro->ro_rt->rt_ifa) && 147165974Srwatson (ifp = ro->ro_rt->rt_ifa->ifa_ifp)) { 148165974Srwatson net = ntohs(satosat(ro->ro_rt->rt_gateway)->sat_addr.s_net); 149165974Srwatson for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { 150165974Srwatson if (((net == 0) || (aa->aa_ifp == ifp)) && 151165974Srwatson net >= ntohs(aa->aa_firstnet) && 152165974Srwatson net <= ntohs(aa->aa_lastnet)) 153165974Srwatson break; 154165974Srwatson } 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. 194165974Srwatson */ 195165974Srwatson if (!(aa->aa_flags & AFA_PHASE2)) { 196165974Srwatson MGET(m0, M_DONTWAIT, MT_DATA); 197165974Srwatson if (m0 == NULL) { 198165974Srwatson m_freem(m); 199165974Srwatson printf("ddp_route: no buffers\n"); 200165974Srwatson return (ENOBUFS); 201165974Srwatson } 202101937Srwatson#ifdef MAC 203165974Srwatson mac_copy_mbuf(m, m0); 204101937Srwatson#endif 205165974Srwatson m0->m_next = m; 206165974Srwatson /* XXX perhaps we ought to align the header? */ 207165974Srwatson m0->m_len = SZ_ELAPHDR; 208165974Srwatson m = m0; 20915885Sjulian 210165974Srwatson elh = mtod(m, struct elaphdr *); 211165974Srwatson elh->el_snode = satosat(&aa->aa_addr)->sat_addr.s_node; 212165974Srwatson elh->el_type = ELAP_DDPEXTEND; 213165974Srwatson elh->el_dnode = gate.sat_addr.s_node; 214165974Srwatson } 215165974Srwatson ro->ro_rt->rt_use++; 21615885Sjulian 21738114Sjulian#ifdef NETATALK_DEBUG 218165974Srwatson printf ("ddp_route: from %d.%d to %d.%d, via %d.%d (%s)\n", 219165974Srwatson ntohs(satosat(&aa->aa_addr)->sat_addr.s_net), 220165974Srwatson satosat(&aa->aa_addr)->sat_addr.s_node, 221165974Srwatson ntohs(satosat(&ro->ro_dst)->sat_addr.s_net), 222165974Srwatson satosat(&ro->ro_dst)->sat_addr.s_node, 223165974Srwatson ntohs(gate.sat_addr.s_net), gate.sat_addr.s_node, ifp->if_xname); 22438114Sjulian#endif 22538114Sjulian 226165974Srwatson /* Short-circuit the output if we're sending this to ourself. */ 227165974Srwatson if ((satosat(&aa->aa_addr)->sat_addr.s_net == 228165974Srwatson satosat(&ro->ro_dst)->sat_addr.s_net) && 229165974Srwatson (satosat(&aa->aa_addr)->sat_addr.s_node == 230165974Srwatson satosat(&ro->ro_dst)->sat_addr.s_node)) 231165974Srwatson return (if_simloop(ifp, m, gate.sat_family, 0)); 23238114Sjulian 233165974Srwatson /* XXX */ 234165974Srwatson return ((*ifp->if_output)(ifp, m, (struct sockaddr *)&gate, NULL)); 23515885Sjulian} 236