get rid of roundup of hash bucket hit; add HASHFRACTION
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
66f52238 1/* uipc_syscalls.c 4.41 83/01/13 */
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"
4147b3f6 15#include "../h/descrip.h"
a6b6f679 16#include "../h/uio.h"
4147b3f6 17
c8c7dd0e 18/*
cf012934 19 * System call interface to the socket abstraction.
c8c7dd0e
BJ
20 */
21
cf012934 22socket()
c8c7dd0e 23{
cc15ab5d 24 register struct a {
cf012934 25 int domain;
cc15ab5d 26 int type;
cf012934 27 int protocol;
cc15ab5d 28 } *uap = (struct a *)u.u_ap;
2b4b57cd 29 struct socket *so;
cc15ab5d 30 register struct file *fp;
c8c7dd0e 31
dfb67abe 32 if ((fp = falloc()) == NULL)
66f52238 33 return;
4147b3f6
BJ
34 fp->f_flag = FREAD|FWRITE;
35 fp->f_type = DTYPE_SOCKET;
66f52238 36 u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol);
cc15ab5d
BJ
37 if (u.u_error)
38 goto bad;
2b4b57cd 39 fp->f_socket = so;
cc15ab5d
BJ
40 return;
41bad:
42 u.u_ofile[u.u_r.r_val1] = 0;
43 fp->f_count = 0;
c8c7dd0e 44}
ae921915 45
cf012934 46bind()
ae921915 47{
2b4b57cd 48 register struct a {
cf012934
BJ
49 int s;
50 caddr_t name;
51 int namelen;
2b4b57cd 52 } *uap = (struct a *)u.u_ap;
2b4b57cd 53 register struct file *fp;
cf012934 54 struct mbuf *nam;
ae921915 55
cf012934
BJ
56 fp = getf(uap->s);
57 if (fp == 0)
58 return;
59 if (fp->f_type != DTYPE_SOCKET) {
60 u.u_error = ENOTSOCK;
2b4b57cd
BJ
61 return;
62 }
cf012934
BJ
63 u.u_error = sockname(&nam, uap->name, uap->namelen);
64 if (u.u_error)
65 return;
66f52238 66 u.u_error = sobind(fp->f_socket, nam);
cf012934 67 m_freem(nam);
cf012934
BJ
68}
69
70listen()
71{
72 register struct a {
73 int s;
74 int backlog;
75 } *uap = (struct a *)u.u_ap;
76 register struct file *fp;
77
78 fp = getf(uap->s);
2b4b57cd
BJ
79 if (fp == 0)
80 return;
4147b3f6 81 if (fp->f_type != DTYPE_SOCKET) {
2b4b57cd
BJ
82 u.u_error = ENOTSOCK;
83 return;
84 }
cf012934
BJ
85 u.u_error = solisten(fp->f_socket, uap->backlog);
86}
87
88accept()
89{
90 register struct a {
91 int s;
92 caddr_t name;
93 int *anamelen;
cf012934
BJ
94 } *uap = (struct a *)u.u_ap;
95 register struct file *fp;
96 struct mbuf *nam;
cf012934
BJ
97 int namelen;
98 int s;
99 register struct socket *so;
100
101 if (uap->name == 0)
102 goto noname;
127f7d76
SL
103 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
104 sizeof (namelen));
105 if (u.u_error)
cf012934 106 return;
b32450f4 107 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
cf012934
BJ
108 u.u_error = EFAULT;
109 return;
110 }
111noname:
cf012934
BJ
112 fp = getf(uap->s);
113 if (fp == 0)
66f52238 114 return;
cf012934
BJ
115 if (fp->f_type != DTYPE_SOCKET) {
116 u.u_error = ENOTSOCK;
66f52238 117 return;
cf012934 118 }
2b4b57cd
BJ
119 s = splnet();
120 so = fp->f_socket;
4147b3f6
BJ
121 if ((so->so_options & SO_ACCEPTCONN) == 0) {
122 u.u_error = EINVAL;
123 splx(s);
66f52238 124 return;
4147b3f6
BJ
125 }
126 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
2b4b57cd
BJ
127 u.u_error = EWOULDBLOCK;
128 splx(s);
66f52238 129 return;
2b4b57cd 130 }
4147b3f6 131 while (so->so_qlen == 0 && so->so_error == 0) {
62229532
BJ
132 if (so->so_state & SS_CANTRCVMORE) {
133 so->so_error = ECONNABORTED;
134 break;
135 }
d08c5322 136 sleep((caddr_t)&so->so_timeo, PZERO+1);
62229532 137 }
f269ef23
BJ
138 if (so->so_error) {
139 u.u_error = so->so_error;
140 splx(s);
66f52238 141 return;
f269ef23 142 }
4147b3f6
BJ
143 if ((so->so_options & SO_NEWFDONCONN) == 0) {
144 struct socket *nso = so->so_q;
145 (void) soqremque(nso, 1);
6e7edb25 146 u.u_error = soclose(so, 1);
4147b3f6
BJ
147 fp->f_socket = nso;
148 nso->so_q = 0;
149 so = nso;
150 goto ret;
151 }
152 if (ufalloc() < 0) {
153 splx(s);
66f52238 154 return;
4147b3f6
BJ
155 }
156 fp = falloc();
157 if (fp == 0) {
158 u.u_ofile[u.u_r.r_val1] = 0;
2b4b57cd 159 splx(s);
66f52238 160 return;
cf012934
BJ
161 }
162 { struct socket *aso = so->so_q;
163 if (soqremque(aso, 1) == 0)
164 panic("accept");
165 so = aso;
2b4b57cd 166 }
4147b3f6
BJ
167 fp->f_type = DTYPE_SOCKET;
168 fp->f_flag = FREAD|FWRITE;
cf012934 169 fp->f_socket = so;
4147b3f6 170ret:
cce93e4b 171 nam = m_get(M_WAIT, MT_SONAME);
66f52238 172 (void) soaccept(so, nam);
cf012934
BJ
173 if (uap->name) {
174 if (namelen > nam->m_len)
175 namelen = nam->m_len;
176 /* SHOULD COPY OUT A CHAIN HERE */
b32450f4
BJ
177 (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
178 (u_int)namelen);
179 (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
cf012934
BJ
180 sizeof (*uap->anamelen));
181 }
182 m_freem(nam);
2b4b57cd 183 splx(s);
ae921915
BJ
184}
185
cf012934 186connect()
c8c7dd0e
BJ
187{
188 register struct a {
cf012934
BJ
189 int s;
190 caddr_t name;
191 int namelen;
c8c7dd0e 192 } *uap = (struct a *)u.u_ap;
c8c7dd0e
BJ
193 register struct file *fp;
194 register struct socket *so;
cf012934 195 struct mbuf *nam;
c8c7dd0e
BJ
196 int s;
197
cf012934 198 fp = getf(uap->s);
c8c7dd0e
BJ
199 if (fp == 0)
200 return;
4147b3f6 201 if (fp->f_type != DTYPE_SOCKET) {
c8c7dd0e
BJ
202 u.u_error = ENOTSOCK;
203 return;
204 }
205 so = fp->f_socket;
cf012934 206 u.u_error = sockname(&nam, uap->name, uap->namelen);
c8c7dd0e
BJ
207 if (u.u_error)
208 return;
66f52238 209 u.u_error = soconnect(so, nam);
cf012934
BJ
210 if (u.u_error)
211 goto bad;
c8c7dd0e 212 s = splnet();
62364f0e 213 if ((so->so_state & SS_NBIO) &&
cc15ab5d 214 (so->so_state & SS_ISCONNECTING)) {
c8c7dd0e 215 u.u_error = EINPROGRESS;
cc15ab5d 216 splx(s);
cf012934 217 goto bad;
c8c7dd0e 218 }
cc15ab5d 219 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
220 sleep((caddr_t)&so->so_timeo, PZERO+1);
221 u.u_error = so->so_error;
cc15ab5d
BJ
222 so->so_error = 0;
223 splx(s);
cf012934
BJ
224bad:
225 m_freem(nam);
c8c7dd0e
BJ
226}
227
cf012934
BJ
228socketpair()
229{
230
231 u.u_error = ENOENT;
232}
233
234sendto()
c8c7dd0e
BJ
235{
236 register struct a {
cf012934
BJ
237 int s;
238 caddr_t buf;
239 int len;
240 int flags;
241 caddr_t to;
242 int tolen;
c8c7dd0e
BJ
243 } *uap = (struct a *)u.u_ap;
244 register struct file *fp;
d3d550b5
BJ
245 struct uio auio;
246 struct iovec aiov;
cf012934 247 struct mbuf *to;
c8c7dd0e 248
cf012934 249 fp = getf(uap->s);
c8c7dd0e
BJ
250 if (fp == 0)
251 return;
4147b3f6 252 if (fp->f_type != DTYPE_SOCKET) {
c8c7dd0e
BJ
253 u.u_error = ENOTSOCK;
254 return;
255 }
d3d550b5
BJ
256 auio.uio_iov = &aiov;
257 auio.uio_iovcnt = 1;
cf012934
BJ
258 aiov.iov_base = uap->buf;
259 aiov.iov_len = uap->len;
260 auio.uio_resid = uap->len;
d3d550b5
BJ
261 auio.uio_segflg = 0;
262 auio.uio_offset = 0; /* XXX */
b32450f4 263 if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) {
c8c7dd0e
BJ
264 u.u_error = EFAULT;
265 return;
266 }
cf012934
BJ
267 u.u_error = sockname(&to, uap->to, uap->tolen);
268 if (u.u_error)
269 goto bad;
970108c7 270 u.u_error = sosend(fp->f_socket, to, &auio, uap->flags);
76d78581 271 u.u_r.r_val1 = uap->len - auio.uio_resid;
cf012934
BJ
272bad:
273 m_freem(to);
c8c7dd0e
BJ
274}
275
cf012934 276send()
cc15ab5d
BJ
277{
278 register struct a {
cf012934
BJ
279 int s;
280 caddr_t buf;
281 int len;
282 int flags;
cc15ab5d
BJ
283 } *uap = (struct a *)u.u_ap;
284 register struct file *fp;
a6b6f679
BJ
285 struct uio auio;
286 struct iovec aiov;
cc15ab5d 287
cf012934
BJ
288 fp = getf(uap->s);
289 if (fp == 0)
290 return;
291 if (fp->f_type != DTYPE_SOCKET) {
292 u.u_error = ENOTSOCK;
293 return;
294 }
295 auio.uio_iov = &aiov;
296 auio.uio_iovcnt = 1;
297 aiov.iov_base = uap->buf;
298 aiov.iov_len = uap->len;
299 auio.uio_resid = uap->len;
300 auio.uio_segflg = 0;
301 auio.uio_offset = 0; /* XXX */
b32450f4 302 if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) {
cf012934
BJ
303 u.u_error = EFAULT;
304 return;
305 }
306 if (u.u_error)
307 return;
970108c7 308 u.u_error = sosend(fp->f_socket, (struct mbuf *)0, &auio, uap->flags);
76d78581 309 u.u_r.r_val1 = uap->len - auio.uio_resid;
cf012934
BJ
310}
311
312recvfrom()
313{
314 register struct a {
315 int s;
316 caddr_t buf;
317 int len;
318 int flags;
319 caddr_t from;
320 int *fromlenaddr;
321 } *uap = (struct a *)u.u_ap;
322 register struct file *fp;
323 struct uio auio;
324 struct iovec aiov;
325 struct mbuf *from;
326 int fromlen;
327
127f7d76
SL
328 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen,
329 sizeof (fromlen));
330 if (u.u_error)
cf012934 331 return;
cf012934
BJ
332 fp = getf(uap->s);
333 if (fp == 0)
334 return;
335 if (fp->f_type != DTYPE_SOCKET) {
336 u.u_error = ENOTSOCK;
337 return;
338 }
339 auio.uio_iov = &aiov;
340 auio.uio_iovcnt = 1;
341 aiov.iov_base = uap->buf;
342 aiov.iov_len = uap->len;
343 auio.uio_resid = uap->len;
344 auio.uio_segflg = 0;
345 auio.uio_offset = 0; /* XXX */
b32450f4 346 if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) {
cf012934
BJ
347 u.u_error = EFAULT;
348 return;
349 }
350 from = 0;
970108c7 351 u.u_error = soreceive(fp->f_socket, &from, &auio, uap->flags);
cf012934
BJ
352 if (u.u_error)
353 goto bad;
354 if (from == 0)
355 fromlen = 0;
356 else {
357 if (fromlen > from->m_len)
358 fromlen = from->m_len;
127f7d76
SL
359 u.u_error = copyout(mtod(from, caddr_t), uap->from,
360 (u_int)fromlen);
361 if (u.u_error)
cf012934 362 goto bad;
cf012934 363 }
127f7d76
SL
364 u.u_error = copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr,
365 sizeof (fromlen));
366 if (u.u_error)
cf012934 367 goto bad;
cf012934
BJ
368 u.u_r.r_val1 = uap->len - auio.uio_resid;
369bad:
370 if (from)
371 m_freem(from);
cf012934
BJ
372}
373
374recv()
375{
376 register struct a {
377 int s;
378 caddr_t buf;
379 int len;
380 int flags;
381 } *uap = (struct a *)u.u_ap;
382 register struct file *fp;
383 struct uio auio;
384 struct iovec aiov;
385
386 fp = getf(uap->s);
cc15ab5d
BJ
387 if (fp == 0)
388 return;
4147b3f6 389 if (fp->f_type != DTYPE_SOCKET) {
cc15ab5d
BJ
390 u.u_error = ENOTSOCK;
391 return;
392 }
a6b6f679
BJ
393 auio.uio_iov = &aiov;
394 auio.uio_iovcnt = 1;
cf012934
BJ
395 aiov.iov_base = uap->buf;
396 aiov.iov_len = uap->len;
397 auio.uio_resid = uap->len;
a6b6f679
BJ
398 auio.uio_segflg = 0;
399 auio.uio_offset = 0; /* XXX */
b32450f4 400 if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) {
cc15ab5d
BJ
401 u.u_error = EFAULT;
402 return;
403 }
b32450f4
BJ
404 u.u_error =
405 soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags);
cf012934
BJ
406 u.u_r.r_val1 = uap->len - auio.uio_resid;
407}
408
409sendmsg()
410{
411
412 u.u_error = EINVAL;
413}
414
415recvmsg()
416{
417
418 u.u_error = EINVAL;
419}
420
421shutdown()
422{
6ef233bf
SL
423 struct a {
424 int s;
425 int how;
426 } *uap = (struct a *)u.u_ap;
427 struct file *fp;
cf012934 428
6ef233bf
SL
429 fp = getf(uap->s);
430 if (fp == 0)
431 return;
432 if (fp->f_type != DTYPE_SOCKET) {
433 u.u_error = ENOTSOCK;
434 return;
435 }
436 u.u_error = soshutdown(fp->f_socket, uap->how);
cf012934
BJ
437}
438
66f52238
SL
439setsockopt()
440{
441 struct a {
442 int s;
443 int level;
444 int name;
445 caddr_t val;
446 int valsize;
447 } *uap = (struct a *)u.u_ap;
448 struct file *fp;
449 struct mbuf *m;
450
451 fp = getf(uap->s);
452 if (fp == 0)
453 return;
454 if (fp->f_type != DTYPE_SOCKET) {
455 u.u_error = ENOTSOCK;
456 return;
457 }
458 if (uap->valsize > MLEN) {
459 u.u_error = EINVAL;
460 return;
461 }
462 m = m_get(M_WAIT, MT_SOOPTS);
463 if (m == 0) {
464 u.u_error = ENOBUFS;
465 return;
466 }
467 u.u_error = copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
468 if (u.u_error)
469 goto bad;
470 m->m_len = uap->valsize;
471 u.u_error = sosetopt(fp->f_socket, uap->level, uap->name, m);
472bad:
473 (void) m_free(m);
474}
475
476getsockopt()
477{
478 struct a {
479 int s;
480 int level;
481 int name;
482 caddr_t val;
483 int *avalsize;
484 } *uap = (struct a *)u.u_ap;
485 struct file *fp;
486 struct mbuf *m;
487 int valsize;
488
489 fp = getf(uap->s);
490 if (fp == 0)
491 return;
492 if (fp->f_type != DTYPE_SOCKET) {
493 u.u_error = ENOTSOCK;
494 return;
495 }
496 u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
497 sizeof (valsize));
498 if (u.u_error)
499 return;
500 if (useracc((caddr_t)uap->val, (u_int)valsize, B_WRITE) == 0) {
501 u.u_error = EFAULT;
502 return;
503 }
504 m = m_get(M_WAIT, MT_SOOPTS);
505 if (m == 0) {
506 u.u_error = ENOBUFS;
507 return;
508 }
509 u.u_error = sogetopt(fp->f_socket, uap->level, uap->name, m);
510 if (u.u_error)
511 goto bad;
512 if (valsize > m->m_len)
513 valsize = m->m_len;
514 u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
515 if (u.u_error)
516 goto bad;
517 u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize,
518 sizeof (valsize));
519bad:
520 (void) m_free(m);
521}
522
cf012934
BJ
523pipe()
524{
525 register struct file *rf, *wf;
526 struct socket *rso, *wso;
527 int r;
528
4f083fd7
SL
529 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0,
530 (struct socketopt *)0);
2b4b57cd
BJ
531 if (u.u_error)
532 return;
4f083fd7
SL
533 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0,
534 (struct socketopt *)0);
cf012934
BJ
535 if (u.u_error)
536 goto free;
537 rf = falloc();
538 if (rf == NULL)
539 goto free2;
540 r = u.u_r.r_val1;
541 rf->f_flag = FREAD;
542 rf->f_type = DTYPE_SOCKET;
543 rf->f_socket = rso;
544 wf = falloc();
545 if (wf == NULL)
546 goto free3;
547 wf->f_flag = FWRITE;
548 wf->f_type = DTYPE_SOCKET;
549 wf->f_socket = wso;
550 u.u_r.r_val2 = u.u_r.r_val1;
551 u.u_r.r_val1 = r;
552 if (piconnect(wso, rso) == 0)
553 goto free4;
554 return;
555free4:
556 wf->f_count = 0;
557 u.u_ofile[u.u_r.r_val2] = 0;
558free3:
559 rf->f_count = 0;
560 u.u_ofile[r] = 0;
561free2:
562 wso->so_state |= SS_NOFDREF;
563 sofree(wso);
564free:
565 rso->so_state |= SS_NOFDREF;
566 sofree(rso);
cc15ab5d 567}
a3076b07
BJ
568
569/*
570 * Get socket address.
571 */
572ssocketaddr()
573{
574 register struct a {
575 int fdes;
576 struct sockaddr *asa;
577 } *uap = (struct a *)u.u_ap;
578 register struct file *fp;
05d69517 579 register struct socket *so;
cf012934 580 struct mbuf *m;
a3076b07
BJ
581
582 fp = getf(uap->fdes);
583 if (fp == 0)
584 return;
4147b3f6 585 if (fp->f_type != DTYPE_SOCKET) {
a3076b07
BJ
586 u.u_error = ENOTSOCK;
587 return;
588 }
05d69517 589 so = fp->f_socket;
cce93e4b 590 m = m_getclr(M_WAIT, MT_SONAME);
05d69517 591 u.u_error =
cf012934 592 (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
05d69517 593 if (u.u_error)
cf012934 594 goto bad;
127f7d76
SL
595 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa,
596 sizeof (struct sockaddr));
cf012934
BJ
597bad:
598 m_freem(m);
599}
600
601sockname(aname, name, namelen)
602 struct mbuf **aname;
603 caddr_t name;
604 int namelen;
605{
606 register struct mbuf *m;
127f7d76 607 int error;
cf012934
BJ
608
609 if (namelen > MLEN)
610 return (EINVAL);
cce93e4b 611 m = m_get(M_WAIT, MT_SONAME);
cf012934 612 m->m_len = namelen;
127f7d76
SL
613 error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
614 if (error)
cf012934 615 (void) m_free(m);
127f7d76
SL
616 else
617 *aname = m;
618 return (error);
cf012934 619}