xref: /original-bsd/sys/kern/uipc_syscalls.c (revision 8208c1e2)
1 /*	uipc_syscalls.c	4.16	82/03/19	*/
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 COUNT(SPIPE);
38 
39 	u.u_error = socreate(&rso, SOCK_STREAM,
40 	    &localproto, (struct sockaddr *)0, 0);
41 	if (u.u_error)
42 		return;
43 	u.u_error = socreate(&wso, SOCK_STREAM,
44 	    &localproto, (struct sockaddr *)0, 0);
45 	if (u.u_error)
46 		goto free;
47 	rf = falloc();
48 	if (rf == NULL)
49 		goto free2;
50 	r = u.u_r.r_val1;
51 	rf->f_flag = FREAD|FSOCKET;
52 	rf->f_socket = rso;
53 	wf = falloc();
54 	if (wf == NULL)
55 		goto free3;
56 	wf->f_flag = FWRITE|FSOCKET;
57 	wf->f_socket = wso;
58 	u.u_r.r_val2 = u.u_r.r_val1;
59 	u.u_r.r_val1 = r;
60 	if (piconnect(wso, rso) == 0)
61 		goto free4;
62 	return;
63 free4:
64 	wf->f_count = 0;
65 	u.u_ofile[u.u_r.r_val1] = 0;
66 free3:
67 	rf->f_count = 0;
68 	u.u_ofile[r] = 0;
69 free2:
70 	wso->so_state |= SS_USERGONE;
71 	sofree(wso);
72 free:
73 	rso->so_state |= SS_USERGONE;
74 	sofree(rso);
75 }
76 
77 /*
78  * Socket system call interface.  Copy sa arguments
79  * set up file descriptor and call internal socket
80  * creation routine.
81  */
82 ssocket()
83 {
84 	register struct a {
85 		int	type;
86 		struct	sockproto *asp;
87 		struct	sockaddr *asa;
88 		int	options;
89 	} *uap = (struct a *)u.u_ap;
90 	struct sockproto sp;
91 	struct sockaddr sa;
92 	struct socket *so;
93 	register struct file *fp;
94 COUNT(SSOCKET);
95 
96 	if ((fp = falloc()) == NULL)
97 		return;
98 	fp->f_flag = FSOCKET|FREAD|FWRITE;
99 	if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
100 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
101 		u.u_error = EFAULT;
102 		return;
103 	}
104 	u.u_error = socreate(&so, uap->type,
105 	    uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
106 	if (u.u_error)
107 		goto bad;
108 	fp->f_socket = so;
109 	return;
110 bad:
111 	u.u_ofile[u.u_r.r_val1] = 0;
112 	fp->f_count = 0;
113 }
114 
115 /*
116  * Accept system call interface.
117  */
118 saccept()
119 {
120 	register struct a {
121 		int	fdes;
122 		struct	sockaddr *asa;
123 	} *uap = (struct a *)u.u_ap;
124 	struct sockaddr sa;
125 	register struct file *fp;
126 	struct socket *so;
127 	int s;
128 COUNT(SACCEPT);
129 
130 	if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
131 		u.u_error = EFAULT;
132 		return;
133 	}
134 	fp = getf(uap->fdes);
135 	if (fp == 0)
136 		return;
137 	if ((fp->f_flag & FSOCKET) == 0) {
138 		u.u_error = ENOTSOCK;
139 		return;
140 	}
141 	s = splnet();
142 	so = fp->f_socket;
143 	if ((so->so_state & SS_NBIO) &&
144 	    (so->so_state & SS_CONNAWAITING) == 0) {
145 		u.u_error = EWOULDBLOCK;
146 		splx(s);
147 		return;
148 	}
149 	while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0)
150 		sleep((caddr_t)&so->so_timeo, PZERO+1);
151 	if (so->so_error) {
152 		u.u_error = so->so_error;
153 		splx(s);
154 		return;
155 	}
156 	u.u_error = soaccept(so, &sa);
157 	if (u.u_error) {
158 		splx(s);
159 		return;
160 	}
161 	if (uap->asa)
162 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
163 	/* deal with new file descriptor case */
164 	/* u.u_r.r_val1 = ... */
165 	splx(s);
166 }
167 
168 /*
169  * Connect socket to foreign peer; system call
170  * interface.  Copy sa arguments and call internal routine.
171  */
172 sconnect()
173 {
174 	register struct a {
175 		int	fdes;
176 		struct	sockaddr *a;
177 	} *uap = (struct a *)u.u_ap;
178 	struct sockaddr sa;
179 	register struct file *fp;
180 	register struct socket *so;
181 	int s;
182 COUNT(SCONNECT);
183 
184 	if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
185 		u.u_error = EFAULT;
186 		return;
187 	}
188 	fp = getf(uap->fdes);
189 	if (fp == 0)
190 		return;
191 	if ((fp->f_flag & FSOCKET) == 0) {
192 		u.u_error = ENOTSOCK;
193 		return;
194 	}
195 	so = fp->f_socket;
196 	u.u_error = soconnect(so, &sa);
197 	if (u.u_error)
198 		return;
199 	s = splnet();
200 	if ((so->so_state & SS_NBIO) &&
201 	    (so->so_state & SS_ISCONNECTING)) {
202 		u.u_error = EINPROGRESS;
203 		splx(s);
204 		return;
205 	}
206 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
207 		sleep((caddr_t)&so->so_timeo, PZERO+1);
208 	u.u_error = so->so_error;
209 	so->so_error = 0;
210 	splx(s);
211 }
212 
213 /*
214  * Send data on socket.
215  */
216 ssend()
217 {
218 	register struct a {
219 		int	fdes;
220 		struct	sockaddr *asa;
221 		caddr_t	cbuf;
222 		unsigned count;
223 	} *uap = (struct a *)u.u_ap;
224 	register struct file *fp;
225 	struct sockaddr sa;
226 COUNT(SSEND);
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 COUNT(SRECEIVE);
261 
262 	fp = getf(uap->fdes);
263 	if (fp == 0)
264 		return;
265 	if ((fp->f_flag & FSOCKET) == 0) {
266 		u.u_error = ENOTSOCK;
267 		return;
268 	}
269 	u.u_base = uap->cbuf;
270 	u.u_count = uap->count;
271 	u.u_segflg = 0;
272 	if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
273 	    uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
274 		u.u_error = EFAULT;
275 		return;
276 	}
277 	u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
278 	if (u.u_error)
279 		return;
280 	if (uap->asa)
281 		(void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
282 	u.u_r.r_val1 = uap->count - u.u_count;
283 }
284 
285 /*
286  * Get socket address.
287  */
288 ssocketaddr()
289 {
290 	register struct a {
291 		int	fdes;
292 		struct	sockaddr *asa;
293 	} *uap = (struct a *)u.u_ap;
294 	register struct file *fp;
295 COUNT(SSOCKETADDR);
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 	if (copyout((caddr_t)&fp->f_socket->so_addr, (caddr_t)uap->asa,
305 	    sizeof (struct sockaddr))) {
306 		u.u_error = EFAULT;
307 		return;
308 	}
309 }
310