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