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