123211Smckusick /* 223211Smckusick * Copyright (c) 1982 Regents of the University of California. 323211Smckusick * All rights reserved. The Berkeley software License Agreement 423211Smckusick * specifies the terms and conditions for redistribution. 523211Smckusick * 6*24731Ssklower * @(#)ns_output.c 6.6 (Berkeley) 09/13/85 723211Smckusick */ 821488Ssklower 921488Ssklower #include "param.h" 1021488Ssklower #include "mbuf.h" 1121488Ssklower #include "errno.h" 1221488Ssklower #include "socket.h" 1321488Ssklower #include "socketvar.h" 1421488Ssklower 1521488Ssklower #include "../net/if.h" 1621488Ssklower #include "../net/route.h" 1721488Ssklower 1821488Ssklower #include "ns.h" 1921488Ssklower #include "ns_if.h" 2021488Ssklower #include "idp.h" 2121488Ssklower #include "idp_var.h" 2221488Ssklower 2321488Ssklower #ifdef vax 2421488Ssklower #include "../vax/mtpr.h" 2521488Ssklower #endif 2621745Ssklower int ns_hold_output = 0; 2721745Ssklower int ns_copy_output = 0; 2821745Ssklower int ns_output_cnt = 0; 2921488Ssklower struct mbuf *ns_lastout; 3021488Ssklower 3121488Ssklower ns_output(m0, ro, flags) 3221488Ssklower struct mbuf *m0; 3321488Ssklower struct route *ro; 3421488Ssklower int flags; 3521488Ssklower { 3621488Ssklower register struct idp *idp = mtod(m0, struct idp *); 3721488Ssklower register struct ifnet *ifp; 3824226Ssklower int error = 0; 3921488Ssklower struct route idproute; 4021488Ssklower struct sockaddr_ns *dst; 4121488Ssklower extern int idpcksum; 4221488Ssklower 4323501Ssklower if (ns_hold_output) { 4423501Ssklower if (ns_lastout) { 4521488Ssklower m_free(ns_lastout); 4621488Ssklower } 4724226Ssklower ns_lastout = m_copy(m0, 0, (int)M_COPYALL); 4821488Ssklower } 4923501Ssklower if (ns_copy_output) { 5021488Ssklower ns_watch_output(m0); 5121488Ssklower } 5221488Ssklower 5321488Ssklower /* 5421488Ssklower * Route packet. 5521488Ssklower */ 5621488Ssklower if (ro == 0) { 5721488Ssklower ro = &idproute; 5821488Ssklower bzero((caddr_t)ro, sizeof (*ro)); 5921488Ssklower } 6021488Ssklower dst = (struct sockaddr_ns *)&ro->ro_dst; 6121488Ssklower if (ro->ro_rt == 0) { 6221488Ssklower dst->sns_family = AF_NS; 6321488Ssklower dst->sns_addr = idp->idp_dna; 6423501Ssklower dst->sns_addr.x_port = 0; 6521488Ssklower /* 6621488Ssklower * If routing to interface only, 6721488Ssklower * short circuit routing lookup. 6821488Ssklower */ 6921488Ssklower if (flags & NS_ROUTETOIF) { 7021488Ssklower struct ns_ifaddr *ia; 71*24731Ssklower struct ifaddr *ifa_ifwithdstaddr(); 72*24731Ssklower 7321488Ssklower ia = ns_iaonnetof(idp->idp_dna.x_net); 7421488Ssklower if (ia == 0) { 7521488Ssklower error = ENETUNREACH; 7621488Ssklower goto bad; 7721488Ssklower } 7821488Ssklower ifp = ia->ia_ifp; 79*24731Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 80*24731Ssklower ia = (struct ns_ifaddr *) 81*24731Ssklower ifa_ifwithdstaddr(&ro->ro_dst); 82*24731Ssklower if (ia == 0) { 83*24731Ssklower error = ENETUNREACH; 84*24731Ssklower goto bad; 85*24731Ssklower } 86*24731Ssklower ifp = ia->ia_ifp; 87*24731Ssklower } 8821488Ssklower goto gotif; 8921488Ssklower } 9021488Ssklower rtalloc(ro); 9121488Ssklower } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 9221488Ssklower /* 9321488Ssklower * The old route has gone away; try for a new one. 9421488Ssklower */ 9521488Ssklower rtfree(ro->ro_rt); 9621488Ssklower rtalloc(ro); 9721488Ssklower } 9821488Ssklower if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { 9921488Ssklower error = ENETUNREACH; 10021488Ssklower goto bad; 10121488Ssklower } 10221488Ssklower ro->ro_rt->rt_use++; 10321488Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 10421488Ssklower dst = (struct sockaddr_ns *)&ro->ro_rt->rt_gateway; 10521488Ssklower gotif: 10621488Ssklower 10721488Ssklower /* 10821488Ssklower * Look for multicast addresses and 10921488Ssklower * and verify user is allowed to send 11021488Ssklower * such a packet. 11121488Ssklower */ 11221488Ssklower if (dst->sns_addr.x_host.c_host[0]&1) { 11321488Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) { 11421488Ssklower error = EADDRNOTAVAIL; 11521488Ssklower goto bad; 11621488Ssklower } 11721488Ssklower if ((flags & NS_ALLOWBROADCAST) == 0) { 11821488Ssklower error = EACCES; 11921488Ssklower goto bad; 12021488Ssklower } 12121488Ssklower } 12221488Ssklower 12321488Ssklower if (htons(idp->idp_len) <= ifp->if_mtu) { 12421488Ssklower ns_output_cnt++; 12521488Ssklower error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst); 12621488Ssklower goto done; 12721488Ssklower } else error = EMSGSIZE; 12821488Ssklower 12921488Ssklower 13021488Ssklower bad: 13121488Ssklower m_freem(m0); 13221488Ssklower done: 13321488Ssklower if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) 13421488Ssklower RTFREE(ro->ro_rt); 13521488Ssklower return (error); 13621488Ssklower } 137