|
|
1.1 root 1: /*
2: * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: *
17: * @(#)ns_output.c 7.3 (Berkeley) 6/29/88
18: */
19:
20: #include "param.h"
21: #include "mbuf.h"
22: #include "errno.h"
23: #include "socket.h"
24: #include "socketvar.h"
25:
26: #include "../net/if.h"
27: #include "../net/route.h"
28:
29: #include "ns.h"
30: #include "ns_if.h"
31: #include "idp.h"
32: #include "idp_var.h"
33:
34: #ifdef vax
35: #include "../vax/mtpr.h"
36: #endif
37: int ns_hold_output = 0;
38: int ns_copy_output = 0;
39: int ns_output_cnt = 0;
40: struct mbuf *ns_lastout;
41:
42: ns_output(m0, ro, flags)
43: struct mbuf *m0;
44: struct route *ro;
45: int flags;
46: {
47: register struct idp *idp = mtod(m0, struct idp *);
48: register struct ifnet *ifp = 0;
49: int error = 0;
50: struct route idproute;
51: struct sockaddr_ns *dst;
52: extern int idpcksum;
53:
54: if (ns_hold_output) {
55: if (ns_lastout) {
56: (void)m_free(ns_lastout);
57: }
58: ns_lastout = m_copy(m0, 0, (int)M_COPYALL);
59: }
60: /*
61: * Route packet.
62: */
63: if (ro == 0) {
64: ro = &idproute;
65: bzero((caddr_t)ro, sizeof (*ro));
66: }
67: dst = (struct sockaddr_ns *)&ro->ro_dst;
68: if (ro->ro_rt == 0) {
69: dst->sns_family = AF_NS;
70: dst->sns_addr = idp->idp_dna;
71: dst->sns_addr.x_port = 0;
72: /*
73: * If routing to interface only,
74: * short circuit routing lookup.
75: */
76: if (flags & NS_ROUTETOIF) {
77: struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
78:
79: if (ia == 0) {
80: error = ENETUNREACH;
81: goto bad;
82: }
83: ifp = ia->ia_ifp;
84: goto gotif;
85: }
86: rtalloc(ro);
87: } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) {
88: /*
89: * The old route has gone away; try for a new one.
90: */
91: rtfree(ro->ro_rt);
92: ro->ro_rt = NULL;
93: rtalloc(ro);
94: }
95: if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
96: error = ENETUNREACH;
97: goto bad;
98: }
99: ro->ro_rt->rt_use++;
100: if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST))
101: dst = (struct sockaddr_ns *)&ro->ro_rt->rt_gateway;
102: gotif:
103:
104: /*
105: * Look for multicast addresses and
106: * and verify user is allowed to send
107: * such a packet.
108: */
109: if (dst->sns_addr.x_host.c_host[0]&1) {
110: if ((ifp->if_flags & IFF_BROADCAST) == 0) {
111: error = EADDRNOTAVAIL;
112: goto bad;
113: }
114: if ((flags & NS_ALLOWBROADCAST) == 0) {
115: error = EACCES;
116: goto bad;
117: }
118: }
119:
120: if (htons(idp->idp_len) <= ifp->if_mtu) {
121: ns_output_cnt++;
122: if (ns_copy_output) {
123: ns_watch_output(m0, ifp);
124: }
125: error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst);
126: goto done;
127: } else error = EMSGSIZE;
128:
129:
130: bad:
131: if (ns_copy_output) {
132: ns_watch_output(m0, ifp);
133: }
134: m_freem(m0);
135: done:
136: if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt)
137: RTFREE(ro->ro_rt);
138: return (error);
139: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.