1*21488Ssklower /* ns_output.c 6.1 85/05/30 */ 2*21488Ssklower 3*21488Ssklower #include "param.h" 4*21488Ssklower #include "mbuf.h" 5*21488Ssklower #include "errno.h" 6*21488Ssklower #include "socket.h" 7*21488Ssklower #include "socketvar.h" 8*21488Ssklower 9*21488Ssklower #include "../net/if.h" 10*21488Ssklower #include "../net/route.h" 11*21488Ssklower 12*21488Ssklower #include "ns.h" 13*21488Ssklower #include "ns_if.h" 14*21488Ssklower #include "idp.h" 15*21488Ssklower #include "idp_var.h" 16*21488Ssklower 17*21488Ssklower #ifdef vax 18*21488Ssklower #include "../vax/mtpr.h" 19*21488Ssklower #endif 20*21488Ssklower int ns_hold_output = 1; 21*21488Ssklower int ns_copy_output = 1; 22*21488Ssklower struct mbuf *ns_lastout; 23*21488Ssklower 24*21488Ssklower int ns_output_cnt = 0; 25*21488Ssklower ns_output(m0, ro, flags) 26*21488Ssklower struct mbuf *m0; 27*21488Ssklower struct route *ro; 28*21488Ssklower int flags; 29*21488Ssklower { 30*21488Ssklower register struct idp *idp = mtod(m0, struct idp *); 31*21488Ssklower register struct ifnet *ifp; 32*21488Ssklower register struct mbuf *m; 33*21488Ssklower int len, rlen, off, error = 0; 34*21488Ssklower struct route idproute; 35*21488Ssklower struct sockaddr_ns *dst; 36*21488Ssklower extern int idpcksum; 37*21488Ssklower 38*21488Ssklower if(ns_hold_output) { 39*21488Ssklower if(ns_lastout) { 40*21488Ssklower m_free(ns_lastout); 41*21488Ssklower } 42*21488Ssklower ns_lastout = m_copy(m0, 0, M_COPYALL); 43*21488Ssklower } 44*21488Ssklower if(ns_copy_output) { 45*21488Ssklower ns_watch_output(m0); 46*21488Ssklower } 47*21488Ssklower 48*21488Ssklower /* 49*21488Ssklower * Route packet. 50*21488Ssklower */ 51*21488Ssklower if (ro == 0) { 52*21488Ssklower ro = &idproute; 53*21488Ssklower bzero((caddr_t)ro, sizeof (*ro)); 54*21488Ssklower } 55*21488Ssklower dst = (struct sockaddr_ns *)&ro->ro_dst; 56*21488Ssklower if (ro->ro_rt == 0) { 57*21488Ssklower dst->sns_family = AF_NS; 58*21488Ssklower dst->sns_addr = idp->idp_dna; 59*21488Ssklower /* 60*21488Ssklower * If routing to interface only, 61*21488Ssklower * short circuit routing lookup. 62*21488Ssklower */ 63*21488Ssklower if (flags & NS_ROUTETOIF) { 64*21488Ssklower struct ns_ifaddr *ia; 65*21488Ssklower ia = ns_iaonnetof(idp->idp_dna.x_net); 66*21488Ssklower if (ia == 0) { 67*21488Ssklower error = ENETUNREACH; 68*21488Ssklower goto bad; 69*21488Ssklower } 70*21488Ssklower ifp = ia->ia_ifp; 71*21488Ssklower goto gotif; 72*21488Ssklower } 73*21488Ssklower rtalloc(ro); 74*21488Ssklower } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) { 75*21488Ssklower /* 76*21488Ssklower * The old route has gone away; try for a new one. 77*21488Ssklower */ 78*21488Ssklower rtfree(ro->ro_rt); 79*21488Ssklower rtalloc(ro); 80*21488Ssklower } 81*21488Ssklower if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { 82*21488Ssklower error = ENETUNREACH; 83*21488Ssklower goto bad; 84*21488Ssklower } 85*21488Ssklower ro->ro_rt->rt_use++; 86*21488Ssklower if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST)) 87*21488Ssklower dst = (struct sockaddr_ns *)&ro->ro_rt->rt_gateway; 88*21488Ssklower gotif: 89*21488Ssklower 90*21488Ssklower /* 91*21488Ssklower * Look for multicast addresses and 92*21488Ssklower * and verify user is allowed to send 93*21488Ssklower * such a packet. 94*21488Ssklower */ 95*21488Ssklower if (dst->sns_addr.x_host.c_host[0]&1) { 96*21488Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) { 97*21488Ssklower error = EADDRNOTAVAIL; 98*21488Ssklower goto bad; 99*21488Ssklower } 100*21488Ssklower if ((flags & NS_ALLOWBROADCAST) == 0) { 101*21488Ssklower error = EACCES; 102*21488Ssklower goto bad; 103*21488Ssklower } 104*21488Ssklower } 105*21488Ssklower 106*21488Ssklower if (htons(idp->idp_len) <= ifp->if_mtu) { 107*21488Ssklower ns_output_cnt++; 108*21488Ssklower error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst); 109*21488Ssklower goto done; 110*21488Ssklower } else error = EMSGSIZE; 111*21488Ssklower 112*21488Ssklower 113*21488Ssklower bad: 114*21488Ssklower m_freem(m0); 115*21488Ssklower done: 116*21488Ssklower if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt) 117*21488Ssklower RTFREE(ro->ro_rt); 118*21488Ssklower return (error); 119*21488Ssklower } 120