source: rtems/cpukit/libnetworking/rtems/rtems_syscall.c @ f87ede5

4.115
Last change on this file since f87ede5 was f87ede5, checked in by Sebastian Huber <sebastian.huber@…>, on 01/15/15 at 13:13:19

libnetworking: Fix close of active sockets

Send a special event to notify tasks waiting for a socket state change
in case this socket gets closed. This prevents a use after free.

Close #785.

  • Property mode set to 100644
File size: 17.2 KB
Line 
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <string.h>
6#include <stdarg.h>
7/* #include <stdlib.h> */
8#include <stdio.h>
9#include <errno.h>
10
11#include <rtems.h>
12#include <rtems/libio_.h>
13#include <rtems/error.h>
14#include <rtems/rtems_bsdnet.h>
15
16#include <errno.h>
17#include <sys/types.h>
18#include <sys/param.h>
19#include <sys/mbuf.h>
20#include <sys/socket.h>
21#include <sys/socketvar.h>
22#include <sys/protosw.h>
23#include <sys/proc.h>
24#include <sys/fcntl.h>
25#include <sys/filio.h>
26#include <sys/sysctl.h>
27
28#include <net/if.h>
29#include <net/route.h>
30
31/*
32 *  Since we are "in the kernel", these do not get prototyped in sys/socket.h
33 */
34ssize_t send(int, const void *, size_t, int);
35ssize_t recv(int, void *, size_t, int);
36
37/*
38 * Hooks to RTEMS I/O system
39 */
40static const rtems_filesystem_file_handlers_r socket_handlers;
41
42/*
43 * Convert an RTEMS file descriptor to a BSD socket pointer.
44 */
45struct socket *
46rtems_bsdnet_fdToSocket (int fd)
47{
48  rtems_libio_t *iop;
49
50  /* same as rtems_libio_check_fd(_fd) but different return */
51  if ((uint32_t)fd >= rtems_libio_number_iops) {
52    errno = EBADF;
53    return NULL;
54  }
55  iop = &rtems_libio_iops[fd];
56
57  /* same as rtems_libio_check_is_open(iop) but different return */
58  if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) {
59    errno = EBADF;
60    return NULL;
61  }
62
63  if (iop->pathinfo.handlers != &socket_handlers) {
64    errno = ENOTSOCK;
65    return NULL;
66  }
67
68  if (iop->data1 == NULL)
69    errno = EBADF;
70  return iop->data1;
71}
72
73/*
74 * Create an RTEMS file descriptor for a socket
75 */
76static int
77rtems_bsdnet_makeFdForSocket (void *so)
78{
79  rtems_libio_t *iop;
80  int fd;
81
82  iop = rtems_libio_allocate();
83  if (iop == 0)
84      rtems_set_errno_and_return_minus_one( ENFILE );
85
86  fd = iop - rtems_libio_iops;
87  iop->flags |= LIBIO_FLAGS_WRITE | LIBIO_FLAGS_READ;
88  iop->data0 = fd;
89  iop->data1 = so;
90  iop->pathinfo.handlers = &socket_handlers;
91  iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
92  rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo);
93  return fd;
94}
95
96/*
97 * Package system call argument into mbuf.
98 */
99static int
100sockargstombuf (struct mbuf **mp, const void *buf, int buflen, int type)
101{
102        struct mbuf *m;
103
104        if ((u_int)buflen > MLEN)
105                return (EINVAL);
106        m = m_get(M_WAIT, type);
107        if (m == NULL)
108                return (ENOBUFS);
109        m->m_len = buflen;
110        memcpy (mtod(m, caddr_t), buf, buflen);
111        *mp = m;
112        if (type == MT_SONAME) {
113                struct sockaddr *sa;
114                sa = mtod(m, struct sockaddr *);
115                sa->sa_len = buflen;
116        }
117        return 0;
118}
119
120/*
121 *********************************************************************
122 *                       BSD-style entry points                      *
123 *********************************************************************
124 */
125int
126socket (int domain, int type, int protocol)
127{
128        int fd;
129        int error;
130        struct socket *so;
131
132        rtems_bsdnet_semaphore_obtain ();
133        error = socreate(domain, &so, type, protocol, NULL);
134        if (error == 0) {
135                fd = rtems_bsdnet_makeFdForSocket (so);
136                if (fd < 0)
137                        soclose (so);
138        }
139        else {
140                errno = error;
141                fd = -1;
142        }
143        rtems_bsdnet_semaphore_release ();
144        return fd;
145}
146
147int
148bind (int s, struct sockaddr *name, int namelen)
149{
150        int error;
151        int ret = -1;
152        struct socket *so;
153        struct mbuf *nam;
154
155        rtems_bsdnet_semaphore_obtain ();
156        if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) {
157                error = sockargstombuf (&nam, name, namelen, MT_SONAME);
158                if (error == 0) {
159                        error = sobind (so, nam);
160                        if (error == 0)
161                                ret = 0;
162                        else
163                                errno = error;
164                        m_freem (nam);
165                }
166                else {
167                        errno = error;
168                }
169        }
170        rtems_bsdnet_semaphore_release ();
171        return ret;
172}
173
174int
175connect (int s, struct sockaddr *name, int namelen)
176{
177        int error;
178        int ret = -1;
179        struct socket *so;
180        struct mbuf *nam;
181
182        rtems_bsdnet_semaphore_obtain ();
183        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
184                rtems_bsdnet_semaphore_release ();
185                return -1;
186        }
187        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
188                errno = EALREADY;
189                rtems_bsdnet_semaphore_release ();
190                return -1;
191        }
192        error = sockargstombuf (&nam, name, namelen, MT_SONAME);
193        if (error) {
194                errno = error;
195                rtems_bsdnet_semaphore_release ();
196                return -1;
197        }
198        error = soconnect (so, nam);
199        if (error)
200                goto bad;
201        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
202                m_freem(nam);
203                errno = EINPROGRESS;
204                rtems_bsdnet_semaphore_release ();
205                return -1;
206        }
207        error = so->so_error;
208        while (error == 0 && (so->so_state & SS_ISCONNECTING)) {
209                error = soconnsleep (so);
210                if (error)
211                        break;
212                error = so->so_error;
213                so->so_error = 0;
214        }
215    bad:
216        if (error != ENXIO)
217                so->so_state &= ~SS_ISCONNECTING;
218        m_freem (nam);
219        if (error)
220                errno = error;
221        else
222                ret = 0;
223        rtems_bsdnet_semaphore_release ();
224        return ret;
225}
226
227int
228listen (int s, int backlog)
229{
230        int error;
231        int ret = -1;
232        struct socket *so;
233
234        rtems_bsdnet_semaphore_obtain ();
235        if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) {
236                error = solisten (so, backlog);
237                if (error == 0)
238                        ret = 0;
239                else
240                        errno = error;
241        }
242        rtems_bsdnet_semaphore_release ();
243        return ret;
244}
245
246int
247accept (int s, struct sockaddr *name, int *namelen)
248{
249        int fd;
250        struct socket *head, *so;
251        struct mbuf *nam;
252        int error;
253
254        rtems_bsdnet_semaphore_obtain ();
255        if ((head = rtems_bsdnet_fdToSocket (s)) == NULL) {
256                rtems_bsdnet_semaphore_release ();
257                return -1;
258        }
259        if ((head->so_options & SO_ACCEPTCONN) == 0) {
260                errno = EINVAL;
261                rtems_bsdnet_semaphore_release ();
262                return -1;
263        }
264        if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) {
265                errno = EWOULDBLOCK;
266                rtems_bsdnet_semaphore_release ();
267                return -1;
268        }
269        error = head->so_error;
270        while (error ==  0 && head->so_comp.tqh_first == NULL) {
271                if (head->so_state & SS_CANTRCVMORE) {
272                        error = ECONNABORTED;
273                        break;
274                }
275                error = soconnsleep (head);
276        }
277        if (error) {
278                errno = error;
279                rtems_bsdnet_semaphore_release ();
280                return -1;
281        }
282
283        so = head->so_comp.tqh_first;
284        TAILQ_REMOVE(&head->so_comp, so, so_list);
285        head->so_qlen--;
286
287        fd = rtems_bsdnet_makeFdForSocket (so);
288        if (fd < 0) {
289                TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
290                head->so_qlen++;
291                soconnwakeup (head);
292                rtems_bsdnet_semaphore_release ();
293                return -1;
294        }
295        so->so_state &= ~SS_COMP;
296        so->so_head = NULL;
297
298        nam = m_get(M_WAIT, MT_SONAME);
299        (void) soaccept(so, nam);
300        if (name) {
301                 /* check length before it is destroyed */
302                if (*namelen > nam->m_len)
303                        *namelen = nam->m_len;
304                memcpy (name, mtod(nam, caddr_t), *namelen);
305        }
306        m_freem(nam);
307        rtems_bsdnet_semaphore_release ();
308        return (fd);
309
310}
311
312/*
313 *  Shutdown routine
314 */
315
316int
317shutdown (int s, int how)
318{
319      struct socket *so;
320      int error;
321
322      rtems_bsdnet_semaphore_obtain ();
323      if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
324              rtems_bsdnet_semaphore_release ();
325              return -1;
326      }
327      error = soshutdown(so, how);
328      rtems_bsdnet_semaphore_release ();
329      if (error) {
330              errno = error;
331              return -1;
332      }
333      return 0;
334}
335
336/*
337 * All `transmit' operations end up calling this routine.
338 */
339ssize_t
340sendmsg (int s, const struct msghdr *mp, int flags)
341{
342        int ret = -1;
343        int error;
344        struct uio auio;
345        struct iovec *iov;
346        struct socket *so;
347        struct mbuf *to;
348        struct mbuf *control = NULL;
349        int i;
350        int len;
351
352        rtems_bsdnet_semaphore_obtain ();
353        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
354                rtems_bsdnet_semaphore_release ();
355                return -1;
356        }
357        auio.uio_iov = mp->msg_iov;
358        auio.uio_iovcnt = mp->msg_iovlen;
359        auio.uio_segflg = UIO_USERSPACE;
360        auio.uio_rw = UIO_WRITE;
361        auio.uio_offset = 0;
362        auio.uio_resid = 0;
363        iov = mp->msg_iov;
364        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
365                if ((auio.uio_resid += iov->iov_len) < 0) {
366                        errno = EINVAL;
367                        rtems_bsdnet_semaphore_release ();
368                        return -1;
369                }
370        }
371        if (mp->msg_name) {
372                error = sockargstombuf (&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
373                if (error) {
374                        errno = error;
375                        rtems_bsdnet_semaphore_release ();
376                        return -1;
377                }
378        }
379        else {
380                to = NULL;
381        }
382        if (mp->msg_control) {
383                if (mp->msg_controllen < sizeof (struct cmsghdr)) {
384                        errno = EINVAL;
385                        if (to)
386                                m_freem(to);
387                        rtems_bsdnet_semaphore_release ();
388                        return -1;
389                }
390                sockargstombuf (&control, mp->msg_control, mp->msg_controllen, MT_CONTROL);
391        }
392        else {
393                control = NULL;
394        }
395        len = auio.uio_resid;
396        error = sosend (so, to, &auio, (struct mbuf *)0, control, flags);
397        if (error) {
398                if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))
399                        error = 0;
400        }
401        if (error)
402                errno = error;
403        else
404                ret = len - auio.uio_resid;
405        if (to)
406                m_freem(to);
407        rtems_bsdnet_semaphore_release ();
408        return (ret);
409}
410
411/*
412 * Send a message to a host
413 */
414ssize_t
415sendto (int s, const void *buf, size_t buflen, int flags, const struct sockaddr *to, int tolen)
416{
417        struct msghdr msg;
418        struct iovec iov;
419
420        iov.iov_base = (void *)buf;
421        iov.iov_len = buflen;
422        msg.msg_name = (caddr_t)to;
423        msg.msg_namelen = tolen;
424        msg.msg_iov = &iov;
425        msg.msg_iovlen = 1;
426        msg.msg_control = NULL;
427        msg.msg_controllen = 0;
428        return sendmsg (s, &msg, flags);
429}
430
431/*
432 * All `receive' operations end up calling this routine.
433 */
434ssize_t
435recvmsg (int s, struct msghdr *mp, int flags)
436{
437        int ret = -1;
438        int error;
439        struct uio auio;
440        struct iovec *iov;
441        struct socket *so;
442        struct mbuf *from = NULL, *control = NULL;
443        int i;
444        int len;
445
446        rtems_bsdnet_semaphore_obtain ();
447        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
448                rtems_bsdnet_semaphore_release ();
449                return -1;
450        }
451        auio.uio_iov = mp->msg_iov;
452        auio.uio_iovcnt = mp->msg_iovlen;
453        auio.uio_segflg = UIO_USERSPACE;
454        auio.uio_rw = UIO_READ;
455        auio.uio_offset = 0;
456        auio.uio_resid = 0;
457        iov = mp->msg_iov;
458        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
459                if ((auio.uio_resid += iov->iov_len) < 0) {
460                        errno = EINVAL;
461                        rtems_bsdnet_semaphore_release ();
462                        return -1;
463                }
464        }
465        len = auio.uio_resid;
466        mp->msg_flags = flags;
467        error = soreceive (so, &from, &auio, (struct mbuf **)NULL,
468                        mp->msg_control ? &control : (struct mbuf **)NULL,
469                        &mp->msg_flags);
470        if (error) {
471                if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))
472                        error = 0;
473        }
474        if (error) {
475                errno = error;
476        }
477        else {
478                ret = len - auio.uio_resid;
479                if (mp->msg_name) {
480                        len = mp->msg_namelen;
481                        if ((len <= 0) || (from == NULL)) {
482                                len = 0;
483                        }
484                        else {
485                                if (len > from->m_len)
486                                        len = from->m_len;
487                                memcpy (mp->msg_name, mtod(from, caddr_t), len);
488                        }
489                        mp->msg_namelen = len;
490                }
491                if (mp->msg_control) {
492                        struct mbuf *m;
493                        void *ctlbuf;
494
495                        len = mp->msg_controllen;
496                        m = control;
497                        mp->msg_controllen = 0;
498                        ctlbuf = mp->msg_control;
499
500                        while (m && (len > 0)) {
501                                unsigned int tocopy;
502
503                                if (len >= m->m_len)
504                                        tocopy = m->m_len;
505                                else {
506                                        mp->msg_flags |= MSG_CTRUNC;
507                                        tocopy = len;
508                                }
509                                memcpy(ctlbuf, mtod(m, caddr_t), tocopy);
510                                ctlbuf += tocopy;
511                                len -= tocopy;
512                                m = m->m_next;
513                        }
514                        mp->msg_controllen = ctlbuf - mp->msg_control;
515                }
516        }
517        if (from)
518                m_freem (from);
519        if (control)
520                m_freem (control);
521        rtems_bsdnet_semaphore_release ();
522        return (ret);
523}
524
525/*
526 * Receive a message from a host
527 */
528ssize_t
529recvfrom (int s, void *buf, size_t buflen, int flags, const struct sockaddr *from, int *fromlen)
530{
531        struct msghdr msg;
532        struct iovec iov;
533        int ret;
534
535        iov.iov_base = buf;
536        iov.iov_len = buflen;
537        msg.msg_name = (caddr_t)from;
538        if (fromlen)
539                msg.msg_namelen = *fromlen;
540        else
541        msg.msg_namelen = 0;
542        msg.msg_iov = &iov;
543        msg.msg_iovlen = 1;
544        msg.msg_control = NULL;
545        msg.msg_controllen = 0;
546        ret = recvmsg (s, &msg, flags);
547        if ((from != NULL) && (fromlen != NULL) && (ret >= 0))
548                *fromlen = msg.msg_namelen;
549        return ret;
550}
551
552int
553setsockopt (int s, int level, int name, const void *val, int len)
554{
555        struct socket *so;
556        struct mbuf *m = NULL;
557        int error;
558
559        rtems_bsdnet_semaphore_obtain ();
560        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
561                rtems_bsdnet_semaphore_release ();
562                return -1;
563        }
564        if (len > MLEN) {
565                errno = EINVAL;
566                rtems_bsdnet_semaphore_release ();
567                return -1;
568        }
569        if (val) {
570                error = sockargstombuf (&m, val, len, MT_SOOPTS);
571                if (error) {
572                        errno = error;
573                        rtems_bsdnet_semaphore_release ();
574                        return -1;
575                }
576        }
577        error = sosetopt(so, level, name, m);
578        if (error) {
579                errno = error;
580                rtems_bsdnet_semaphore_release ();
581                return -1;
582        }
583        rtems_bsdnet_semaphore_release ();
584        return 0;
585}
586
587int
588getsockopt (int s, int level, int name, void *aval, int *avalsize)
589{
590        struct socket *so;
591        struct mbuf *m = NULL, *m0;
592        char *val = aval;
593        int i, op, valsize;
594        int error;
595
596        rtems_bsdnet_semaphore_obtain ();
597        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
598                rtems_bsdnet_semaphore_release ();
599                return -1;
600        }
601        if (val)
602                valsize = *avalsize;
603        else
604                valsize = 0;
605        if (((error = sogetopt(so, level, name, &m)) == 0) && val && valsize && m) {
606                op = 0;
607                while (m && op < valsize) {
608                        i = valsize - op;
609                        if (i > m->m_len)
610                                i = m->m_len;
611                        memcpy (val, mtod(m, caddr_t), i);
612                        op += i;
613                        val += i;
614                        m0 = m;
615                        MFREE (m0, m);
616                }
617                *avalsize = op;
618        }
619        if (m != NULL)
620                (void) m_free(m);
621        if (error) {
622                errno = error;
623                rtems_bsdnet_semaphore_release ();
624                return -1;
625        }
626        rtems_bsdnet_semaphore_release ();
627        return 0;
628}
629
630static int
631getpeersockname (int s, struct sockaddr *name, int *namelen, int pflag)
632{
633        struct socket *so;
634        struct mbuf *m;
635        int len = *namelen;
636        int error;
637
638        rtems_bsdnet_semaphore_obtain ();
639        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
640                rtems_bsdnet_semaphore_release ();
641                return -1;
642        }
643        m = m_getclr(M_WAIT, MT_SONAME);
644        if (m == NULL) {
645                errno = ENOBUFS;
646                rtems_bsdnet_semaphore_release ();
647                return -1;
648        }
649        if (pflag)
650                error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, m);
651        else
652                error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, m);
653        if (error) {
654                m_freem(m);
655                errno = error;
656                rtems_bsdnet_semaphore_release ();
657                return -1;
658        }
659        if (len > m->m_len) {
660                len = m->m_len;
661                *namelen = len;
662        }
663        memcpy (name, mtod(m, caddr_t), len);
664        m_freem (m);
665        rtems_bsdnet_semaphore_release ();
666        return 0;
667}
668
669int
670getpeername (int s, struct sockaddr *name, int *namelen)
671{
672        return getpeersockname (s, name, namelen, 1);
673}
674int
675getsockname (int s, struct sockaddr *name, int *namelen)
676{
677        return getpeersockname (s, name, namelen, 0);
678}
679
680int
681sysctl(int *name, u_int namelen, void *oldp,
682       size_t *oldlenp, void *newp, size_t newlen)
683{
684  int    error;
685        size_t j;
686
687  rtems_bsdnet_semaphore_obtain ();
688  error = userland_sysctl (0, name, namelen, oldp, oldlenp, 1, newp, newlen, &j);
689  rtems_bsdnet_semaphore_release ();
690
691  if (oldlenp)
692    *oldlenp = j;
693
694  if (error)
695  {
696    errno = error;
697    return -1;
698  }
699  return 0;
700}
701
702/*
703 ************************************************************************
704 *                      RTEMS I/O HANDLER ROUTINES                      *
705 ************************************************************************
706 */
707static int
708rtems_bsdnet_close (rtems_libio_t *iop)
709{
710        struct socket *so;
711        int error;
712
713        rtems_bsdnet_semaphore_obtain ();
714        if ((so = iop->data1) == NULL) {
715                errno = EBADF;
716                rtems_bsdnet_semaphore_release ();
717                return -1;
718        }
719        iop->data1 = NULL;
720        error = soclose (so);
721        rtems_bsdnet_semaphore_release ();
722        if (error) {
723                errno = error;
724                return -1;
725        }
726        return 0;
727}
728
729static ssize_t
730rtems_bsdnet_read (rtems_libio_t *iop, void *buffer, size_t count)
731{
732        return recv (iop->data0, buffer, count, 0);
733}
734
735static ssize_t
736rtems_bsdnet_write (rtems_libio_t *iop, const void *buffer, size_t count)
737{
738        return send (iop->data0, buffer, count, 0);
739}
740
741static int
742so_ioctl (rtems_libio_t *iop, struct socket *so, uint32_t   command, void *buffer)
743{
744        switch (command) {
745        case FIONBIO:
746                if (*(int *)buffer) {
747                        iop->flags |= O_NONBLOCK;
748                        so->so_state |= SS_NBIO;
749                }
750                else {
751                        iop->flags &= ~O_NONBLOCK;
752                        so->so_state &= ~SS_NBIO;
753                }
754                return 0;
755
756        case FIONREAD:
757                *(int *)buffer = so->so_rcv.sb_cc;
758                return 0;
759        }
760
761        if (IOCGROUP(command) == 'i')
762                return ifioctl (so, command, buffer, NULL);
763        if (IOCGROUP(command) == 'r')
764                return rtioctl (command, buffer, NULL);
765        return (*so->so_proto->pr_usrreqs->pru_control)(so, command, buffer, 0);
766}
767
768static int
769rtems_bsdnet_ioctl (rtems_libio_t *iop, uint32_t   command, void *buffer)
770{
771        struct socket *so;
772        int error;
773
774        rtems_bsdnet_semaphore_obtain ();
775        if ((so = iop->data1) == NULL) {
776                errno = EBADF;
777                rtems_bsdnet_semaphore_release ();
778                return -1;
779        }
780        error = so_ioctl (iop, so, command, buffer);
781        rtems_bsdnet_semaphore_release ();
782        if (error) {
783                errno = error;
784                return -1;
785        }
786        return 0;
787}
788
789static int
790rtems_bsdnet_fcntl (rtems_libio_t *iop, int cmd)
791{
792        struct socket *so;
793
794        if (cmd == F_SETFL) {
795                rtems_bsdnet_semaphore_obtain ();
796                if ((so = iop->data1) == NULL) {
797                        rtems_bsdnet_semaphore_release ();
798                        return EBADF;
799                }
800                if (iop->flags & LIBIO_FLAGS_NO_DELAY)
801                        so->so_state |= SS_NBIO;
802                else
803                        so->so_state &= ~SS_NBIO;
804                rtems_bsdnet_semaphore_release ();
805        }
806        return 0;
807}
808
809static int
810rtems_bsdnet_fstat (const rtems_filesystem_location_info_t *loc, struct stat *sp)
811{
812        sp->st_mode = S_IFSOCK;
813        return 0;
814}
815
816static const rtems_filesystem_file_handlers_r socket_handlers = {
817        .open_h = rtems_filesystem_default_open,
818        .close_h = rtems_bsdnet_close,
819        .read_h = rtems_bsdnet_read,
820        .write_h = rtems_bsdnet_write,
821        .ioctl_h = rtems_bsdnet_ioctl,
822        .lseek_h = rtems_filesystem_default_lseek,
823        .fstat_h = rtems_bsdnet_fstat,
824        .ftruncate_h = rtems_filesystem_default_ftruncate,
825        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
826        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
827        .fcntl_h = rtems_bsdnet_fcntl,
828        .kqfilter_h = rtems_filesystem_default_kqfilter,
829        .poll_h = rtems_filesystem_default_poll,
830        .readv_h = rtems_filesystem_default_readv,
831        .writev_h = rtems_filesystem_default_writev
832};
Note: See TracBrowser for help on using the repository browser.