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