123211Smckusick /* 233371Ssklower * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 333371Ssklower * All rights reserved. 423211Smckusick * 533371Ssklower * Redistribution and use in source and binary forms are permitted 6*34856Sbostic * provided that the above copyright notice and this paragraph are 7*34856Sbostic * duplicated in all such forms and that any documentation, 8*34856Sbostic * advertising materials, and other materials related to such 9*34856Sbostic * distribution and use acknowledge that the software was developed 10*34856Sbostic * by the University of California, Berkeley. The name of the 11*34856Sbostic * University may not be used to endorse or promote products derived 12*34856Sbostic * from this software without specific prior written permission. 13*34856Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34856Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34856Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633371Ssklower * 17*34856Sbostic * @(#)ns_output.c 7.3 (Berkeley) 06/29/88 1823211Smckusick */ 1921488Ssklower 2021488Ssklower #include "param.h" 2121488Ssklower #include "mbuf.h" 2221488Ssklower #include "errno.h" 2321488Ssklower #include "socket.h" 2421488Ssklower #include "socketvar.h" 2521488Ssklower 2621488Ssklower #include "../net/if.h" 2721488Ssklower #include "../net/route.h" 2821488Ssklower 2921488Ssklower #include "ns.h" 3021488Ssklower #include "ns_if.h" 3121488Ssklower #include "idp.h" 3221488Ssklower #include "idp_var.h" 3321488Ssklower 3421488Ssklower #ifdef vax 3521488Ssklower #include "../vax/mtpr.h" 3621488Ssklower #endif 3721745Ssklower int ns_hold_output = 0; 3821745Ssklower int ns_copy_output = 0; 3921745Ssklower int ns_output_cnt = 0; 4021488Ssklower struct mbuf *ns_lastout; 4121488Ssklower 4221488Ssklower ns_output(m0, ro, flags) 4321488Ssklower struct mbuf *m0; 4421488Ssklower struct route *ro; 4521488Ssklower int flags; 4621488Ssklower { 4721488Ssklower register struct idp *idp = mtod(m0, struct idp *); 4825043Ssklower register struct ifnet *ifp = 0; 4924226Ssklower int error = 0; 5021488Ssklower struct route idproute; 5121488Ssklower struct sockaddr_ns *dst; 5221488Ssklower extern int idpcksum; 5321488Ssklower 5423501Ssklower if (ns_hold_output) { 5523501Ssklower if (ns_lastout) { 5626389Skarels (void)m_free(ns_lastout); 5721488Ssklower } 5824226Ssklower ns_lastout = m_copy(m0, 0, (int)M_COPYALL); 5921488Ssklower } 6021488Ssklower /* 6121488Ssklower * Route packet. 6221488Ssklower */ 6321488Ssklower if (ro == 0) { 6421488Ssklower ro = &idproute; 6521488Ssklower bzero((caddr_t)ro, sizeof (*ro)); 6621488Ssklower } 6721488Ssklower dst = (struct sockaddr_ns *)&ro->ro_dst; 6821488Ssklower if (ro->ro_rt == 0) { 6921488Ssklower dst->sns_family = AF_NS; 7021488Ssklower dst->sns_addr = idp->idp_dna; 7123501Ssklower dst->sns_addr.x_port = 0; 7221488Ssklower /* 7321488Ssklower * If routing to interface only, 7421488Ssklower * short circuit routing lookup. 7521488Ssklower */ 7621488Ssklower if (flags & NS_ROUTETOIF) { 7725043Ssklower struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna); 7824731Ssklower 7921488Ssklower if (ia == 0) { 8021488Ssklower error = ENETUNREACH; 8121488Ssklower goto bad; 8221488Ssklower } 8321488Ssklower ifp = ia->ia_ifp; 8421488Ssklower goto gotif; 8521488Ssklower } 8621488Ssklower rtalloc(ro); 8721488Ssklower } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 8821488Ssklower /* 8921488Ssklower * The old route has gone away; try for a new one. 9021488Ssklower */ 9121488Ssklower rtfree(ro->ro_rt); 9225510Ssklower ro->ro_rt = NULL; 9321488Ssklower rtalloc(ro); 9421488Ssklower } 9521488Ssklower if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { 9621488Ssklower error = ENETUNREACH; 9721488Ssklower goto bad; 9821488Ssklower } 9921488Ssklower ro->ro_rt->rt_use++; 10021488Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 10121488Ssklower dst = (struct sockaddr_ns *)&ro->ro_rt->rt_gateway; 10221488Ssklower gotif: 10321488Ssklower 10421488Ssklower /* 10521488Ssklower * Look for multicast addresses and 10621488Ssklower * and verify user is allowed to send 10721488Ssklower * such a packet. 10821488Ssklower */ 10921488Ssklower if (dst->sns_addr.x_host.c_host[0]&1) { 11021488Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) { 11121488Ssklower error = EADDRNOTAVAIL; 11221488Ssklower goto bad; 11321488Ssklower } 11421488Ssklower if ((flags & NS_ALLOWBROADCAST) == 0) { 11521488Ssklower error = EACCES; 11621488Ssklower goto bad; 11721488Ssklower } 11821488Ssklower } 11921488Ssklower 12021488Ssklower if (htons(idp->idp_len) <= ifp->if_mtu) { 12121488Ssklower ns_output_cnt++; 12225043Ssklower if (ns_copy_output) { 12325043Ssklower ns_watch_output(m0, ifp); 12425043Ssklower } 12521488Ssklower error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst); 12621488Ssklower goto done; 12721488Ssklower } else error = EMSGSIZE; 12821488Ssklower 12921488Ssklower 13021488Ssklower bad: 13125043Ssklower if (ns_copy_output) { 13225043Ssklower ns_watch_output(m0, ifp); 13325043Ssklower } 13421488Ssklower m_freem(m0); 13521488Ssklower done: 13621488Ssklower if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) 13721488Ssklower RTFREE(ro->ro_rt); 13821488Ssklower return (error); 13921488Ssklower } 140