123211Smckusick /* 2*63231Sbostic * Copyright (c) 1984, 1985, 1986, 1987, 1993 3*63231Sbostic * The Regents of the University of California. All rights reserved. 423211Smckusick * 544506Sbostic * %sccs.include.redist.c% 633371Ssklower * 7*63231Sbostic * @(#)ns_output.c 8.1 (Berkeley) 06/10/93 823211Smckusick */ 921488Ssklower 1056534Sbostic #include <sys/param.h> 1156534Sbostic #include <sys/malloc.h> 1256534Sbostic #include <sys/mbuf.h> 1356534Sbostic #include <sys/errno.h> 1456534Sbostic #include <sys/socket.h> 1556534Sbostic #include <sys/socketvar.h> 1621488Ssklower 1756534Sbostic #include <net/if.h> 1856534Sbostic #include <net/route.h> 1921488Ssklower 2056534Sbostic #include <netns/ns.h> 2156534Sbostic #include <netns/ns_if.h> 2256534Sbostic #include <netns/idp.h> 2356534Sbostic #include <netns/idp_var.h> 2421488Ssklower 2521488Ssklower #ifdef vax 2656534Sbostic #include <machine/mtpr.h> 2721488Ssklower #endif 2821745Ssklower int ns_hold_output = 0; 2921745Ssklower int ns_copy_output = 0; 3021745Ssklower int ns_output_cnt = 0; 3121488Ssklower struct mbuf *ns_lastout; 3221488Ssklower 3321488Ssklower ns_output(m0, ro, flags) 3421488Ssklower struct mbuf *m0; 3521488Ssklower struct route *ro; 3621488Ssklower int flags; 3721488Ssklower { 3821488Ssklower register struct idp *idp = mtod(m0, struct idp *); 3925043Ssklower register struct ifnet *ifp = 0; 4024226Ssklower int error = 0; 4121488Ssklower struct route idproute; 4221488Ssklower struct sockaddr_ns *dst; 4321488Ssklower extern int idpcksum; 4421488Ssklower 4523501Ssklower if (ns_hold_output) { 4623501Ssklower if (ns_lastout) { 4726389Skarels (void)m_free(ns_lastout); 4821488Ssklower } 4924226Ssklower ns_lastout = m_copy(m0, 0, (int)M_COPYALL); 5021488Ssklower } 5121488Ssklower /* 5221488Ssklower * Route packet. 5321488Ssklower */ 5421488Ssklower if (ro == 0) { 5521488Ssklower ro = &idproute; 5621488Ssklower bzero((caddr_t)ro, sizeof (*ro)); 5721488Ssklower } 5821488Ssklower dst = (struct sockaddr_ns *)&ro->ro_dst; 5921488Ssklower if (ro->ro_rt == 0) { 6021488Ssklower dst->sns_family = AF_NS; 6137473Ssklower dst->sns_len = sizeof (*dst); 6221488Ssklower dst->sns_addr = idp->idp_dna; 6323501Ssklower dst->sns_addr.x_port = 0; 6421488Ssklower /* 6521488Ssklower * If routing to interface only, 6621488Ssklower * short circuit routing lookup. 6721488Ssklower */ 6821488Ssklower if (flags & NS_ROUTETOIF) { 6925043Ssklower struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna); 7024731Ssklower 7121488Ssklower if (ia == 0) { 7221488Ssklower error = ENETUNREACH; 7321488Ssklower goto bad; 7421488Ssklower } 7521488Ssklower ifp = ia->ia_ifp; 7621488Ssklower goto gotif; 7721488Ssklower } 7821488Ssklower rtalloc(ro); 7921488Ssklower } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 8021488Ssklower /* 8121488Ssklower * The old route has gone away; try for a new one. 8221488Ssklower */ 8321488Ssklower rtfree(ro->ro_rt); 8425510Ssklower ro->ro_rt = NULL; 8521488Ssklower rtalloc(ro); 8621488Ssklower } 8721488Ssklower if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { 8821488Ssklower error = ENETUNREACH; 8921488Ssklower goto bad; 9021488Ssklower } 9121488Ssklower ro->ro_rt->rt_use++; 9221488Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 9337473Ssklower dst = (struct sockaddr_ns *)ro->ro_rt->rt_gateway; 9421488Ssklower gotif: 9521488Ssklower 9621488Ssklower /* 9721488Ssklower * Look for multicast addresses and 9821488Ssklower * and verify user is allowed to send 9921488Ssklower * such a packet. 10021488Ssklower */ 10121488Ssklower if (dst->sns_addr.x_host.c_host[0]&1) { 10221488Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) { 10321488Ssklower error = EADDRNOTAVAIL; 10421488Ssklower goto bad; 10521488Ssklower } 10621488Ssklower if ((flags & NS_ALLOWBROADCAST) == 0) { 10721488Ssklower error = EACCES; 10821488Ssklower goto bad; 10921488Ssklower } 11021488Ssklower } 11121488Ssklower 11221488Ssklower if (htons(idp->idp_len) <= ifp->if_mtu) { 11321488Ssklower ns_output_cnt++; 11425043Ssklower if (ns_copy_output) { 11525043Ssklower ns_watch_output(m0, ifp); 11625043Ssklower } 11740799Ssklower error = (*ifp->if_output)(ifp, m0, 11840799Ssklower (struct sockaddr *)dst, ro->ro_rt); 11921488Ssklower goto done; 12021488Ssklower } else error = EMSGSIZE; 12121488Ssklower 12221488Ssklower 12321488Ssklower bad: 12425043Ssklower if (ns_copy_output) { 12525043Ssklower ns_watch_output(m0, ifp); 12625043Ssklower } 12721488Ssklower m_freem(m0); 12821488Ssklower done: 12937473Ssklower if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) { 13021488Ssklower RTFREE(ro->ro_rt); 13137473Ssklower ro->ro_rt = 0; 13237473Ssklower } 13321488Ssklower return (error); 13421488Ssklower } 135