123211Smckusick /* 2*33371Ssklower * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 3*33371Ssklower * All rights reserved. 423211Smckusick * 5*33371Ssklower * Redistribution and use in source and binary forms are permitted 6*33371Ssklower * provided that this notice is preserved and that due credit is given 7*33371Ssklower * to the University of California at Berkeley. The name of the University 8*33371Ssklower * may not be used to endorse or promote products derived from this 9*33371Ssklower * software without specific prior written permission. This software 10*33371Ssklower * is provided ``as is'' without express or implied warranty. 11*33371Ssklower * 12*33371Ssklower * @(#)ns_output.c 7.2 (Berkeley) 01/20/88 1323211Smckusick */ 1421488Ssklower 1521488Ssklower #include "param.h" 1621488Ssklower #include "mbuf.h" 1721488Ssklower #include "errno.h" 1821488Ssklower #include "socket.h" 1921488Ssklower #include "socketvar.h" 2021488Ssklower 2121488Ssklower #include "../net/if.h" 2221488Ssklower #include "../net/route.h" 2321488Ssklower 2421488Ssklower #include "ns.h" 2521488Ssklower #include "ns_if.h" 2621488Ssklower #include "idp.h" 2721488Ssklower #include "idp_var.h" 2821488Ssklower 2921488Ssklower #ifdef vax 3021488Ssklower #include "../vax/mtpr.h" 3121488Ssklower #endif 3221745Ssklower int ns_hold_output = 0; 3321745Ssklower int ns_copy_output = 0; 3421745Ssklower int ns_output_cnt = 0; 3521488Ssklower struct mbuf *ns_lastout; 3621488Ssklower 3721488Ssklower ns_output(m0, ro, flags) 3821488Ssklower struct mbuf *m0; 3921488Ssklower struct route *ro; 4021488Ssklower int flags; 4121488Ssklower { 4221488Ssklower register struct idp *idp = mtod(m0, struct idp *); 4325043Ssklower register struct ifnet *ifp = 0; 4424226Ssklower int error = 0; 4521488Ssklower struct route idproute; 4621488Ssklower struct sockaddr_ns *dst; 4721488Ssklower extern int idpcksum; 4821488Ssklower 4923501Ssklower if (ns_hold_output) { 5023501Ssklower if (ns_lastout) { 5126389Skarels (void)m_free(ns_lastout); 5221488Ssklower } 5324226Ssklower ns_lastout = m_copy(m0, 0, (int)M_COPYALL); 5421488Ssklower } 5521488Ssklower /* 5621488Ssklower * Route packet. 5721488Ssklower */ 5821488Ssklower if (ro == 0) { 5921488Ssklower ro = &idproute; 6021488Ssklower bzero((caddr_t)ro, sizeof (*ro)); 6121488Ssklower } 6221488Ssklower dst = (struct sockaddr_ns *)&ro->ro_dst; 6321488Ssklower if (ro->ro_rt == 0) { 6421488Ssklower dst->sns_family = AF_NS; 6521488Ssklower dst->sns_addr = idp->idp_dna; 6623501Ssklower dst->sns_addr.x_port = 0; 6721488Ssklower /* 6821488Ssklower * If routing to interface only, 6921488Ssklower * short circuit routing lookup. 7021488Ssklower */ 7121488Ssklower if (flags & NS_ROUTETOIF) { 7225043Ssklower struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna); 7324731Ssklower 7421488Ssklower if (ia == 0) { 7521488Ssklower error = ENETUNREACH; 7621488Ssklower goto bad; 7721488Ssklower } 7821488Ssklower ifp = ia->ia_ifp; 7921488Ssklower goto gotif; 8021488Ssklower } 8121488Ssklower rtalloc(ro); 8221488Ssklower } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 8321488Ssklower /* 8421488Ssklower * The old route has gone away; try for a new one. 8521488Ssklower */ 8621488Ssklower rtfree(ro->ro_rt); 8725510Ssklower ro->ro_rt = NULL; 8821488Ssklower rtalloc(ro); 8921488Ssklower } 9021488Ssklower if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { 9121488Ssklower error = ENETUNREACH; 9221488Ssklower goto bad; 9321488Ssklower } 9421488Ssklower ro->ro_rt->rt_use++; 9521488Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 9621488Ssklower dst = (struct sockaddr_ns *)&ro->ro_rt->rt_gateway; 9721488Ssklower gotif: 9821488Ssklower 9921488Ssklower /* 10021488Ssklower * Look for multicast addresses and 10121488Ssklower * and verify user is allowed to send 10221488Ssklower * such a packet. 10321488Ssklower */ 10421488Ssklower if (dst->sns_addr.x_host.c_host[0]&1) { 10521488Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) { 10621488Ssklower error = EADDRNOTAVAIL; 10721488Ssklower goto bad; 10821488Ssklower } 10921488Ssklower if ((flags & NS_ALLOWBROADCAST) == 0) { 11021488Ssklower error = EACCES; 11121488Ssklower goto bad; 11221488Ssklower } 11321488Ssklower } 11421488Ssklower 11521488Ssklower if (htons(idp->idp_len) <= ifp->if_mtu) { 11621488Ssklower ns_output_cnt++; 11725043Ssklower if (ns_copy_output) { 11825043Ssklower ns_watch_output(m0, ifp); 11925043Ssklower } 12021488Ssklower error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst); 12121488Ssklower goto done; 12221488Ssklower } else error = EMSGSIZE; 12321488Ssklower 12421488Ssklower 12521488Ssklower bad: 12625043Ssklower if (ns_copy_output) { 12725043Ssklower ns_watch_output(m0, ifp); 12825043Ssklower } 12921488Ssklower m_freem(m0); 13021488Ssklower done: 13121488Ssklower if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) 13221488Ssklower RTFREE(ro->ro_rt); 13321488Ssklower return (error); 13421488Ssklower } 135