|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1989, 1993
28: * The Regents of the University of California. All rights reserved.
29: * (c) UNIX System Laboratories, Inc.
30: * All or some portions of this file are derived from material licensed
31: * to the University of California by American Telephone and Telegraph
32: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
33: * the permission of UNIX System Laboratories, Inc.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: * 4. Neither the name of the University nor the names of its contributors
48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: *
63: * @(#)sys_generic.c 8.9 (Berkeley) 2/14/95
64: */
65: #include <sys/param.h>
66: #include <sys/systm.h>
1.1.1.2 ! root 67: #include <sys/malloc.h>
! 68: #include <sys/mbuf.h>
! 69: #include <sys/protosw.h>
! 70: #include <sys/socket.h>
! 71: #include <sys/socketvar.h>
! 72: #include <sys/errno.h>
! 73: #include <sys/ev.h>
! 74:
! 75: #include <net/if.h>
! 76: #include <net/route.h>
! 77:
! 78: #include <netinet/in.h>
! 79: #include <netinet/in_systm.h>
! 80: #include <netinet/ip.h>
! 81: #include <netinet/in_pcb.h>
! 82: #include <netinet/ip_var.h>
! 83: #include <netinet/tcp.h>
! 84: #include <netinet/tcp_fsm.h>
! 85: #include <netinet/tcp_seq.h>
! 86: #include <netinet/tcp_timer.h>
! 87: #include <netinet/tcp_var.h>
! 88: #include <netinet/tcpip.h>
! 89: #include <netinet/tcp_debug.h>
! 90: #include <sys/ev.h>
! 91:
1.1 root 92: #include <sys/filedesc.h>
93: #include <sys/ioctl.h>
94: #include <sys/file.h>
95: #include <sys/proc.h>
96: #include <sys/uio.h>
97: #include <sys/kernel.h>
98: #include <sys/stat.h>
1.1.1.2 ! root 99:
1.1 root 100: #if KTRACE
101: #include <sys/ktrace.h>
102: #endif
103:
104: #include <sys/mount.h>
105: #include <sys/protosw.h>
106: #include <sys/ev.h>
107: #include <sys/user.h>
108: #include <kern/kdebug.h>
109:
110: /*
111: * Read system call.
112: */
113: struct read_args {
114: int fd;
115: char *cbuf;
116: u_int nbyte;
117: };
118: /* ARGSUSED */
119: read(p, uap, retval)
120: struct proc *p;
121: register struct read_args *uap;
122: register_t *retval;
123: {
124: struct uio auio;
125: struct iovec aiov;
126:
127: aiov.iov_base = (caddr_t)uap->cbuf;
128: aiov.iov_len = uap->nbyte;
129: auio.uio_iov = &aiov;
130: auio.uio_iovcnt = 1;
131: auio.uio_rw = UIO_READ;
132: return (rwuio(p, uap->fd, &auio, UIO_READ, retval));
133: }
134:
135: struct readv_args {
136: int fd;
137: struct iovec *iovp;
138: u_int iovcnt;
139: };
140: readv(p, uap, retval)
141: struct proc *p;
142: register struct readv_args *uap;
143: int *retval;
144: {
145: struct uio auio;
146: register struct iovec *iov;
147: int error;
148: struct iovec aiov[UIO_SMALLIOV];
149:
150: if (uap->iovcnt > UIO_SMALLIOV) {
151: if (uap->iovcnt > UIO_MAXIOV)
152: return (EINVAL);
153: if ((iov = (struct iovec *)
154: kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
155: return (ENOMEM);
156: } else
157: iov = aiov;
158: auio.uio_iov = iov;
159: auio.uio_iovcnt = uap->iovcnt;
160: auio.uio_rw = UIO_READ;
161: error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
162: uap->iovcnt * sizeof (struct iovec));
163: if (!error)
164: error = rwuio(p, uap->fd, &auio, UIO_READ, retval);
165: if (uap->iovcnt > UIO_SMALLIOV)
166: kfree(iov, sizeof(struct iovec)*uap->iovcnt);
167: return (error);
168: }
169:
170: /*
171: * Write system call
172: */
173: struct write_args {
174: int fd;
175: char *cbuf;
176: u_int nbyte;
177: };
178: write(p, uap, retval)
179: struct proc *p;
180: register struct write_args *uap;
181: int *retval;
182: {
183: struct uio auio;
184: struct iovec aiov;
185:
186: aiov.iov_base = uap->cbuf;
187: aiov.iov_len = uap->nbyte;
188: auio.uio_iov = &aiov;
189: auio.uio_iovcnt = 1;
190: auio.uio_rw = UIO_WRITE;
191: return (rwuio(p, uap->fd, &auio, UIO_WRITE, retval));
192: }
193:
194: struct writev_args {
195: int fd;
196: struct iovec *iovp;
197: u_int iovcnt;
198: };
199: writev(p, uap, retval)
200: struct proc *p;
201: register struct writev_args *uap;
202: int *retval;
203: {
204: struct uio auio;
205: register struct iovec *iov;
206: int error;
207: struct iovec aiov[UIO_SMALLIOV];
208:
209: if (uap->iovcnt > UIO_SMALLIOV) {
210: if (uap->iovcnt > UIO_MAXIOV)
211: return (EINVAL);
212: if ((iov = (struct iovec *)
213: kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
214: return (ENOMEM);
215: } else
216: iov = aiov;
217: auio.uio_iov = iov;
218: auio.uio_iovcnt = uap->iovcnt;
219: auio.uio_rw = UIO_WRITE;
220: error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
221: uap->iovcnt * sizeof (struct iovec));
222: if (!error)
223: error = rwuio(p, uap->fd, &auio, UIO_WRITE, retval);
224: if (uap->iovcnt > UIO_SMALLIOV)
225: kfree(iov, sizeof(struct iovec)*uap->iovcnt);
226: return (error);
227: }
228:
229: rwuio(p, fdes, uio, rw, retval)
230: struct proc *p;
231: int fdes;
232: register struct uio *uio;
233: enum uio_rw rw;
234: int *retval;
235: {
236: register struct file *fp;
237: register struct iovec *iov;
238: int i, count, flag, error;
239:
240: if (error = fdgetf(p, fdes, &fp))
241: return (error);
242:
243: if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
244: return(EBADF);
245: }
246: uio->uio_resid = 0;
247: uio->uio_segflg = UIO_USERSPACE;
248: uio->uio_procp = p;
249: iov = uio->uio_iov;
250: for (i = 0; i < uio->uio_iovcnt; i++) {
251: if (iov->iov_len < 0) {
252: return(EINVAL);
253: }
254: uio->uio_resid += iov->iov_len;
255: if (uio->uio_resid < 0) {
256: return(EINVAL);
257: }
258: iov++;
259: }
260: count = uio->uio_resid;
261: if (rw == UIO_READ) {
262: if (error = (*fp->f_ops->fo_read)(fp, uio, fp->f_cred))
263: if (uio->uio_resid != count && (error == ERESTART ||
264: error == EINTR || error == EWOULDBLOCK))
265: error = 0;
266: } else {
267: if (error = (*fp->f_ops->fo_write)(fp, uio, fp->f_cred)) {
268: if (uio->uio_resid != count && (error == ERESTART ||
269: error == EINTR || error == EWOULDBLOCK))
270: error = 0;
271: if (error == EPIPE)
272: psignal(p, SIGPIPE);
273: }
274: }
275: *retval = count - uio->uio_resid;
276: return(error);
277: }
278:
279: /*
280: * Ioctl system call
281: */
282: struct ioctl_args {
283: int fd;
284: u_long com;
285: caddr_t data;
286: };
287: /* ARGSUSED */
288: ioctl(p, uap, retval)
289: struct proc *p;
290: register struct ioctl_args *uap;
291: register_t *retval;
292: {
293: register struct file *fp;
294: register u_long com;
295: register int error;
296: register u_int size;
297: caddr_t data, memp;
298: int tmp;
299: #define STK_PARAMS 128
300: char stkbuf[STK_PARAMS];
301:
302: if (error = fdgetf(p, uap->fd, &fp))
303: return (error);
304:
305: if ((fp->f_flag & (FREAD | FWRITE)) == 0)
306: return (EBADF);
307:
308: /*### LD 6/11/97 Hack Alert: this is to get AppleTalk to work
309: * while implementing an ATioctl system call
310: */
311: #if NETAT
312: {
313: extern int appletalk_inited;
314:
315: if (appletalk_inited && ((uap->com & 0x0000FFFF) == 0xff99)) {
316: #ifdef APPLETALK_DEBUG
317: kprintf("ioctl: special AppleTalk \n");
318: #endif
319: error = (*fp->f_ops->fo_ioctl)(fp, uap->com, uap->data, p);
320: return(error);
321: }
322: }
323:
324: #endif /* NETAT */
325:
326:
327: switch (com = uap->com) {
328: case FIONCLEX:
329: *fdflags(p, uap->fd) &= ~UF_EXCLOSE;
330: return (0);
331: case FIOCLEX:
332: *fdflags(p, uap->fd) |= UF_EXCLOSE;
333: return (0);
334: }
335:
336: /*
337: * Interpret high order word to find amount of data to be
338: * copied to/from the user's address space.
339: */
340: size = IOCPARM_LEN(com);
341: if (size > IOCPARM_MAX)
342: return (ENOTTY);
343: memp = NULL;
344: if (size > sizeof (stkbuf)) {
345: if ((memp = (caddr_t)kalloc(size)) == 0)
346: return(ENOMEM);
347: data = memp;
348: } else
349: data = stkbuf;
350: if (com&IOC_IN) {
351: if (size) {
352: error = copyin(uap->data, data, (u_int)size);
353: if (error) {
354: if (memp)
355: kfree(memp, size);
356: return (error);
357: }
358: } else
359: *(caddr_t *)data = uap->data;
360: } else if ((com&IOC_OUT) && size)
361: /*
362: * Zero the buffer so the user always
363: * gets back something deterministic.
364: */
365: bzero(data, size);
366: else if (com&IOC_VOID)
367: *(caddr_t *)data = uap->data;
368:
369: switch (com) {
370:
371: case FIONBIO:
372: if (tmp = *(int *)data)
373: fp->f_flag |= FNONBLOCK;
374: else
375: fp->f_flag &= ~FNONBLOCK;
376: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
377: break;
378:
379: case FIOASYNC:
380: if (tmp = *(int *)data)
381: fp->f_flag |= FASYNC;
382: else
383: fp->f_flag &= ~FASYNC;
384: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
385: break;
386:
387: case FIOSETOWN:
388: tmp = *(int *)data;
389: if (fp->f_type == DTYPE_SOCKET) {
390: ((struct socket *)fp->f_data)->so_pgid = tmp;
391: error = 0;
392: break;
393: }
394: if (tmp <= 0) {
395: tmp = -tmp;
396: } else {
397: struct proc *p1 = pfind(tmp);
398: if (p1 == 0) {
399: error = ESRCH;
400: break;
401: }
402: tmp = p1->p_pgrp->pg_id;
403: }
404: error = (*fp->f_ops->fo_ioctl)
405: (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
406: break;
407:
408: case FIOGETOWN:
409: if (fp->f_type == DTYPE_SOCKET) {
410: error = 0;
411: *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
412: break;
413: }
414: error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
415: *(int *)data = -*(int *)data;
416: break;
417:
418: default:
419: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
420: /*
421: * Copy any data to user, size was
422: * already set and checked above.
423: */
424: if (error == 0 && (com&IOC_OUT) && size)
425: error = copyout(data, uap->data, (u_int)size);
426: break;
427: }
428: if (memp)
429: kfree(memp, size);
430: return (error);
431: }
432:
433:
434: int selwait, nselcoll;
435:
436: /*
437: * Select system call.
438: */
439: struct select_args {
440: u_int nd;
441: fd_set *in;
442: fd_set *ou;
443: fd_set *ex;
444: struct timeval *tv;
445: };
446:
447: select(p, uap, retval)
448: register struct proc *p;
449: register struct select_args *uap;
450: register_t *retval;
451: {
452: fd_set ibits[3], obits[3];
453: struct timeval atv;
454: int s, ncoll, error = 0, timo;
455: u_int ni;
456: struct thread *th;
457: struct uthread *uth;
458:
459: th = current_thread();
460: uth = th->_uthread;
461:
462: bzero((caddr_t)ibits, sizeof(ibits));
463: bzero((caddr_t)obits, sizeof(obits));
464:
465: if (uap->nd > FD_SETSIZE)
466: return (EINVAL);
467: if (uap->nd > p->p_fd->fd_nfiles) {
468: /* forgiving; slightly wrong */
469: uap->nd = p->p_fd->fd_nfiles;
470: }
471: ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
472:
473: #define getbits(name, x) \
474: if (uap->name && (error = copyin((caddr_t)uap->name, \
475: (caddr_t)&ibits[x], ni))) \
476: goto done;
477: getbits(in, 0);
478: getbits(ou, 1);
479: getbits(ex, 2);
480: #undef getbits
481: if (uap->tv) {
482: error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
483: sizeof (atv));
484: if (error)
485: goto done;
486: if (itimerfix(&atv)) {
487: error = EINVAL;
488: goto done;
489: }
490: s = splhigh();
491: timeradd(&atv, &time, &atv);
492: timo = hzto(&atv);
493: splx(s);
494: } else
495: timo = 0;
496: retry:
497: ncoll = nselcoll;
498: p->p_flag |= P_SELECT;
499: error = selscan(p, ibits, obits, uap->nd, retval);
500: if (error || *retval)
501: goto done;
502: s = splhigh();
503: /* this should be timercmp(&time, &atv, >=) */
504: if (uap->tv && (time.tv_sec > atv.tv_sec ||
505: time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
506: splx(s);
507: goto done;
508: }
509: /*
510: * To effect a poll, the timeout argument should be
511: * non-nil, pointing to a zero-valued timeval structure.
512: */
513: if (uap->tv && (timo == 0)) {
514: splx(s);
515: goto done;
516: }
517: if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
518: splx(s);
519: goto retry;
520: }
521: p->p_flag &= ~P_SELECT;
522: error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
523: splx(s);
524: if (error == 0)
525: goto retry;
526: done:
527: p->p_flag &= ~P_SELECT;
528: /* select is not restarted after signals... */
529: if (error == ERESTART)
530: error = EINTR;
531: if (error == EWOULDBLOCK)
532: error = 0;
533: #define putbits(name, x) \
534: if (uap->name && (error2 = copyout((caddr_t)&obits[x], \
535: (caddr_t)uap->name, ni))) \
536: error = error2;
537: if (error == 0) {
538: int error2;
539:
540: putbits(in, 0);
541: putbits(ou, 1);
542: putbits(ex, 2);
543: #undef putbits
544: }
545: return (error);
546: }
547:
548: selscan(p, ibits, obits, nfd, retval)
549: struct proc *p;
550: fd_set *ibits, *obits;
551: int nfd;
552: register_t *retval;
553: {
554: register struct filedesc *fdp = p->p_fd;
555: register int msk, i, j, fd;
556: register fd_mask bits;
557: struct file *fp;
558: int n = 0;
559: static int flag[3] = { FREAD, FWRITE, 0 };
560:
561: for (msk = 0; msk < 3; msk++) {
562: for (i = 0; i < nfd; i += NFDBITS) {
563: bits = ibits[msk].fds_bits[i/NFDBITS];
564: while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
565: bits &= ~(1 << j);
566: fp = fdp->fd_ofiles[fd];
567: if (fp == NULL || (fdp->fd_ofileflags[fd] &
568: UF_RESERVED))
569: return (EBADF);
570: if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
571: FD_SET(fd, &obits[msk]);
572: n++;
573: }
574: }
575: }
576: }
577: *retval = n;
578: return (0);
579: }
580:
581: /*ARGSUSED*/
582: seltrue(dev, flag, p)
583: dev_t dev;
584: int flag;
585: struct proc *p;
586: {
587:
588: return (1);
589: }
590:
591: /*
592: * Record a select request.
593: */
594: void
595: selrecord(selector, sip)
596: struct proc *selector;
597: struct selinfo *sip;
598: {
599: int oldpri = splhigh();
600: thread_t my_thread = current_thread();
601: thread_t selthread;
602:
603: selthread = sip->si_thread;
604:
605: if (selthread == my_thread) {
606: splx(oldpri);
607: return;
608: }
609:
610: if (selthread && selthread->active &&
611: selthread->wait_event == (caddr_t)&selwait) {
612: sip->si_flags |= SI_COLL;
613: splx(oldpri);
614: }
615: else {
616: sip->si_thread = my_thread;
617: splx(oldpri);
618: thread_deallocate(selthread);
619: thread_reference(sip->si_thread);
620: }
621:
622: return;
623: }
624:
625: void
626: selwakeup(sip)
627: register struct selinfo *sip;
628: {
629: register thread_t the_thread = (thread_t)sip->si_thread;
630: int oldpri;
631:
632: if (the_thread == 0)
633: return;
634:
635: if (sip->si_flags & SI_COLL) {
636: nselcoll++;
637: sip->si_flags &= ~SI_COLL;
638: wakeup((caddr_t)&selwait);
639: }
640:
641: oldpri = splhigh();
642:
643: if (the_thread->active) {
644: /* protect p_flag minimally at splsched() */
645: if (the_thread->wait_event == &selwait)
646: clear_wait(the_thread, THREAD_AWAKENED, TRUE);
647: if (the_thread->task->proc)
648: the_thread->task->proc->p_flag &= ~P_SELECT;
649: }
650:
651: thread_deallocate_interrupt(the_thread);
652:
653: sip->si_thread = 0;
654:
655: splx(oldpri);
656:
657: }
658:
659: void selthreadclear(sip)
660: register struct selinfo *sip;
661: {
662:
663: if (sip->si_thread)
664: thread_deallocate_interrupt(sip->si_thread);
665:
666: }
667:
668:
669: /*
670: * called upon socket close. deque and free all events for
671: * the socket
672: */
673: evsofree(struct socket *sp)
674: {
675: struct eventqelt *eqp, *next;
676:
677: if (sp == NULL) return;
678:
679: for (eqp = sp->so_evlist.tqh_first; eqp != NULL; eqp = next) {
680: next = eqp->ee_slist.tqe_next;
681: evprocdeque(eqp->ee_proc, eqp); // remove from proc q if there
682: TAILQ_REMOVE(&sp->so_evlist, eqp, ee_slist); // remove from socket q
683: FREE(eqp, M_TEMP);
684: }
685: }
686:
687:
688: #define DBG_EVENT 0x10
689:
690: #define DBG_POST 0x10
691: #define DBG_WATCH 0x11
692: #define DBG_WAIT 0x12
693: #define DBG_MOD 0x13
694: #define DBG_EWAKEUP 0x14
695:
696: #define DBG_MISC_POST MISCDBG_CODE(DBG_EVENT,DBG_POST)
697: #define DBG_MISC_WATCH MISCDBG_CODE(DBG_EVENT,DBG_WATCH)
698: #define DBG_MISC_WAIT MISCDBG_CODE(DBG_EVENT,DBG_WAIT)
699: #define DBG_MISC_MOD MISCDBG_CODE(DBG_EVENT,DBG_MOD)
700: #define DBG_MISC_EWAKEUP MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP)
701:
702:
703:
704: /*
705: * enque this event if it's not already queued. wakeup
706: the proc if we do queue this event to it.
707: */
708: evprocenque(struct eventqelt *eqp)
709: {
710: struct proc *p;
711:
712: assert(eqp);
713: if (eqp->ee_flags & EV_QUEUED) {
714: return;
715: }
716: eqp->ee_flags |= EV_QUEUED;
717: eqp->ee_eventmask = 0; // disarm
718: p = eqp->ee_proc;
719: TAILQ_INSERT_TAIL(&p->p_evlist, eqp, ee_plist);
720: KERNEL_DEBUG(DBG_MISC_EWAKEUP,0,0,0,eqp,0);
721: wakeup(&p->p_evlist);
722: }
723:
724: /*
725: * given either a sockbuf or a socket run down the
726: * event list and queue ready events found
727: */
728: postevent(struct socket *sp, struct sockbuf *sb, int event)
729: {
730: int mask;
731: struct eventqelt *evq;
1.1.1.2 ! root 732: register struct tcpcb *tp;
! 733:
1.1 root 734:
735: if (sb) sp = sb->sb_so;
736: if (!sp || sp->so_evlist.tqh_first == NULL) return;
737:
738: KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_START, 0,0,0,0,0);
739:
740: for (evq = sp->so_evlist.tqh_first;
741: evq != NULL; evq = evq->ee_slist.tqe_next) {
742:
743: mask = 0;
744:
745: /* ready for reading:
746: - byte cnt >= receive low water mark
747: - read-half of conn closed
748: - conn pending for listening sock
749: - socket error pending
750:
751: ready for writing
752: - byte cnt avail >= send low water mark
753: - write half of conn closed
754: - socket error pending
755: - non-blocking conn completed successfully
756:
757: exception pending
758: - out of band data
759: - sock at out of band mark
760:
761: */
762: switch (event & EV_DMASK) {
763:
764: case EV_RWBYTES:
765: case EV_OOB:
766: if (event & EV_OOB) {
767: if ((evq->ee_eventmask & EV_EX)) {
768: if (sp->so_oobmark || ((sp->so_state & SS_RCVATMARK))) {
769: mask |= EV_EX|EV_OOB;
770: }
771: }
772: }
773: if (event & EV_RWBYTES) {
774: if ((evq->ee_eventmask & EV_RE) && soreadable(sp)) {
1.1.1.2 ! root 775: if ((sp->so_type == SOCK_STREAM) && (sp->so_error == ECONNREFUSED) ||
! 776: (sp->so_error == ECONNRESET)) {
! 777: tp = sototcpcb(sp);
! 778: if (tp->t_state == TCPS_CLOSED) {
! 779: mask |= EV_RE|EV_RESET;
! 780: break;
! 781: }
! 782: }
! 783: if (sp->so_state & SS_CANTRCVMORE) {
! 784: mask |= EV_RE|EV_FIN;
! 785: break;
! 786: }
1.1 root 787: mask |= EV_RE;
788: evq->ee_req.er_rcnt = sp->so_rcv.sb_cc;
789: }
790:
791: if ((evq->ee_eventmask & EV_WR) && sowriteable(sp)) {
1.1.1.2 ! root 792: if ((sp->so_type == SOCK_STREAM) &&(sp->so_error == ECONNREFUSED) ||
! 793: (sp->so_error == ECONNRESET)) {
! 794: tp = sototcpcb(sp);
! 795: if (tp->t_state == TCPS_CLOSED) {
! 796: mask |= EV_WR|EV_RESET;
! 797: break;
! 798: }
! 799: }
1.1 root 800: mask |= EV_WR;
801: evq->ee_req.er_wcnt = sbspace(&sp->so_snd);
802: }
803: }
804: break;
805:
806: case EV_RCONN:
807: if ((evq->ee_eventmask & EV_RE)) {
808: evq->ee_req.er_rcnt = sp->so_qlen + 1; // incl this one
809: mask |= EV_RE|EV_RCONN;
810: }
811: break;
812:
813: case EV_WCONN:
814: if ((evq->ee_eventmask & EV_WR)) {
815: mask |= EV_WR|EV_WCONN;
816: }
817: break;
818:
819: case EV_RCLOSED:
820: if ((evq->ee_eventmask & EV_RE)) {
821: mask |= EV_RE|EV_RCLOSED;
822: break;
823: }
824:
825: case EV_WCLOSED:
826: if ((evq->ee_eventmask & EV_WR)) {
827: mask |= EV_WR|EV_WCLOSED;
828: break;
829: }
830:
831: case EV_FIN:
1.1.1.2 ! root 832: if (evq->ee_eventmask & EV_RE) {
! 833: mask |= EV_RE|EV_FIN;
1.1 root 834: break;
835: }
836:
837: case EV_RESET:
1.1.1.2 ! root 838: if (evq->ee_eventmask & EV_RE) {
! 839: mask |= EV_RE|EV_RESET;
! 840: }
! 841: if (evq->ee_eventmask & EV_WR) {
! 842: mask |= EV_WR|EV_RESET;
1.1 root 843: }
1.1.1.2 ! root 844: break;
1.1 root 845:
846: default:
847: return;
848: } /* switch */
849:
850: if (mask) {
851: evq->ee_req.er_eventbits |= mask;
852: evprocenque(evq);
853: }
854: }
855: KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_END, 0,0,0,0,0);
856: }
857:
858: /*
859: * remove and return the first event (eqp=NULL) or a specific
860: * event, or return NULL if no events found
861: */
862: struct eventqelt *
863: evprocdeque(struct proc *p, struct eventqelt *eqp)
864: {
865:
866:
867: if (eqp && ((eqp->ee_flags & EV_QUEUED) == NULL))
868: return(NULL);
869: if (p->p_evlist.tqh_first == NULL)
870: return(NULL);
871: if (eqp == NULL) { // remove first
872: eqp = p->p_evlist.tqh_first;
873: }
874: TAILQ_REMOVE(&p->p_evlist, eqp, ee_plist);
875: eqp->ee_flags &= ~EV_QUEUED;
876: return(eqp);
877: }
878:
879: struct evwatch_args {
880: struct eventreq *u_req;
881: int u_eventmask;
882: };
883:
884:
885: /*
886: * watchevent system call. user passes us an event to watch
887: * for. we malloc an event object, initialize it, and queue
888: * it to the open socket. when the event occurs, postevent()
889: * will enque it back to our proc where we can retrieve it
890: * via waitevent().
891: *
892: * should this prevent duplicate events on same socket?
893: */
894: int
895: watchevent(p, uap, retval)
896: struct proc *p;
897: struct evwatch_args *uap;
898: register_t *retval;
899: {
900: struct eventqelt *eqp = (struct eventqelt *)0;
901: struct eventqelt *np;
902: struct eventreq *erp;
903: struct file *fp;
904: struct socket *sp;
905: int error;
906:
907: // get a qelt and fill with users req
908: MALLOC(eqp, struct eventqelt *, sizeof(struct eventqelt), M_TEMP, M_WAITOK);
909: if (!eqp) panic("can't MALLOC eqp");
910: erp = &eqp->ee_req;
911: // get users request pkt
912: if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
913: sizeof(struct eventreq))) {
914: FREE(eqp, M_TEMP);
915: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
916: return(error);
917: }
918: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_START, 0,
919: erp->er_handle,uap->u_eventmask,eqp,0);
920: // validate, freeing qelt if errors
921: error = 0;
922: if (erp->er_type != EV_FD) {
923: error = EINVAL;
924: } else if (erp->er_handle < 0) {
925: error = EBADF;
926: } else if (erp->er_handle > p->p_fd->fd_nfiles) {
927: error = EBADF;
928: } else if ((fp = *fdfile(p, erp->er_handle)) == NULL) {
929: error = EBADF;
930: } else if (fp->f_type != DTYPE_SOCKET) {
931: error = EINVAL;
932: }
933: if (error) {
934: FREE(eqp,M_TEMP);
935: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
936: return(error);
937: }
938:
939: erp->er_rcnt = erp->er_wcnt = erp->er_eventbits = 0;
940: eqp->ee_proc = p;
941: eqp->ee_eventmask = uap->u_eventmask & EV_MASK;
942: eqp->ee_flags = 0;
943:
944: sp = (struct socket *)fp->f_data;
945: assert(sp != NULL);
1.1.1.2 ! root 946: eqp->ee_sp = sp;
1.1 root 947:
948: // only allow one watch per file per proc
949: for (np = sp->so_evlist.tqh_first; np != NULL; np = np->ee_slist.tqe_next) {
950: if (np->ee_proc == p) {
951: FREE(eqp,M_TEMP);
952: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
953: return(EINVAL);
954: }
955: }
956:
957: TAILQ_INSERT_TAIL(&sp->so_evlist, eqp, ee_slist);
958: postevent(sp, 0, EV_RWBYTES); // catch existing events
959: KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
960: return(0);
961: }
962:
963: struct evwait_args {
964: struct eventreq *u_req;
965: struct timeval *tv;
966: };
967:
968: /*
969: * waitevent system call.
970: * grabs the next waiting event for this proc and returns
971: * it. if no events, user can request to sleep with timeout
972: * or poll mode (tv=NULL);
973: */
974: int
975: waitevent(p, uap, retval)
976: struct proc *p;
977: struct evwait_args *uap;
978: register_t *retval;
979: {
980: int error = 0;
981: struct eventqelt *eqp;
982: int timo;
983: struct timeval atv;
984: int s;
985:
986: if (uap->tv) {
987: error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
988: sizeof (atv));
989: if (error)
990: return(error);
991: if (itimerfix(&atv)) {
992: error = EINVAL;
993: return(error);
994: }
995: s = splhigh();
996: timeradd(&atv, &time, &atv);
997: timo = hzto(&atv);
998: splx(s);
999: } else
1000: timo = 0;
1001:
1002: KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_START, 0,0,0,0,0);
1003:
1004: retry:
1005: s = splhigh();
1006: if ((eqp = evprocdeque(p,NULL)) != NULL) {
1007: splx(s);
1008: error = copyout((caddr_t)&eqp->ee_req, (caddr_t)uap->u_req,
1009: sizeof(struct eventreq));
1010: KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,
1011: eqp->ee_req.er_handle,eqp->ee_req.er_eventbits,eqp,0);
1012: return(error);
1013: } else {
1014: if (uap->tv && (timo == 0)) {
1015: splx(s);
1016: *retval = 1; // poll failed
1017: return(error);
1018: }
1019:
1020: KERNEL_DEBUG(DBG_MISC_WAIT, 1,0,0,0,0);
1021: error = tsleep(&p->p_evlist, PSOCK | PCATCH, "waitevent", timo);
1022: KERNEL_DEBUG(DBG_MISC_WAIT, 0,0,2,p->p_evlist.tqh_first,0);
1023: splx(s);
1024: if (error == 0)
1025: goto retry;
1026: if (error == ERESTART)
1027: error = EINTR;
1028: if (error == EWOULDBLOCK) {
1029: *retval = 1;
1030: error = 0;
1031: }
1032: }
1033: KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,0,0,0,0);
1034: return(error);
1035: }
1036:
1037: struct modwatch_args {
1038: struct eventreq *u_req;
1039: int u_eventmask;
1040: };
1041:
1042: /*
1043: * modwatch system call. user passes in event to modify.
1044: * if we find it we reset the event bits and que/deque event
1045: * it needed.
1046: */
1047: int
1048: modwatch(p, uap, retval)
1049: struct proc *p;
1050: struct modwatch_args *uap;
1051: register_t *retval;
1052: {
1053: struct eventreq er;
1054: struct eventreq *erp = &er;
1055: struct eventqelt *evq;
1056: int error;
1057: struct file *fp;
1058: struct socket *sp;
1059: int flag;
1060:
1061:
1062: // get users request pkt
1063: if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
1064: sizeof(struct eventreq))) return(error);
1065:
1066: if (erp->er_type != EV_FD) return(EINVAL);
1067: if (erp->er_handle < 0) return(EBADF);
1068: if (erp->er_handle > p->p_fd->fd_nfiles) return(EBADF);
1069: if ((fp = *fdfile(p, erp->er_handle)) == NULL)
1070: return(EBADF);
1071: if (fp->f_type != DTYPE_SOCKET) return(EINVAL); // for now must be sock
1072: sp = (struct socket *)fp->f_data;
1073: assert(sp != NULL);
1074:
1075: // locate event if possible
1076: for (evq = sp->so_evlist.tqh_first;
1077: evq != NULL; evq = evq->ee_slist.tqe_next) {
1078: if (evq->ee_proc == p) break;
1079: }
1080: if (evq == NULL) {
1081: return(EINVAL);
1082: }
1083:
1084:
1085: if (uap->u_eventmask == EV_RM) {
1086: evprocdeque(p, evq);
1087: TAILQ_REMOVE(&sp->so_evlist, evq, ee_slist);
1088: FREE(evq, M_TEMP);
1089: return(0);
1090: }
1091:
1092: switch (uap->u_eventmask & EV_MASK) {
1093:
1094: case 0:
1095: flag = 0;
1096: break;
1097:
1098: case EV_RE:
1099: case EV_WR:
1100: case EV_RE|EV_WR:
1101: flag = EV_RWBYTES;
1102: break;
1103:
1104: case EV_EX:
1105: flag = EV_OOB;
1106: break;
1107:
1108: case EV_EX|EV_RE:
1109: case EV_EX|EV_WR:
1110: case EV_EX|EV_RE|EV_WR:
1111: flag = EV_OOB|EV_RWBYTES;
1112: break;
1113:
1114: default:
1115: return(EINVAL);
1116: }
1117:
1118: evq->ee_eventmask = uap->u_eventmask & EV_MASK;
1119: evprocdeque(p, evq);
1120: evq->ee_req.er_eventbits = 0;
1121: postevent(sp, 0, flag);
1122: return(0);
1123: }
1124:
1125:
1126:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.