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