xref: /csrg-svn/sys/kern/uipc_syscalls.c (revision 4888)
1 /*	uipc_syscalls.c	4.2	81/11/14	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/proc.h"
8 #include "../h/file.h"
9 #include "../h/inode.h"
10 #include "../h/buf.h"
11 #include "../h/mbuf.h"
12 #include "../h/protocol.h"
13 #include "../h/protosw.h"
14 #include "../h/socket.h"
15 #include "../h/socketvar.h"
16 #include "../h/inaddr.h"
17 #include "../net/inet.h"
18 #include "../net/inet_systm.h"
19 
20 /*
21  * Socket system call interface.
22  *
23  * These routines interface the socket routines to UNIX,
24  * isolating the system interface from the socket-protocol interface.
25  *
26  * TODO:
27  *	SO_NEWFDONCONN
28  *	SO_INTNOTIFY
29  */
30 
31 static	struct in_addr localaddr = { PF_LOCAL };
32 /*
33  * Pipe system call interface.
34  */
35 spipe()
36 {
37 	register struct file *rf, *wf;
38 	struct socket *rso, *wso;
39 	int r;
40 	struct in_addr waddr;
41 
42 	u.u_error = socket(&rso, SOCK_STREAM, &localaddr, SO_ACCEPTCONN);
43 	if (u.u_error)
44 		return;
45 	u.u_error = socket(&wso, SOCK_STREAM, &localaddr, 0);
46 	if (u.u_error)
47 		goto free;
48 	rf = falloc();
49 	if (rf == NULL)
50 		goto free2;
51 	r = u.u_r.r_val1;
52 	rf->f_flag = FREAD|FSOCKET;
53 	rf->f_socket = rso;
54 	wf = falloc();
55 	if (wf == NULL)
56 		goto free3;
57 	wf->f_flag = FWRITE|FSOCKET;
58 	wf->f_socket = wso;
59 	u.u_r.r_val2 = u.u_r.r_val1;
60 	u.u_r.r_val1 = r;
61 	if (pi_connect(rso, wso) == 0)
62 		goto free4;
63 	return;
64 free4:
65 	wf->f_count = 0;
66 	u.u_ofile[u.u_r.r_val1] = 0;
67 free3:
68 	rf->f_count = 0;
69 	u.u_ofile[r] = 0;
70 free2:
71 	sofree(wso);
72 free:
73 	sofree(rso);
74 }
75 
76 /*
77  * Portal system call interface.
78  *
79  * This call creates a portal.
80  * All the difficulty here is in dealing with errors.
81  * A long sequence of steps is necessary:
82  *	1. a socket must be allocated
83  *	2. the server name length must be determined
84  *	3. the portal must be entered into the file system
85  *	4. the portal type and server must be entered into the portals' file
86  *	5. a file descriptor referencing the socket+inode must be returned
87  * If any errors occur in this process we must back it all out.
88  */
89 sportal()
90 {
91 	register struct a {
92 		caddr_t	name;
93 		int	mode;
94 		caddr_t server;
95 		int	kind;
96 	} *ap = (struct a *)u.u_ap;
97 	struct socket *so;
98 	struct inode *ip;
99 	struct file *fp;
100 	int err, len;
101 	char ch;
102 
103 	/*
104 	 * Allocate the socket for the portal.
105 	 */
106 	u.u_error = socket(&so, SOCK_STREAM, &localaddr, SO_NEWFDONCONN);
107 	if (u.u_error)
108 		return;
109 
110 	/*
111 	 * Check that server name fis in a file system buffer.
112 	 * This to simplify the creation of the portal service process.
113 	 */
114 	if (ap->server) {
115 		u.u_dirp = ap->server;
116 		for (len = 0; len < BSIZE-2; len++) {
117 			register c = uchar();
118 			if (c < 0)
119 				goto bad;
120 			if (c == 0)
121 				break;
122 		}
123 		if (len == BSIZE - 2) {
124 			u.u_error = EINVAL;
125 			goto bad;
126 		}
127 	}
128 
129 	/*
130 	 * Make sure that nothing with the portal's name exists.
131 	 */
132 	u.u_dirp = ap->name;
133 	ip = namei(uchar, 1);
134 	if (ip != NULL) {
135 		iput(ip);
136 		u.u_error = EEXIST;
137 	}
138 	if (u.u_error)
139 		goto bad;
140 
141 	/*
142 	 * Make a node in the file system for the portal.
143 	 */
144 	ip = maknode((ap->mode & 0x7777) | IFPORTAL);
145 	if (ip == NULL)
146 		goto bad;
147 
148 	/*
149 	 * Make the first character of the contents of the
150 	 * portal be the portal type and the rest of the portal be
151 	 * the pathname of the server (if one was given).
152 	 */
153 	ch = (char)ap->kind;
154 	u.u_base = (caddr_t)&ch;
155 	u.u_count = 1;
156 	u.u_offset = 0;
157 	u.u_segflg = 1;
158 	writei(ip);
159 	if (ap->server) {
160 		u.u_base = ap->server;
161 		u.u_count = len;
162 		u.u_segflg = 0;
163 		writei(ip);
164 	}
165 	if (u.u_error)
166 		goto bad2;
167 
168 	/*
169 	 * Allocate a file descriptor and make it reference both
170 	 * the inode representing the portal and the call director
171 	 * socket for the portal.
172 	 */
173 	fp = falloc();
174 	if (fp == NULL)
175 		goto bad2;
176 	fp->f_flag = FPORTAL|FSOCKET;
177 	fp->f_inode = ip;
178 	fp->f_socket = so;
179 
180 	/*
181 	 * Make the in-core inode reference the socket.
182 	 */
183 	ip->i_un.i_socket = so;
184 	irele(ip);
185 	return;
186 bad2:
187 	err = u.u_error;
188 	iput(ip);
189 	u.u_dirp = ap->name;
190 	unlink();
191 	u.u_error = err;
192 bad:
193 	sofree(so);
194 }
195 
196 /*
197  * Splice system call interface.
198  */
199 ssplice()
200 {
201 	register struct a {
202 		int	fd1;
203 		int	fd2;
204 	} *ap = (struct a *)u.u_ap;
205 	struct file *f1, *f2;
206 	struct socket *pso, *pso2;
207 
208 	f1 = getf(ap->fd1);
209 	if (f1 == NULL)
210 		return;
211 	f2 = getf(ap->fd2);
212 	if (f2 == NULL)
213 		return;
214 	if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) {
215 		u.u_error = ENOTSOCK;
216 		return;
217 	}
218 	if (f1->f_count > 1 || f2->f_count > 1) {
219 		u.u_error = ETOOMANYREFS;
220 		return;
221 	}
222 	u.u_error = pi_splice(f1->f_socket, f2->f_socket);
223 	if (u.u_error)
224 		return;
225 	u.u_ofile[ap->fd1] = 0;
226 	u.u_ofile[ap->fd2] = 0;
227 	f1->f_count = 0;
228 	f2->f_count = 0;
229 }
230 
231 /*
232  * Socket system call interface.  Copy in arguments
233  * set up file descriptor and call internal socket
234  * creation routine.
235  */
236 ssocket()
237 {
238 	register struct a {
239 		int	type;
240 		struct	in_addr *ain;
241 		int	options;
242 	} *uap = (struct a *)u.u_ap;
243 	struct in_addr in;
244 	struct socket *so0;
245 	register struct file *fp;
246 
247 	if ((fp = falloc()) == NULL)
248 		return;
249 	fp->f_flag = FSOCKET|FREAD|FWRITE;
250 	if (copyin((caddr_t)uap->ain, &in, sizeof (in))) {
251 		u.u_error = EFAULT;
252 		return;
253 	}
254 	u.u_error = socket(&so0, uap->type, &in, uap->options);
255 	if (u.u_error)
256 		goto bad;
257 	fp->f_socket = so0;
258 	return;
259 bad:
260 	u.u_ofile[u.u_r.r_val1] = 0;
261 	fp->f_count = 0;
262 }
263 /*
264  * Connect socket to foreign peer; system call
265  * interface.  Copy in arguments and call internal routine.
266  */
267 sconnect()
268 {
269 	register struct a {
270 		int fdes;
271 		struct in_addr *a;
272 	} *uap = (struct a *)u.u_ap;
273 	in_addr in;
274 	register struct file *fp;
275 	register struct socket *so;
276 	int s;
277 
278 	if (copyin((caddr_t)uap->a, &in, sizeof (in))) {
279 		u.u_error = EFAULT;
280 		return;
281 	}
282 	fp = getf(uap->fdes);
283 	if (fp == 0)
284 		return;
285 	if ((fp->f_flag & FSOCKET) == 0) {
286 		u.u_error = ENOTSOCK;
287 		return;
288 	}
289 	so = fp->f_socket;
290 	u.u_error = connect(so, &in);
291 	if (u.u_error)
292 		return;
293 	s = splnet();
294 	if ((so->so_options & SO_NBIO) &&
295 	    (so->so_state & SS_ISCONNECTING)) {
296 		u.u_error = EINPROGRESS;
297 		splx(s);
298 		return;
299 	}
300 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
301 		sleep((caddr_t)&so->so_timeo, PZERO+1);
302 	u.u_error = so->so_error;
303 	so->so_error = 0;
304 	splx(s);
305 }
306 
307 /*
308  * Disconnect socket from foreign peer; system call
309  * interface.  Copy in arguments and call internal routine.
310  */
311 sdisconnect()
312 {
313 	register struct a {
314 		int	fdes;
315 		in_addr	 *addr;
316 	} *uap = (struct a *)u.u_ap;
317 	in_addr in;
318 	register struct file *fp;
319 	register struct socket *so;
320 	int s;
321 
322 	if (uap->addr &&
323 	    copyin((caddr_t)uap->addr, (caddr_t)&in, sizeof (in))) {
324 		u.u_error = EFAULT;
325 		return;
326 	}
327 	fp = getf(uap->fdes);
328 	if (fp == 0)
329 		return;
330 	if ((fp->f_flag & FSOCKET) == 0) {
331 		u.u_error = ENOTSOCK;
332 		return;
333 	}
334 	so = fp->f_socket;
335 	u.u_error = disconnect(so, uap->addr ? &in : 0);
336 	if (u.u_error)
337 		return;
338 	s = splnet();
339 	if ((so->so_options&SO_NBIO) && (so->so_state&SS_ISDISCONNECTING)) {
340 		u.u_error = EINPROGRESS;
341 		splx(s);
342 		return;
343 	}
344 	while (so->so_state & SS_ISDISCONNECTING)
345 		sleep((caddr_t)&so->so_timeo, PZERO+1);
346 	u.u_error = so->so_error;
347 	so->so_error = 0;
348 	splx(s);
349 }
350 
351 /*
352  * Send data on socket.
353  */
354 ssend()
355 {
356 	register struct a {
357 		int	fdes;
358 		in_addr	*ain;
359 		caddr_t	cbuf;
360 		int	count;
361 	} *uap = (struct a *)u.u_ap;
362 	register struct file *fp;
363 	struct in_addr in;
364 
365 	fp = getf(uap->fdes);
366 	if (fp == 0)
367 		return;
368 	if ((fp->f_flag & FSOCKET) == 0) {
369 		u.u_error = ENOTSOCK;
370 		return;
371 	}
372 	if (uap->count < 0) {
373 		u.u_error = EINVAL;
374 		return;
375 	}
376 	u.u_base = uap->cbuf;
377 	u.u_count = uap->count;
378 	u.u_segflg = 0;
379 	if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
380 	    uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) {
381 		u.u_error = EFAULT;
382 		return;
383 	}
384 	u.u_error = send(fp->f_socket, uap->ain ? &in : 0);
385 }
386 
387 /*
388  * Receive data on socket.
389  */
390 sreceive()
391 {
392 	register struct a {
393 		int	fdes;
394 		in_addr	*ain;
395 		caddr_t	cbuf;
396 		int	count;
397 	} *uap = (struct a *)u.u_ap;
398 	register struct file *fp;
399 	struct in_addr *in;
400 
401 	fp = getf(uap->fdes);
402 	if (fp == 0)
403 		return;
404 	if ((fp->f_flag & FSOCKET) == 0) {
405 		u.u_error = ENOTSOCK;
406 		return;
407 	}
408 	if (uap->count < 0) {
409 		u.u_error = EINVAL;
410 		return;
411 	}
412 	u.u_base = uap->cbuf;
413 	u.u_count = uap->count;
414 	u.u_segflg = 0;
415 	if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
416 	    uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) {
417 		u.u_error = EFAULT;
418 		return;
419 	}
420 	receive(fp->f_socket, uap->ain ? &in : 0);
421 }
422