2 * Copyright (c) 2006 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sys/kern/kern_syslink.c,v 1.8 2007/04/16 17:40:13 dillon Exp $
37 * This module implements the syslink() system call and protocol which
38 * is used to glue clusters together as well as to interface userland
39 * devices and filesystems to the kernel.
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/alist.h>
51 #include <sys/thread.h>
53 #include <sys/sysctl.h>
54 #include <sys/sysproto.h>
55 #include <sys/syslink.h>
56 #include <sys/syslink_msg.h>
58 #include <sys/thread2.h>
61 * Red-Black trees organizing the syslink 'router' nodes and connections
67 RB_HEAD(slrouter_rb_tree, slrouter);
68 RB_HEAD(sldata_rb_tree, sldata);
69 RB_PROTOTYPE2(slrouter_rb_tree, slrouter, rbnode,
70 rb_slrouter_compare, sysid_t);
71 RB_PROTOTYPE2(sldata_rb_tree, sldata, rbnode,
72 rb_sldata_compare, int);
75 RB_ENTRY(slrouter) rbnode; /* list of routers */
76 struct sldata_rb_tree sldata_rb_root; /* connections to router */
77 sysid_t sysid; /* logical sysid of router */
78 int flags; /* flags passed on create */
79 int bits; /* accomodate connections */
80 int count; /* number of connections */
83 char label[SYSLINK_LABEL_SIZE];
87 * fileops interface. slbuf and sldata are also used in conjunction with a
88 * normal file descriptor.
92 int bufsize; /* must be a power of 2 */
93 int bufmask; /* (bufsize - 1) */
94 int rindex; /* tail-chasing FIFO indices */
99 RB_ENTRY(sldata) rbnode;
100 struct slrouter *router; /* organizing router */
103 struct file *xfp; /* external file pointer */
104 struct lock rlock; /* synchronizing lock */
105 struct lock wlock; /* synchronizing lock */
106 struct thread *rthread; /* xfp -> rbuf & process */
107 struct thread *wthread; /* wbuf -> xfp */
108 int flags; /* connection flags */
112 char label[SYSLINK_LABEL_SIZE];
116 * syslink kernel thread support flags
118 #define SLF_RQUIT 0x0001
119 #define SLF_WQUIT 0x0002
120 #define SLF_RDONE 0x0004
121 #define SLF_WDONE 0x0008
122 #define SLF_DESTROYED 0x8000
124 #define SYSLINK_BUFSIZE (128*1024)
126 static int rb_slrouter_compare(struct slrouter *r1, struct slrouter *r2);
127 static int rb_sldata_compare(struct sldata *d1, struct sldata *d2);
129 static int syslink_destroy(struct slrouter *slrouter);
130 static int syslink_add(struct slrouter *slrouter, int fd,
131 struct syslink_info *info, int *result);
132 static int syslink_rem(struct slrouter *slrouter, struct sldata *sldata,
133 struct syslink_info *info);
135 static int syslink_read(struct file *fp, struct uio *uio,
136 struct ucred *cred, int flags);
137 static int syslink_write(struct file *fp, struct uio *uio,
138 struct ucred *cred, int flags);
139 static int syslink_close(struct file *fp);
140 static int syslink_stat(struct file *fp, struct stat *sb, struct ucred *cred);
141 static int syslink_shutdown(struct file *fp, int how);
142 static int syslink_ioctl(struct file *fp, u_long cmd, caddr_t data,
144 static int syslink_poll(struct file *fp, int events, struct ucred *cred);
145 static int syslink_kqfilter(struct file *fp, struct knote *kn);
147 static void syslink_rthread(void *arg);
148 static void syslink_wthread(void *arg);
149 static void slbuf_alloc(struct slbuf *buf, int bytes);
150 static void slbuf_free(struct slbuf *buf);
151 static void sldata_rels(struct sldata *sldata);
152 static void slrouter_rels(struct slrouter *slrouter);
153 static int process_syslink_msg(struct sldata *sldata, struct syslink_msg *head);
154 static int syslink_validate(struct syslink_msg *head, int bytes);
156 RB_GENERATE2(slrouter_rb_tree, slrouter, rbnode,
157 rb_slrouter_compare, sysid_t, sysid);
158 RB_GENERATE2(sldata_rb_tree, sldata, rbnode,
159 rb_sldata_compare, int, linkid);
161 static struct fileops syslinkops = {
162 .fo_read = syslink_read,
163 .fo_write = syslink_write,
164 .fo_ioctl = syslink_ioctl,
165 .fo_poll = syslink_poll,
166 .fo_kqfilter = syslink_kqfilter,
167 .fo_stat = syslink_stat,
168 .fo_close = syslink_close,
169 .fo_shutdown = syslink_shutdown
172 MALLOC_DEFINE(M_SYSLINK, "syslink", "syslink manager");
174 static int syslink_enabled;
175 SYSCTL_INT(_kern, OID_AUTO, syslink_enabled,
176 CTLFLAG_RW, &syslink_enabled, 0, "Enable SYSLINK");
179 * Support declarations and compare function for our RB trees
181 static struct slrouter_rb_tree slrouter_rb_root;
184 rb_slrouter_compare(struct slrouter *r1, struct slrouter *r2)
186 if (r1->sysid < r2->sysid)
188 if (r1->sysid > r2->sysid)
194 rb_sldata_compare(struct sldata *d1, struct sldata *d2)
196 if (d1->linkid < d2->linkid)
198 if (d1->linkid > d2->linkid)
204 * Compare and callback functions for first-sysid and first-linkid searches.
207 syslink_cmd_locate_cmp(struct slrouter *slrouter, void *data)
209 struct syslink_info *info = data;
211 if (slrouter->sysid < info->sysid)
213 if (slrouter->sysid > info->sysid)
219 syslink_cmd_locate_callback(struct slrouter *slrouter, void *data)
221 struct syslink_info *info = data;
223 info->flags = slrouter->flags; /* also clears SLIF_ERROR */
224 bcopy(slrouter->label, info->label, SYSLINK_LABEL_SIZE);
230 syslink_cmd_find_cmp(struct sldata *sldata, void *data)
232 struct syslink_info *info = data;
234 if (sldata->linkid < info->linkid)
236 if (sldata->linkid > info->linkid)
242 syslink_cmd_find_callback(struct sldata *sldata, void *data)
244 struct syslink_info *info = data;
246 info->linkid = sldata->linkid;
247 info->flags = sldata->flags; /* also clears SLIF_ERROR */
248 bcopy(sldata->label, info->label, SYSLINK_LABEL_SIZE);
254 * Primary system call interface - associate a full-duplex stream
255 * (typically a pipe or a connected socket) with a sysid namespace,
256 * or create a direct link.
258 * syslink(int fd, int cmd, void *info, size_t *infosize)
261 sys_syslink(struct syslink_args *uap)
263 struct syslink_info info;
264 struct slrouter *slrouter = NULL;
265 struct sldata *sldata = NULL;
270 * System call is under construction and disabled by default.
271 * Superuser access is also required.
273 if (syslink_enabled == 0)
275 error = suser(curthread);
280 * Load and validate the info structure. Unloaded bytes are zerod out
282 bzero(&info, sizeof(info));
283 if ((unsigned)uap->bytes <= sizeof(info)) {
285 error = copyin(uap->info, &info, uap->bytes);
292 if (info.label[sizeof(info.label)-1] != 0)
300 case SYSLINK_CMD_CREATE:
302 * Create a new syslink router node. Set refs to prevent the
303 * router node from being destroyed. One ref is our temporary
304 * reference while the other is the SLIF_DESTROYED-interlocked
307 if (info.bits < 2 || info.bits > SYSLINK_ROUTER_MAXBITS)
309 slrouter = kmalloc(sizeof(struct slrouter), M_SYSLINK,
311 if (slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root, info.sysid)) {
312 kfree(slrouter, M_SYSLINK);
316 slrouter->sysid = info.sysid;
318 slrouter->bits = info.bits;
319 slrouter->flags = info.flags & SLIF_USERFLAGS;
320 slrouter->bitmap = alist_create(1 << info.bits, M_SYSLINK);
321 RB_INIT(&slrouter->sldata_rb_root);
322 RB_INSERT(slrouter_rb_tree, &slrouter_rb_root, slrouter);
324 case SYSLINK_CMD_DESTROY:
326 * Destroy a syslink router node. The physical node is
327 * not freed until our temporary reference is removed.
329 slrouter = slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root,
333 if ((slrouter->flags & SLIF_DESTROYED) == 0) {
334 slrouter->flags |= SLIF_DESTROYED;
335 /* SLIF_DESTROYED interlock */
336 slrouter_rels(slrouter);
337 error = syslink_destroy(slrouter);
338 /* still holding our private interlock */
342 case SYSLINK_CMD_LOCATE:
344 * Locate the first syslink router node >= info.sysid
346 info.flags |= SLIF_ERROR;
347 n = slrouter_rb_tree_RB_SCAN(
349 syslink_cmd_locate_cmp, syslink_cmd_locate_callback,
351 if (info.flags & SLIF_ERROR)
354 case SYSLINK_CMD_ADD:
355 slrouter = slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root, info.sysid);
357 (info.bits < 2 || info.bits > SYSLINK_ROUTER_MAXBITS)) {
359 } else if (slrouter && (slrouter->flags & SLIF_DESTROYED)) {
361 * Someone is trying to destroy this route node,
362 * no new adds please!
365 } else if (slrouter) {
367 error = syslink_add(slrouter, uap->fd, &info,
368 &uap->sysmsg_result);
373 case SYSLINK_CMD_REM:
374 slrouter = slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root,
378 sldata = sldata_rb_tree_RB_LOOKUP(&slrouter->sldata_rb_root, info.linkid);
381 error = syslink_rem(slrouter, sldata, &info);
389 case SYSLINK_CMD_FIND:
390 slrouter = slrouter_rb_tree_RB_LOOKUP(&slrouter_rb_root, info.sysid);
391 info.flags |= SLIF_ERROR;
394 n = sldata_rb_tree_RB_SCAN(
395 &slrouter->sldata_rb_root,
396 syslink_cmd_find_cmp, syslink_cmd_find_callback,
398 if (info.flags & SLIF_ERROR)
415 slrouter_rels(slrouter);
421 syslink_destroy_callback(struct sldata *sldata, void *data __unused)
424 if ((sldata->flags & SLF_RQUIT) == 0) {
425 sldata->flags |= SLF_RQUIT;
426 wakeup(&sldata->rbuf);
428 if ((sldata->flags & SLF_WQUIT) == 0) {
429 sldata->flags |= SLF_WQUIT;
430 wakeup(&sldata->wbuf);
437 * Shutdown all the connections going into this syslink.
439 * Try to wait for completion, but return after 1 second
444 syslink_destroy(struct slrouter *slrouter)
448 while (!RB_EMPTY(&slrouter->sldata_rb_root) && retries) {
449 RB_SCAN(sldata_rb_tree, &slrouter->sldata_rb_root, NULL,
450 syslink_destroy_callback, slrouter);
452 tsleep(&retries, 0, "syslnk", hz / 10);
454 if (RB_EMPTY(&slrouter->sldata_rb_root))
462 syslink_add(struct slrouter *slrouter, int fd, struct syslink_info *info,
465 struct sldata *sldata;
473 maxphys = 1 << slrouter->bits;
474 numphys = info->bits ? (1 << info->bits) : 1;
477 * Create a connection to the route node and allocate a physical ID.
478 * Physical ID 0 is reserved for the route node itself, and an all-1's
479 * ID is reserved as a broadcast address.
481 sldata = kmalloc(sizeof(struct sldata), M_SYSLINK, M_WAITOK|M_ZERO);
483 linkid = alist_alloc(slrouter->bitmap, numphys);
484 if (linkid == ALIST_BLOCK_NONE) {
485 kfree(sldata, M_SYSLINK);
490 * Insert the node, initializing enough fields to prevent things from
491 * being ripped out from under us before we have a chance to complete
494 sldata->linkid = linkid;
497 if (sldata_rb_tree_RB_LOOKUP(&slrouter->sldata_rb_root, linkid))
498 panic("syslink_add: free linkid wasn't free!");
499 RB_INSERT(sldata_rb_tree, &slrouter->sldata_rb_root, sldata);
502 * Complete initialization of the physical route node. Setting
503 * sldata->router activates the node.
505 lockinit(&sldata->rlock, "slread", 0, 0);
506 lockinit(&sldata->wlock, "slwrite", 0, 0);
510 * We create a direct syslink descriptor. Only the
511 * reader thread is needed.
513 error = falloc(curproc, &fp, &fd);
515 fp->f_type = DTYPE_SYSLINK;
516 fp->f_flag = FREAD | FWRITE;
517 fp->f_ops = &syslinkops;
519 slbuf_alloc(&sldata->rbuf, SYSLINK_BUFSIZE);
520 slbuf_alloc(&sldata->wbuf, SYSLINK_BUFSIZE);
521 /* two refs: reader thread and fp descriptor */
523 sldata->flags = SLF_WQUIT | SLF_WDONE;
524 lwkt_create(syslink_rthread, sldata,
525 &sldata->rthread, NULL,
527 fsetfd(curproc, fp, fd);
532 sldata->xfp = holdfp(curproc->p_fd, fd, -1);
533 if (sldata->xfp != NULL) {
534 slbuf_alloc(&sldata->rbuf, SYSLINK_BUFSIZE);
535 slbuf_alloc(&sldata->wbuf, SYSLINK_BUFSIZE);
536 /* two refs: reader thread and writer thread */
538 lwkt_create(syslink_rthread, sldata,
539 &sldata->rthread, NULL,
541 lwkt_create(syslink_wthread, sldata,
542 &sldata->wthread, NULL,
548 sldata->router = slrouter;
555 syslink_rem(struct slrouter *slrouter, struct sldata *sldata,
556 struct syslink_info *info)
558 int error = EINPROGRESS;
560 if ((sldata->flags & SLF_RQUIT) == 0) {
561 sldata->flags |= SLF_RQUIT;
562 wakeup(&sldata->rbuf);
565 if ((sldata->flags & SLF_WQUIT) == 0) {
566 sldata->flags |= SLF_WQUIT;
567 wakeup(&sldata->wbuf);
574 * This thread reads from an external descriptor into rbuf, then parses and
575 * dispatches syslink messages from rbuf.
579 syslink_rthread(void *arg)
581 struct sldata *sldata = arg;
582 struct slbuf *slbuf = &sldata->rbuf;
583 struct syslink_msg *head;
584 const int min_msg_size = SL_MIN_MESSAGE_SIZE;
586 while ((sldata->flags & SLF_RQUIT) == 0) {
592 * Calculate contiguous space available to read and read as
595 * If the entire buffer is used there's probably a format
596 * error of some sort and we terminate the link.
598 used = slbuf->windex - slbuf->rindex;
602 * Read some data, terminate the link if an error occurs or
603 * if EOF is encountered. xfp can be NULL, indicating that
604 * the data was injected by other means.
607 count = slbuf->bufsize -
608 (slbuf->windex & slbuf->bufmask);
609 if (count > slbuf->bufsize - used)
610 count = slbuf->bufsize - used;
613 error = fp_read(sldata->xfp,
615 (slbuf->windex & slbuf->bufmask),
616 count, &count, 0, UIO_SYSSPACE);
621 slbuf->windex += count;
624 tsleep(slbuf, 0, "fiford", 0);
628 * Process as many syslink messages as we can. The record
629 * length must be at least a minimal PAD record (8 bytes).
631 while (slbuf->windex - slbuf->rindex >= min_msg_size) {
634 head = (void *)(slbuf->buf +
635 (slbuf->rindex & slbuf->bufmask));
636 if (head->sm_bytes < min_msg_size) {
640 aligned_reclen = SLMSG_ALIGN(head->sm_bytes);
645 if ((slbuf->rindex & slbuf->bufmask) >
646 ((slbuf->rindex + aligned_reclen) & slbuf->bufmask)
653 * Insufficient data read
655 if (slbuf->windex - slbuf->rindex < aligned_reclen)
659 * Process non-pad messages. Non-pad messages have
660 * to be at least the size of the syslink_msg
663 * A PAD message's sm_cmd field contains 0.
666 if (head->sm_bytes < sizeof(*head)) {
670 error = process_syslink_msg(sldata, head);
675 slbuf->rindex += aligned_reclen;
682 * Mark us as done and deref sldata. Tell the writer to terminate as
685 sldata->flags |= SLF_RDONE;
686 if ((sldata->flags & SLF_WDONE) == 0) {
687 sldata->flags |= SLF_WQUIT;
688 wakeup(&sldata->wbuf);
690 wakeup(&sldata->rbuf);
691 wakeup(&sldata->wbuf);
696 * This thread takes outgoing syslink messages queued to wbuf and writes them
697 * to the descriptor. PAD is stripped. PAD is also added as required to
698 * conform to the outgoing descriptor's buffering requirements.
702 syslink_wthread(void *arg)
704 struct sldata *sldata = arg;
705 struct slbuf *slbuf = &sldata->wbuf;
706 struct syslink_msg *head;
709 while ((sldata->flags & SLF_WQUIT) == 0) {
716 used = slbuf->windex - slbuf->rindex;
717 if (used < SL_MIN_MESSAGE_SIZE)
720 head = (void *)(slbuf->buf +
721 (slbuf->rindex & slbuf->bufmask));
722 if (head->sm_bytes < SL_MIN_MESSAGE_SIZE) {
726 aligned_reclen = SLMSG_ALIGN(head->sm_bytes);
731 if ((slbuf->rindex & slbuf->bufmask) >
732 ((slbuf->rindex + aligned_reclen) & slbuf->bufmask)
739 * Insufficient data read
741 if (used < aligned_reclen)
745 * Write it out whether it is PAD or not.
746 * XXX re-PAD for output here.
748 error = fp_write(sldata->xfp, head,
752 if (error && error != ENOBUFS)
754 if (count != aligned_reclen) {
758 slbuf->rindex += aligned_reclen;
762 tsleep(slbuf, 0, "fifowt", 0);
764 sldata->flags |= SLF_WDONE;
770 slbuf_alloc(struct slbuf *slbuf, int bytes)
772 bzero(slbuf, sizeof(*slbuf));
773 slbuf->buf = kmalloc(bytes, M_SYSLINK, M_WAITOK);
774 slbuf->bufsize = bytes;
775 slbuf->bufmask = bytes - 1;
780 slbuf_free(struct slbuf *slbuf)
782 kfree(slbuf->buf, M_SYSLINK);
788 sldata_rels(struct sldata *sldata)
790 struct slrouter *slrouter;
792 if (--sldata->refs == 0) {
793 slrouter = sldata->router;
794 KKASSERT(slrouter != NULL);
796 RB_REMOVE(sldata_rb_tree,
797 &sldata->router->sldata_rb_root, sldata);
798 sldata->router = NULL;
799 slbuf_free(&sldata->rbuf);
800 slbuf_free(&sldata->wbuf);
801 kfree(sldata, M_SYSLINK);
802 slrouter_rels(slrouter);
808 slrouter_rels(struct slrouter *slrouter)
810 if (--slrouter->refs == 0 && RB_EMPTY(&slrouter->sldata_rb_root)) {
811 KKASSERT(slrouter->flags & SLIF_DESTROYED);
812 RB_REMOVE(slrouter_rb_tree, &slrouter_rb_root, slrouter);
813 alist_destroy(slrouter->bitmap, M_SYSLINK);
814 slrouter->bitmap = NULL;
815 kfree(slrouter, M_SYSLINK);
820 * fileops for an established syslink when the kernel is asked to create a
821 * descriptor (verses one being handed to it). No threads are created in
826 * Transfer zero or more messages from the kernel to userland. Only complete
827 * messages are returned. If the uio has insufficient space then EMSGSIZE
828 * is returned. The kernel feeds messages to wbuf so we use wlock (structures
829 * are relative to the kernel).
833 syslink_read(struct file *fp, struct uio *uio, struct ucred *cred, int flags)
835 struct sldata *sldata = fp->f_data;
836 struct slbuf *slbuf = &sldata->wbuf;
837 struct syslink_msg *head;
843 if (flags & O_FBLOCKING)
845 else if (flags & O_FNONBLOCKING)
847 else if (fp->f_flag & O_NONBLOCK)
852 lockmgr(&sldata->wlock, LK_EXCLUSIVE | LK_RETRY);
855 * Calculate the number of bytes we can transfer in one shot. Transfers
856 * do not wrap the FIFO.
858 contig = slbuf->bufsize - (slbuf->rindex & slbuf->bufmask);
860 bytes = slbuf->windex - slbuf->rindex;
863 if (sldata->flags & SLF_RDONE) {
871 tsleep(slbuf, 0, "fiford", 0);
877 * The uio must be able to accomodate the transfer.
879 if (uio->uio_resid < bytes) {
885 * Copy the data to userland and update rindex.
887 head = (void *)(slbuf->buf + (slbuf->rindex & slbuf->bufmask));
888 error = uiomove((caddr_t)head, bytes, uio);
890 slbuf->rindex += bytes;
896 lockmgr(&sldata->wlock, LK_RELEASE);
901 * Transfer zero or more messages from userland to the kernel. Only complete
902 * messages may be written. The kernel processes from rbuf so that is where
903 * we have to copy the messages.
907 syslink_write (struct file *fp, struct uio *uio, struct ucred *cred, int flags)
909 struct sldata *sldata = fp->f_data;
910 struct slbuf *slbuf = &sldata->rbuf;
911 struct syslink_msg *head;
917 if (flags & O_FBLOCKING)
919 else if (flags & O_FNONBLOCKING)
921 else if (fp->f_flag & O_NONBLOCK)
926 lockmgr(&sldata->rlock, LK_EXCLUSIVE | LK_RETRY);
929 * Calculate the maximum number of contiguous bytes that may be
930 * available. Caller is required to not wrap our FIFO.
932 contig = slbuf->bufsize - (slbuf->windex & slbuf->bufmask);
933 if (uio->uio_resid > contig) {
939 * Truncate based on actual unused space available in the FIFO. If
940 * the uio does not fit, block and loop.
943 bytes = slbuf->bufsize - (slbuf->windex - slbuf->rindex);
946 if (uio->uio_resid <= bytes)
948 if (sldata->flags & SLF_RDONE) {
956 tsleep(slbuf, 0, "fifowr", 0);
958 bytes = uio->uio_resid;
959 head = (void *)(slbuf->buf + (slbuf->windex & slbuf->bufmask));
960 error = uiomove((caddr_t)head, bytes, uio);
962 error = syslink_validate(head, bytes);
964 slbuf->windex += bytes;
968 lockmgr(&sldata->rlock, LK_RELEASE);
974 syslink_close (struct file *fp)
976 struct sldata *sldata;
979 if ((sldata->flags & SLF_RQUIT) == 0) {
980 sldata->flags |= SLF_RQUIT;
981 wakeup(&sldata->rbuf);
983 if ((sldata->flags & SLF_WQUIT) == 0) {
984 sldata->flags |= SLF_WQUIT;
985 wakeup(&sldata->wbuf);
994 syslink_stat (struct file *fp, struct stat *sb, struct ucred *cred)
1001 syslink_shutdown (struct file *fp, int how)
1008 syslink_ioctl (struct file *fp, u_long cmd, caddr_t data, struct ucred *cred)
1015 syslink_poll (struct file *fp, int events, struct ucred *cred)
1022 syslink_kqfilter(struct file *fp, struct knote *kn)
1028 * This routine is called from a route node's reader thread to process a
1029 * syslink message once it has been completely read and its size validated.
1033 process_syslink_msg(struct sldata *sldata, struct syslink_msg *head)
1035 kprintf("process syslink msg %08x\n", head->sm_cmd);
1040 * Validate that the syslink message header(s) are correctly sized.
1044 syslink_validate(struct syslink_msg *head, int bytes)
1046 const int min_msg_size = SL_MIN_MESSAGE_SIZE;
1051 * Message size and alignment
1053 if (bytes < min_msg_size)
1055 if (bytes & SL_ALIGNMASK)
1057 if (head->sm_cmd && bytes < sizeof(struct syslink_msg))
1061 * Buffer must contain entire record
1063 aligned_reclen = SLMSG_ALIGN(head->sm_bytes);
1064 if (bytes < aligned_reclen)
1066 bytes -= aligned_reclen;
1067 head = (void *)((char *)head + aligned_reclen);