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 634856Sbostic * provided that the above copyright notice and this paragraph are 734856Sbostic * duplicated in all such forms and that any documentation, 834856Sbostic * advertising materials, and other materials related to such 934856Sbostic * distribution and use acknowledge that the software was developed 1034856Sbostic * by the University of California, Berkeley. The name of the 1134856Sbostic * University may not be used to endorse or promote products derived 1234856Sbostic * from this software without specific prior written permission. 1334856Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434856Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534856Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633371Ssklower * 17*37473Ssklower * @(#)ns_output.c 7.5 (Berkeley) 04/22/89 1823211Smckusick */ 1921488Ssklower 2021488Ssklower #include "param.h" 2135797Ssklower #include "malloc.h" 2221488Ssklower #include "mbuf.h" 2321488Ssklower #include "errno.h" 2421488Ssklower #include "socket.h" 2521488Ssklower #include "socketvar.h" 2621488Ssklower 2721488Ssklower #include "../net/if.h" 2821488Ssklower #include "../net/route.h" 2921488Ssklower 3021488Ssklower #include "ns.h" 3121488Ssklower #include "ns_if.h" 3221488Ssklower #include "idp.h" 3321488Ssklower #include "idp_var.h" 3421488Ssklower 3521488Ssklower #ifdef vax 3621488Ssklower #include "../vax/mtpr.h" 3721488Ssklower #endif 3821745Ssklower int ns_hold_output = 0; 3921745Ssklower int ns_copy_output = 0; 4021745Ssklower int ns_output_cnt = 0; 4121488Ssklower struct mbuf *ns_lastout; 4221488Ssklower 4321488Ssklower ns_output(m0, ro, flags) 4421488Ssklower struct mbuf *m0; 4521488Ssklower struct route *ro; 4621488Ssklower int flags; 4721488Ssklower { 4821488Ssklower register struct idp *idp = mtod(m0, struct idp *); 4925043Ssklower register struct ifnet *ifp = 0; 5024226Ssklower int error = 0; 5121488Ssklower struct route idproute; 5221488Ssklower struct sockaddr_ns *dst; 5321488Ssklower extern int idpcksum; 5421488Ssklower 5523501Ssklower if (ns_hold_output) { 5623501Ssklower if (ns_lastout) { 5726389Skarels (void)m_free(ns_lastout); 5821488Ssklower } 5924226Ssklower ns_lastout = m_copy(m0, 0, (int)M_COPYALL); 6021488Ssklower } 6121488Ssklower /* 6221488Ssklower * Route packet. 6321488Ssklower */ 6421488Ssklower if (ro == 0) { 6521488Ssklower ro = &idproute; 6621488Ssklower bzero((caddr_t)ro, sizeof (*ro)); 6721488Ssklower } 6821488Ssklower dst = (struct sockaddr_ns *)&ro->ro_dst; 6921488Ssklower if (ro->ro_rt == 0) { 7021488Ssklower dst->sns_family = AF_NS; 71*37473Ssklower dst->sns_len = sizeof (*dst); 7221488Ssklower dst->sns_addr = idp->idp_dna; 7323501Ssklower dst->sns_addr.x_port = 0; 7421488Ssklower /* 7521488Ssklower * If routing to interface only, 7621488Ssklower * short circuit routing lookup. 7721488Ssklower */ 7821488Ssklower if (flags & NS_ROUTETOIF) { 7925043Ssklower struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna); 8024731Ssklower 8121488Ssklower if (ia == 0) { 8221488Ssklower error = ENETUNREACH; 8321488Ssklower goto bad; 8421488Ssklower } 8521488Ssklower ifp = ia->ia_ifp; 8621488Ssklower goto gotif; 8721488Ssklower } 8821488Ssklower rtalloc(ro); 8921488Ssklower } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 9021488Ssklower /* 9121488Ssklower * The old route has gone away; try for a new one. 9221488Ssklower */ 9321488Ssklower rtfree(ro->ro_rt); 9425510Ssklower ro->ro_rt = NULL; 9521488Ssklower rtalloc(ro); 9621488Ssklower } 9721488Ssklower if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { 9821488Ssklower error = ENETUNREACH; 9921488Ssklower goto bad; 10021488Ssklower } 10121488Ssklower ro->ro_rt->rt_use++; 10221488Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 103*37473Ssklower dst = (struct sockaddr_ns *)ro->ro_rt->rt_gateway; 10421488Ssklower gotif: 10521488Ssklower 10621488Ssklower /* 10721488Ssklower * Look for multicast addresses and 10821488Ssklower * and verify user is allowed to send 10921488Ssklower * such a packet. 11021488Ssklower */ 11121488Ssklower if (dst->sns_addr.x_host.c_host[0]&1) { 11221488Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) { 11321488Ssklower error = EADDRNOTAVAIL; 11421488Ssklower goto bad; 11521488Ssklower } 11621488Ssklower if ((flags & NS_ALLOWBROADCAST) == 0) { 11721488Ssklower error = EACCES; 11821488Ssklower goto bad; 11921488Ssklower } 12021488Ssklower } 12121488Ssklower 12221488Ssklower if (htons(idp->idp_len) <= ifp->if_mtu) { 12321488Ssklower ns_output_cnt++; 12425043Ssklower if (ns_copy_output) { 12525043Ssklower ns_watch_output(m0, ifp); 12625043Ssklower } 12721488Ssklower error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst); 12821488Ssklower goto done; 12921488Ssklower } else error = EMSGSIZE; 13021488Ssklower 13121488Ssklower 13221488Ssklower bad: 13325043Ssklower if (ns_copy_output) { 13425043Ssklower ns_watch_output(m0, ifp); 13525043Ssklower } 13621488Ssklower m_freem(m0); 13721488Ssklower done: 138*37473Ssklower if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) { 13921488Ssklower RTFREE(ro->ro_rt); 140*37473Ssklower ro->ro_rt = 0; 141*37473Ssklower } 14221488Ssklower return (error); 14321488Ssklower } 144