conversion of ino_t from u_short to u_long (making dir entries 32 bytes each)
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
2b4b57cd 1/* uipc_syscalls.c 4.4 81/11/18 */
c8c7dd0e
BJ
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"
c8c7dd0e
BJ
12#include "../h/protosw.h"
13#include "../h/socket.h"
14#include "../h/socketvar.h"
c8c7dd0e
BJ
15#include "../net/inet.h"
16#include "../net/inet_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 *
cc15ab5d 24 * TODO:
cc15ab5d 25 * SO_INTNOTIFY
c8c7dd0e
BJ
26 */
27
2b4b57cd 28static struct sockproto localproto = { PF_LOCAL, 0 };
c8c7dd0e 29/*
cc15ab5d 30 * Pipe system call interface.
c8c7dd0e 31 */
cc15ab5d 32spipe()
c8c7dd0e 33{
cc15ab5d
BJ
34 register struct file *rf, *wf;
35 struct socket *rso, *wso;
36 int r;
2b4b57cd 37COUNT(SPIPE);
cc15ab5d 38
2b4b57cd
BJ
39 u.u_error = socreate(&rso, SOCK_STREAM,
40 &localproto, (struct sockaddr *)0, 0);
cc15ab5d 41 if (u.u_error)
c8c7dd0e 42 return;
2b4b57cd
BJ
43 u.u_error = socreate(&wso, SOCK_STREAM,
44 &localproto, (struct sockaddr *)0, 0);
c8c7dd0e 45 if (u.u_error)
cc15ab5d
BJ
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;
2b4b57cd 60 if (piconnect(rso, wso) == 0)
cc15ab5d 61 goto free4;
2b4b57cd 62 rso->so_isfilerefd = wso->so_isfilerefd = 1;
c8c7dd0e 63 return;
cc15ab5d
BJ
64free4:
65 wf->f_count = 0;
c8c7dd0e 66 u.u_ofile[u.u_r.r_val1] = 0;
cc15ab5d
BJ
67free3:
68 rf->f_count = 0;
69 u.u_ofile[r] = 0;
70free2:
71 sofree(wso);
72free:
73 sofree(rso);
c8c7dd0e
BJ
74}
75
c8c7dd0e 76/*
cc15ab5d 77 * Splice system call interface.
c8c7dd0e 78 */
cc15ab5d 79ssplice()
c8c7dd0e 80{
cc15ab5d
BJ
81 register struct a {
82 int fd1;
83 int fd2;
84 } *ap = (struct a *)u.u_ap;
85 struct file *f1, *f2;
2b4b57cd 86COUNT(SSPLICE);
c8c7dd0e 87
cc15ab5d
BJ
88 f1 = getf(ap->fd1);
89 if (f1 == NULL)
90 return;
91 f2 = getf(ap->fd2);
92 if (f2 == NULL)
93 return;
2b4b57cd
BJ
94 if (f1 == f2) {
95 u.u_error = EINVAL;
96 return;
97 }
cc15ab5d
BJ
98 if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) {
99 u.u_error = ENOTSOCK;
100 return;
101 }
102 if (f1->f_count > 1 || f2->f_count > 1) {
103 u.u_error = ETOOMANYREFS;
104 return;
105 }
2b4b57cd 106 u.u_error = sosplice(f1->f_socket, f2->f_socket);
cc15ab5d
BJ
107 if (u.u_error)
108 return;
109 u.u_ofile[ap->fd1] = 0;
110 u.u_ofile[ap->fd2] = 0;
111 f1->f_count = 0;
112 f2->f_count = 0;
c8c7dd0e
BJ
113}
114
115/*
2b4b57cd 116 * Socket system call interface. Copy sa arguments
cc15ab5d
BJ
117 * set up file descriptor and call internal socket
118 * creation routine.
c8c7dd0e 119 */
cc15ab5d 120ssocket()
c8c7dd0e 121{
cc15ab5d
BJ
122 register struct a {
123 int type;
2b4b57cd
BJ
124 struct sockproto *asp;
125 struct sockaddr *asa;
cc15ab5d
BJ
126 int options;
127 } *uap = (struct a *)u.u_ap;
2b4b57cd
BJ
128 struct sockproto sp;
129 struct sockaddr sa;
130 struct socket *so;
cc15ab5d 131 register struct file *fp;
2b4b57cd 132COUNT(SSOCKET);
c8c7dd0e 133
cc15ab5d
BJ
134 if ((fp = falloc()) == NULL)
135 return;
136 fp->f_flag = FSOCKET|FREAD|FWRITE;
2b4b57cd
BJ
137 if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) ||
138 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
cc15ab5d
BJ
139 u.u_error = EFAULT;
140 return;
c8c7dd0e 141 }
2b4b57cd
BJ
142 u.u_error = socreate(&so, uap->type,
143 uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
cc15ab5d
BJ
144 if (u.u_error)
145 goto bad;
2b4b57cd
BJ
146 fp->f_socket = so;
147 so->so_isfilerefd = 1;
cc15ab5d
BJ
148 return;
149bad:
150 u.u_ofile[u.u_r.r_val1] = 0;
151 fp->f_count = 0;
c8c7dd0e 152}
ae921915 153
2b4b57cd
BJ
154/*
155 * Accept system call interface.
156 */
ae921915
BJ
157saccept()
158{
2b4b57cd
BJ
159 register struct a {
160 int fdes;
161 struct sockaddr *asa;
162 } *uap = (struct a *)u.u_ap;
163 struct sockaddr sa;
164 register struct file *fp;
165 struct socket *so;
166 int s;
167COUNT(SACCEPT);
ae921915 168
2b4b57cd
BJ
169 if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
170 u.u_error = EFAULT;
171 return;
172 }
173 fp = getf(uap->fdes);
174 if (fp == 0)
175 return;
176 if ((fp->f_flag & FSOCKET) == 0) {
177 u.u_error = ENOTSOCK;
178 return;
179 }
180 s = splnet();
181 so = fp->f_socket;
182 if ((so->so_options & SO_NBIO) &&
183 (so->so_state & SS_CONNAWAITING) == 0) {
184 u.u_error = EWOULDBLOCK;
185 splx(s);
186 return;
187 }
188 u.u_error = soaccept(so, &sa);
189 if (u.u_error) {
190 splx(s);
191 return;
192 }
193 /* deal with new file descriptor case */
194 /* u.u_r.r_val1 = ... */
195 splx(s);
ae921915
BJ
196}
197
c8c7dd0e
BJ
198/*
199 * Connect socket to foreign peer; system call
2b4b57cd 200 * interface. Copy sa arguments and call internal routine.
c8c7dd0e
BJ
201 */
202sconnect()
203{
204 register struct a {
2b4b57cd
BJ
205 int fdes;
206 struct sockaddr *a;
c8c7dd0e 207 } *uap = (struct a *)u.u_ap;
2b4b57cd 208 struct sockaddr sa;
c8c7dd0e
BJ
209 register struct file *fp;
210 register struct socket *so;
211 int s;
2b4b57cd 212COUNT(SCONNECT);
c8c7dd0e 213
2b4b57cd 214 if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
c8c7dd0e
BJ
215 u.u_error = EFAULT;
216 return;
217 }
218 fp = getf(uap->fdes);
219 if (fp == 0)
220 return;
221 if ((fp->f_flag & FSOCKET) == 0) {
222 u.u_error = ENOTSOCK;
223 return;
224 }
225 so = fp->f_socket;
2b4b57cd 226 u.u_error = soconnect(so, &sa);
c8c7dd0e
BJ
227 if (u.u_error)
228 return;
229 s = splnet();
cc15ab5d
BJ
230 if ((so->so_options & SO_NBIO) &&
231 (so->so_state & SS_ISCONNECTING)) {
c8c7dd0e 232 u.u_error = EINPROGRESS;
cc15ab5d 233 splx(s);
c8c7dd0e
BJ
234 return;
235 }
cc15ab5d 236 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
237 sleep((caddr_t)&so->so_timeo, PZERO+1);
238 u.u_error = so->so_error;
cc15ab5d
BJ
239 so->so_error = 0;
240 splx(s);
c8c7dd0e
BJ
241}
242
243/*
244 * Disconnect socket from foreign peer; system call
2b4b57cd 245 * interface. Copy sa arguments and call internal routine.
c8c7dd0e
BJ
246 */
247sdisconnect()
248{
249 register struct a {
250 int fdes;
2b4b57cd 251 struct sockaddr *asa;
c8c7dd0e 252 } *uap = (struct a *)u.u_ap;
2b4b57cd 253 struct sockaddr sa;
c8c7dd0e 254 register struct file *fp;
cc15ab5d 255 register struct socket *so;
c8c7dd0e 256 int s;
2b4b57cd 257COUNT(SDISCONNECT);
c8c7dd0e 258
2b4b57cd
BJ
259 if (uap->asa &&
260 copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
c8c7dd0e
BJ
261 u.u_error = EFAULT;
262 return;
263 }
264 fp = getf(uap->fdes);
265 if (fp == 0)
266 return;
267 if ((fp->f_flag & FSOCKET) == 0) {
268 u.u_error = ENOTSOCK;
269 return;
270 }
cc15ab5d 271 so = fp->f_socket;
2b4b57cd 272 u.u_error = sodisconnect(so, uap->asa ? &sa : 0);
c8c7dd0e
BJ
273 if (u.u_error)
274 return;
275 s = splnet();
cc15ab5d
BJ
276 if ((so->so_options&SO_NBIO) && (so->so_state&SS_ISDISCONNECTING)) {
277 u.u_error = EINPROGRESS;
278 splx(s);
279 return;
280 }
281 while (so->so_state & SS_ISDISCONNECTING)
c8c7dd0e
BJ
282 sleep((caddr_t)&so->so_timeo, PZERO+1);
283 u.u_error = so->so_error;
cc15ab5d
BJ
284 so->so_error = 0;
285 splx(s);
c8c7dd0e
BJ
286}
287
288/*
289 * Send data on socket.
290 */
291ssend()
292{
293 register struct a {
294 int fdes;
2b4b57cd 295 struct sockaddr *asa;
c8c7dd0e 296 caddr_t cbuf;
2b4b57cd 297 unsigned count;
c8c7dd0e
BJ
298 } *uap = (struct a *)u.u_ap;
299 register struct file *fp;
2b4b57cd
BJ
300 struct sockaddr sa;
301COUNT(SSEND);
c8c7dd0e
BJ
302
303 fp = getf(uap->fdes);
304 if (fp == 0)
305 return;
306 if ((fp->f_flag & FSOCKET) == 0) {
307 u.u_error = ENOTSOCK;
308 return;
309 }
c8c7dd0e
BJ
310 u.u_count = uap->count;
311 u.u_segflg = 0;
cc15ab5d 312 if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
2b4b57cd 313 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
c8c7dd0e
BJ
314 u.u_error = EFAULT;
315 return;
316 }
2b4b57cd 317 u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
c8c7dd0e
BJ
318}
319
cc15ab5d
BJ
320/*
321 * Receive data on socket.
322 */
323sreceive()
324{
325 register struct a {
326 int fdes;
2b4b57cd 327 struct sockaddr *asa;
cc15ab5d 328 caddr_t cbuf;
ae921915 329 u_int count;
cc15ab5d
BJ
330 } *uap = (struct a *)u.u_ap;
331 register struct file *fp;
2b4b57cd
BJ
332 struct sockaddr sa;
333COUNT(SRECEIVE);
cc15ab5d
BJ
334
335 fp = getf(uap->fdes);
336 if (fp == 0)
337 return;
338 if ((fp->f_flag & FSOCKET) == 0) {
339 u.u_error = ENOTSOCK;
340 return;
341 }
cc15ab5d
BJ
342 u.u_count = uap->count;
343 u.u_segflg = 0;
344 if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
2b4b57cd 345 uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
cc15ab5d
BJ
346 u.u_error = EFAULT;
347 return;
348 }
2b4b57cd
BJ
349 u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0);
350 if (u.u_error)
351 return;
352 if (uap->asa)
353 (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
cc15ab5d 354}