xref: /csrg-svn/sys/kern/uipc_syscalls.c (revision 7247)
1 /*	uipc_syscalls.c	4.20	82/06/20	*/
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/protosw.h"
13 #include "../h/socket.h"
14 #include "../h/socketvar.h"
15 #include "../net/in.h"
16 #include "../net/in_systm.h"
17 
18 /*
19  * Socket system call interface.
20  *
21  * These routines interface the socket routines to UNIX,
22  * isolating the system interface from the socket-protocol interface.
23  *
24  * TODO:
25  *	SO_INTNOTIFY
26  */
27 
28 static	struct sockproto localproto = { PF_UNIX, 0 };
29 /*
30  * Pipe system call interface.
31  */
32 spipe()
33 {
34 	register struct file *rf, *wf;
35 	struct socket *rso, *wso;
36 	int r;
37 
38 	u.u_error = socreate(&rso, SOCK_STREAM,
39 	    &localproto, (struct sockaddr *)0, 0);
40 	if (u.u_error)
41 		return;
42 	u.u_error = socreate(&wso, SOCK_STREAM,
43 	    &localproto, (struct sockaddr *)0, 0);
44 	if (u.u_error)
45 		goto free;
46 	rf = falloc();
47 	if (rf == NULL)
48 		goto free2;
49 	r = u.u_r.r_val1;
50 	rf->f_flag = FREAD|FSOCKET;
51 	rf->f_socket = rso;
52 	wf = falloc();
53 	if (wf == NULL)
54 		goto free3;
55 	wf->f_flag = FWRITE|FSOCKET;
56 	wf->f_socket = wso;
57 	u.u_r.r_val2 = u.u_r.r_val1;
58 	u.u_r.r_val1 = r;
59 	if (piconnect(wso, rso) == 0)
60 		goto free4;
61 	return;
62 free4:
63 	wf->f_count = 0;
64 	u.u_ofile[u.u_r.r_val2] = 0;
65 free3:
66 	rf->f_count = 0;
67 	u.u_ofile[r] = 0;
68 free2:
69 	wso->so_state |= SS_USERGONE;
70 	sofree(wso);
71 free:
72 	rso->so_state |= SS_USERGONE;
73 	sofree(rso);
74 }
75 
76 /*
77  * Socket system call interface.  Copy sa arguments
78  * set up file descriptor and call internal socket
79  * creation routine.
80  */
81 ssocket()
82 {
83 	register struct a {
84 		int	type;
85 		struct	sockproto *asp;
86 		struct	sockaddr *asa;
87 		int	options;
88 	} *uap = (struct a *)u.u_ap;
89 	struct sockproto sp;
90 	struct sockaddr sa;
91 	struct socket *so;
92 	register struct file *fp;
93 
94 	if ((fp = falloc()) == NULL)
95 		return;
96 	fp->f_flag = FSOCKET|FREAD|FWRITE;
97 	if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
98 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
99 		u.u_error = EFAULT;
100 		return;
101 	}
102 	u.u_error = socreate(&so, uap->type,
103 	    uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
104 	if (u.u_error)
105 		goto bad;
106 	fp->f_socket = so;
107 	return;
108 bad:
109 	u.u_ofile[u.u_r.r_val1] = 0;
110 	fp->f_count = 0;
111 }
112 
113 /*
114  * Accept system call interface.
115  */
116 saccept()
117 {
118 	register struct a {
119 		int	fdes;
120 		struct	sockaddr *asa;
121 	} *uap = (struct a *)u.u_ap;
122 	struct sockaddr sa;
123 	register struct file *fp;
124 	struct socket *so;
125 	int s;
126 
127 	if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
128 		u.u_error = EFAULT;
129 		return;
130 	}
131 	fp = getf(uap->fdes);
132 	if (fp == 0)
133 		return;
134 	if ((fp->f_flag & FSOCKET) == 0) {
135 		u.u_error = ENOTSOCK;
136 		return;
137 	}
138 	s = splnet();
139 	so = fp->f_socket;
140 	if ((so->so_state & SS_NBIO) &&
141 	    (so->so_state & SS_CONNAWAITING) == 0) {
142 		u.u_error = EWOULDBLOCK;
143 		splx(s);
144 		return;
145 	}
146 	while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0) {
147 		if (so->so_state & SS_CANTRCVMORE) {
148 			so->so_error = ECONNABORTED;
149 			break;
150 		}
151 		sleep((caddr_t)&so->so_timeo, PZERO+1);
152 	}
153 	if (so->so_error) {
154 		u.u_error = so->so_error;
155 		splx(s);
156 		return;
157 	}
158 	u.u_error = soaccept(so, &sa);
159 	if (u.u_error) {
160 		splx(s);
161 		return;
162 	}
163 	if (uap->asa)
164 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
165 	/* deal with new file descriptor case */
166 	/* u.u_r.r_val1 = ... */
167 	splx(s);
168 }
169 
170 /*
171  * Connect socket to foreign peer; system call
172  * interface.  Copy sa arguments and call internal routine.
173  */
174 sconnect()
175 {
176 	register struct a {
177 		int	fdes;
178 		struct	sockaddr *a;
179 	} *uap = (struct a *)u.u_ap;
180 	struct sockaddr sa;
181 	register struct file *fp;
182 	register struct socket *so;
183 	int s;
184 
185 	if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
186 		u.u_error = EFAULT;
187 		return;
188 	}
189 	fp = getf(uap->fdes);
190 	if (fp == 0)
191 		return;
192 	if ((fp->f_flag & FSOCKET) == 0) {
193 		u.u_error = ENOTSOCK;
194 		return;
195 	}
196 	so = fp->f_socket;
197 	u.u_error = soconnect(so, &sa);
198 	if (u.u_error)
199 		return;
200 	s = splnet();
201 	if ((so->so_state & SS_NBIO) &&
202 	    (so->so_state & SS_ISCONNECTING)) {
203 		u.u_error = EINPROGRESS;
204 		splx(s);
205 		return;
206 	}
207 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
208 		sleep((caddr_t)&so->so_timeo, PZERO+1);
209 	u.u_error = so->so_error;
210 	so->so_error = 0;
211 	splx(s);
212 }
213 
214 /*
215  * Send data on socket.
216  */
217 ssend()
218 {
219 	register struct a {
220 		int	fdes;
221 		struct	sockaddr *asa;
222 		caddr_t	cbuf;
223 		unsigned count;
224 	} *uap = (struct a *)u.u_ap;
225 	register struct file *fp;
226 	struct sockaddr sa;
227 
228 	fp = getf(uap->fdes);
229 	if (fp == 0)
230 		return;
231 	if ((fp->f_flag & FSOCKET) == 0) {
232 		u.u_error = ENOTSOCK;
233 		return;
234 	}
235 	u.u_base = uap->cbuf;
236 	u.u_count = uap->count;
237 	u.u_segflg = 0;
238 	if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
239 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
240 		u.u_error = EFAULT;
241 		return;
242 	}
243 	u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
244 	u.u_r.r_val1 = uap->count - u.u_count;
245 }
246 
247 /*
248  * Receive data on socket.
249  */
250 sreceive()
251 {
252 	register struct a {
253 		int	fdes;
254 		struct	sockaddr *asa;
255 		caddr_t	cbuf;
256 		u_int	count;
257 	} *uap = (struct a *)u.u_ap;
258 	register struct file *fp;
259 	struct sockaddr sa;
260 
261 	fp = getf(uap->fdes);
262 	if (fp == 0)
263 		return;
264 	if ((fp->f_flag & FSOCKET) == 0) {
265 		u.u_error = ENOTSOCK;
266 		return;
267 	}
268 	u.u_base = uap->cbuf;
269 	u.u_count = uap->count;
270 	u.u_segflg = 0;
271 	if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
272 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
273 		u.u_error = EFAULT;
274 		return;
275 	}
276 	u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
277 	if (u.u_error)
278 		return;
279 	if (uap->asa)
280 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
281 	u.u_r.r_val1 = uap->count - u.u_count;
282 }
283 
284 /*
285  * Get socket address.
286  */
287 ssocketaddr()
288 {
289 	register struct a {
290 		int	fdes;
291 		struct	sockaddr *asa;
292 	} *uap = (struct a *)u.u_ap;
293 	register struct file *fp;
294 	register struct socket *so;
295 	struct sockaddr addr;
296 
297 	fp = getf(uap->fdes);
298 	if (fp == 0)
299 		return;
300 	if ((fp->f_flag & FSOCKET) == 0) {
301 		u.u_error = ENOTSOCK;
302 		return;
303 	}
304 	so = fp->f_socket;
305 	u.u_error =
306 		(*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr);
307 	if (u.u_error)
308 		return;
309 	if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr)))
310 		u.u_error = EFAULT;
311 }
312