|
|
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_pcb.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "param.h"
10: #include "systm.h"
11: #include "dir.h"
12: #include "user.h"
13: #include "mbuf.h"
14: #include "socket.h"
15: #include "socketvar.h"
16: #include "../net/if.h"
17: #include "../net/route.h"
18: #include "protosw.h"
19:
20: #include "ns.h"
21: #include "ns_if.h"
22: #include "ns_pcb.h"
23:
24: struct ns_addr zerons_addr;
25:
26: ns_pcballoc(so, head)
27: struct socket *so;
28: struct nspcb *head;
29: {
30: struct mbuf *m;
31: register struct nspcb *nsp;
32:
33: m = m_getclr(M_DONTWAIT, MT_PCB);
34: if (m == NULL)
35: return (ENOBUFS);
36: nsp = mtod(m, struct nspcb *);
37: nsp->nsp_socket = so;
38: insque(nsp, head);
39: so->so_pcb = (caddr_t)nsp;
40: return (0);
41: }
42:
43: ns_pcbbind(nsp, nam)
44: register struct nspcb *nsp;
45: struct mbuf *nam;
46: {
47: register struct sockaddr_ns *sns;
48: u_short lport = 0;
49:
50: if(nsp->nsp_lport || !ns_nullhost(nsp->nsp_laddr))
51: return (EINVAL);
52: if (nam == 0)
53: goto noname;
54: sns = mtod(nam, struct sockaddr_ns *);
55: if (nam->m_len != sizeof (*sns))
56: return (EINVAL);
57: if (!ns_nullhost(sns->sns_addr)) {
58: int tport = sns->sns_port;
59:
60: sns->sns_port = 0; /* yech... */
61: if (ifa_ifwithaddr((struct sockaddr *)sns) == 0)
62: return (EADDRNOTAVAIL);
63: sns->sns_port = tport;
64: }
65: lport = sns->sns_port;
66: if (lport) {
67: u_short aport = ntohs(lport);
68:
69: if (aport < NSPORT_RESERVED && u.u_uid != 0)
70: return (EACCES);
71: if (ns_pcblookup(&zerons_addr, lport, 0))
72: return (EADDRINUSE);
73: }
74: nsp->nsp_laddr = sns->sns_addr;
75: noname:
76: if (lport == 0)
77: do {
78: if (nspcb.nsp_lport++ < NSPORT_RESERVED)
79: nspcb.nsp_lport = NSPORT_RESERVED;
80: lport = htons(nspcb.nsp_lport);
81: } while (ns_pcblookup(&zerons_addr, lport, 0));
82: nsp->nsp_lport = lport;
83: return (0);
84: }
85:
86: /*
87: * Connect from a socket to a specified address.
88: * Both address and port must be specified in argument sns.
89: * If don't have a local address for this socket yet,
90: * then pick one.
91: */
92: ns_pcbconnect(nsp, nam)
93: struct nspcb *nsp;
94: struct mbuf *nam;
95: {
96: struct ns_ifaddr *ia;
97: register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
98: register struct ns_addr *dst;
99:
100: if (nam->m_len != sizeof (*sns))
101: return (EINVAL);
102: if (sns->sns_family != AF_NS)
103: return (EAFNOSUPPORT);
104: if (sns->sns_port==0 || ns_nullhost(sns->sns_addr))
105: return (EADDRNOTAVAIL);
106: if (ns_nullhost(nsp->nsp_laddr) &&
107: (!ns_neteq(nsp->nsp_lastdst, sns->sns_addr))) {
108: register struct route *ro;
109: struct ifnet *ifp;
110: ro = &nsp->nsp_route;
111: dst = &satons_addr(ro->ro_dst);
112:
113: ia = ns_iaonnetof(&sns->sns_addr);
114: if (ia == 0 ||
115: (ia->ia_ifp->if_flags & IFF_UP) == 0) {
116: /*
117: * If route is known or can be allocated now,
118: * our src addr is taken from the i/f, else punt.
119: */
120: if (ro->ro_rt &&
121: !ns_hosteq(*dst, sns->sns_addr)) {
122: RTFREE(ro->ro_rt);
123: ro->ro_rt = (struct rtentry *)0;
124: }
125: if ((ro->ro_rt == (struct rtentry *)0) ||
126: (ifp = ro->ro_rt->rt_ifp) == (struct ifnet *)0) {
127: /* No route yet, so try to acquire one */
128: ro->ro_dst.sa_family = AF_NS;
129: *dst = sns->sns_addr;
130: dst->x_port = 0;
131: rtalloc(ro);
132: if (ro->ro_rt == 0)
133: ifp = (struct ifnet *)0;
134: else
135: ifp = ro->ro_rt->rt_ifp;
136: }
137: if (ifp) {
138: for (ia = ns_ifaddr; ia; ia = ia->ia_next)
139: if (ia->ia_ifp == ifp)
140: break;
141: }
142: if (ia == 0)
143: ia = ns_ifaddr;
144: if (ia == 0)
145: return (EADDRNOTAVAIL);
146: } else if (ro->ro_rt) {
147: if (ns_neteq(*dst, sns->sns_addr)) {
148: /*
149: * This assume that we have no GH
150: * type routes.
151: */
152: if (ro->ro_rt->rt_flags & RTF_HOST) {
153: if (!ns_hosteq(*dst, sns->sns_addr))
154: goto re_route;
155:
156: }
157: if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
158: dst->x_host = sns->sns_addr.x_host;
159: }
160: /*
161: * Otherwise, we go through the same gateway
162: * and dst is already set up.
163: */
164: } else {
165: re_route:
166: RTFREE(ro->ro_rt);
167: ro->ro_rt = (struct rtentry *)0;
168: }
169: }
170: nsp->nsp_laddr.x_net = satons_addr(ia->ia_addr).x_net;
171: nsp->nsp_lastdst = sns->sns_addr;
172: }
173: if (ns_pcblookup(&sns->sns_addr, nsp->nsp_lport, 0))
174: return (EADDRINUSE);
175: if (ns_nullhost(nsp->nsp_laddr)) {
176: if (nsp->nsp_lport == 0)
177: (void) ns_pcbbind(nsp, (struct mbuf *)0);
178: nsp->nsp_laddr.x_host = ns_thishost;
179: }
180: nsp->nsp_faddr = sns->sns_addr;
181: /* Includes nsp->nsp_fport = sns->sns_port; */
182: return (0);
183: }
184:
185: ns_pcbdisconnect(nsp)
186: struct nspcb *nsp;
187: {
188:
189: nsp->nsp_faddr = zerons_addr;
190: if (nsp->nsp_socket->so_state & SS_NOFDREF)
191: ns_pcbdetach(nsp);
192: }
193:
194: ns_pcbdetach(nsp)
195: struct nspcb *nsp;
196: {
197: struct socket *so = nsp->nsp_socket;
198:
199: so->so_pcb = 0;
200: sofree(so);
201: if (nsp->nsp_route.ro_rt)
202: rtfree(nsp->nsp_route.ro_rt);
203: remque(nsp);
204: (void) m_free(dtom(nsp));
205: }
206:
207: ns_setsockaddr(nsp, nam)
208: register struct nspcb *nsp;
209: struct mbuf *nam;
210: {
211: register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
212:
213: nam->m_len = sizeof (*sns);
214: sns = mtod(nam, struct sockaddr_ns *);
215: bzero((caddr_t)sns, sizeof (*sns));
216: sns->sns_family = AF_NS;
217: sns->sns_addr = nsp->nsp_laddr;
218: }
219:
220: ns_setpeeraddr(nsp, nam)
221: register struct nspcb *nsp;
222: struct mbuf *nam;
223: {
224: register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
225:
226: nam->m_len = sizeof (*sns);
227: sns = mtod(nam, struct sockaddr_ns *);
228: bzero((caddr_t)sns, sizeof (*sns));
229: sns->sns_family = AF_NS;
230: sns->sns_addr = nsp->nsp_faddr;
231: }
232:
233: /*
234: * Pass some notification to all connections of a protocol
235: * associated with address dst. Call the
236: * protocol specific routine to handle each connection.
237: * Also pass an extra paramter via the nspcb. (which may in fact
238: * be a parameter list!)
239: */
240: ns_pcbnotify(dst, errno, notify, param)
241: register struct ns_addr *dst;
242: long param;
243: int errno, (*notify)();
244: {
245: register struct nspcb *nsp, *oinp;
246: int s = splimp();
247:
248: for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb);) {
249: if (!ns_hosteq(*dst,nsp->nsp_faddr)) {
250: next:
251: nsp = nsp->nsp_next;
252: continue;
253: }
254: if (nsp->nsp_socket == 0)
255: goto next;
256: if (errno)
257: nsp->nsp_socket->so_error = errno;
258: oinp = nsp;
259: nsp = nsp->nsp_next;
260: oinp->nsp_notify_param = param;
261: (*notify)(oinp);
262: }
263: splx(s);
264: }
265:
266: #ifdef notdef
267: /*
268: * After a routing change, flush old routing
269: * and allocate a (hopefully) better one.
270: */
271: ns_rtchange(nsp)
272: struct nspcb *nsp;
273: {
274: if (nsp->nsp_route.ro_rt) {
275: rtfree(nsp->nsp_route.ro_rt);
276: nsp->nsp_route.ro_rt = 0;
277: /*
278: * A new route can be allocated the next time
279: * output is attempted.
280: */
281: }
282: /* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */
283: }
284: #endif
285:
286: struct nspcb *
287: ns_pcblookup(faddr, lport, wildp)
288: struct ns_addr *faddr;
289: u_short lport;
290: {
291: register struct nspcb *nsp, *match = 0;
292: int matchwild = 3, wildcard;
293: u_short fport;
294:
295: fport = faddr->x_port;
296: for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb); nsp = nsp->nsp_next) {
297: if (nsp->nsp_lport != lport)
298: continue;
299: wildcard = 0;
300: if (ns_nullhost(nsp->nsp_faddr)) {
301: if (!ns_nullhost(*faddr))
302: wildcard++;
303: } else {
304: if (ns_nullhost(*faddr))
305: wildcard++;
306: else {
307: if (!ns_hosteq(nsp->nsp_faddr, *faddr))
308: continue;
309: if( nsp->nsp_fport != fport) {
310: if(nsp->nsp_fport != 0)
311: continue;
312: else
313: wildcard++;
314: }
315: }
316: }
317: if (wildcard && wildp==0)
318: continue;
319: if (wildcard < matchwild) {
320: match = nsp;
321: matchwild = wildcard;
322: if (wildcard == 0)
323: break;
324: }
325: }
326: return (match);
327: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.