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

5
Last change on this file since ca90c6c was ca90c6c, checked in by Sebastian Huber <sebastian.huber@…>, on 09/13/17 at 12:00:50

libio: Add rtems_libio_iop_flags_initialize()

Update #3132.

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