source: rtems-libbsd/freebsd/sys/kern/sys_socket.c @ ec702ab

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since ec702ab was ec702ab, checked in by Sebastian Huber <sebastian.huber@…>, on 10/14/13 at 12:55:04

Use socket read() and write() from FreeBSD

  • Property mode set to 100644
File size: 11.0 KB
Line 
1#include <machine/rtems-bsd-config.h>
2
3/*-
4 * Copyright (c) 1982, 1986, 1990, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 4. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *      @(#)sys_socket.c        8.1 (Berkeley) 6/10/93
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD$");
36
37#include <rtems/bsd/sys/param.h>
38#include <sys/systm.h>
39#include <sys/file.h>
40#include <sys/filedesc.h>
41#include <sys/proc.h>
42#include <sys/protosw.h>
43#include <sys/sigio.h>
44#include <sys/signal.h>
45#include <sys/signalvar.h>
46#include <sys/socket.h>
47#include <sys/socketvar.h>
48#include <sys/filio.h>                  /* XXX */
49#include <sys/sockio.h>
50#include <sys/stat.h>
51#include <sys/uio.h>
52#include <sys/ucred.h>
53
54#include <net/if.h>
55#include <net/route.h>
56#include <net/vnet.h>
57
58#include <security/mac/mac_framework.h>
59
60#ifndef __rtems__
61struct fileops  socketops = {
62        .fo_read = soo_read,
63        .fo_write = soo_write,
64        .fo_truncate = soo_truncate,
65        .fo_ioctl = soo_ioctl,
66        .fo_poll = soo_poll,
67        .fo_kqfilter = soo_kqfilter,
68        .fo_stat = soo_stat,
69        .fo_close = soo_close,
70        .fo_flags = DFLAG_PASSABLE
71};
72#endif /* __rtems__ */
73
74/* ARGSUSED */
75#ifdef __rtems__
76static
77#endif /* __rtems__ */
78int
79soo_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
80    int flags, struct thread *td)
81{
82        struct socket *so = fp->f_data;
83        int error;
84
85#ifdef MAC
86        error = mac_socket_check_receive(active_cred, so);
87        if (error)
88                return (error);
89#endif
90        CURVNET_SET(so->so_vnet);
91        error = soreceive(so, 0, uio, 0, 0, 0);
92        CURVNET_RESTORE();
93        return (error);
94}
95#ifdef __rtems__
96static ssize_t
97rtems_bsd_soo_read(rtems_libio_t *iop, void *buffer, size_t count)
98{
99        struct thread *td = rtems_bsd_get_curthread_or_null();
100        struct file *fp = rtems_bsd_iop_to_fp(iop);
101        struct iovec iov = {
102                .iov_base = buffer,
103                .iov_len = count
104        };
105        struct uio auio = {
106                .uio_iov = &iov,
107                .uio_iovcnt = 1,
108                .uio_offset = 0,
109                .uio_resid = count,
110                .uio_segflg = UIO_USERSPACE,
111                .uio_rw = UIO_READ,
112                .uio_td = td
113        };
114        int error;
115
116        if (td != NULL) {
117                error = soo_read(fp, &auio, NULL, 0, NULL);
118        } else {
119                error = ENOMEM;
120        }
121
122        if (error == 0) {
123                return (count - auio.uio_resid);
124        } else {
125                rtems_set_errno_and_return_minus_one(error);
126        }
127}
128#endif /* __rtems__ */
129
130/* ARGSUSED */
131#ifdef __rtems__
132static
133#endif /* __rtems__ */
134int
135soo_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
136    int flags, struct thread *td)
137{
138        struct socket *so = fp->f_data;
139        int error;
140
141#ifdef MAC
142        error = mac_socket_check_send(active_cred, so);
143        if (error)
144                return (error);
145#endif
146        error = sosend(so, 0, uio, 0, 0, 0, uio->uio_td);
147        if (error == EPIPE && (so->so_options & SO_NOSIGPIPE) == 0) {
148#ifndef __rtems__
149                PROC_LOCK(uio->uio_td->td_proc);
150                tdksignal(uio->uio_td, SIGPIPE, NULL);
151                PROC_UNLOCK(uio->uio_td->td_proc);
152#else /* __rtems__ */
153                /* FIXME: Determine if we really want to use signals */
154#endif /* __rtems__ */
155        }
156        return (error);
157}
158#ifdef __rtems__
159static ssize_t
160rtems_bsd_soo_write(rtems_libio_t *iop, const void *buffer, size_t count)
161{
162        struct thread *td = rtems_bsd_get_curthread_or_null();
163        struct file *fp = rtems_bsd_iop_to_fp(iop);
164        struct iovec iov = {
165                .iov_base = __DECONST(void *, buffer),
166                .iov_len = count
167        };
168        struct uio auio = {
169                .uio_iov = &iov,
170                .uio_iovcnt = 1,
171                .uio_offset = 0,
172                .uio_resid = count,
173                .uio_segflg = UIO_USERSPACE,
174                .uio_rw = UIO_WRITE,
175                .uio_td = td
176        };
177        int error;
178
179        if (td != NULL) {
180                error = soo_write(fp, &auio, NULL, 0, NULL);
181        } else {
182                error = ENOMEM;
183        }
184
185        if (error == 0) {
186                return (count - auio.uio_resid);
187        } else {
188                rtems_set_errno_and_return_minus_one(error);
189        }
190}
191#endif /* __rtems__ */
192
193#ifndef __rtems__
194int
195soo_truncate(struct file *fp, off_t length, struct ucred *active_cred,
196    struct thread *td)
197{
198
199        return (EINVAL);
200}
201#endif /* __rtems__ */
202
203#ifdef __rtems__
204static
205#endif /* __rtems__ */
206int
207soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
208    struct thread *td)
209{
210        struct socket *so = fp->f_data;
211        int error = 0;
212
213        CURVNET_SET(so->so_vnet);
214        switch (cmd) {
215        case FIONBIO:
216                SOCK_LOCK(so);
217                if (*(int *)data)
218                        so->so_state |= SS_NBIO;
219                else
220                        so->so_state &= ~SS_NBIO;
221                SOCK_UNLOCK(so);
222                break;
223
224        case FIOASYNC:
225                /*
226                 * XXXRW: This code separately acquires SOCK_LOCK(so) and
227                 * SOCKBUF_LOCK(&so->so_rcv) even though they are the same
228                 * mutex to avoid introducing the assumption that they are
229                 * the same.
230                 */
231                if (*(int *)data) {
232                        SOCK_LOCK(so);
233                        so->so_state |= SS_ASYNC;
234                        SOCK_UNLOCK(so);
235                        SOCKBUF_LOCK(&so->so_rcv);
236                        so->so_rcv.sb_flags |= SB_ASYNC;
237                        SOCKBUF_UNLOCK(&so->so_rcv);
238                        SOCKBUF_LOCK(&so->so_snd);
239                        so->so_snd.sb_flags |= SB_ASYNC;
240                        SOCKBUF_UNLOCK(&so->so_snd);
241                } else {
242                        SOCK_LOCK(so);
243                        so->so_state &= ~SS_ASYNC;
244                        SOCK_UNLOCK(so);
245                        SOCKBUF_LOCK(&so->so_rcv);
246                        so->so_rcv.sb_flags &= ~SB_ASYNC;
247                        SOCKBUF_UNLOCK(&so->so_rcv);
248                        SOCKBUF_LOCK(&so->so_snd);
249                        so->so_snd.sb_flags &= ~SB_ASYNC;
250                        SOCKBUF_UNLOCK(&so->so_snd);
251                }
252                break;
253
254        case FIONREAD:
255                /* Unlocked read. */
256                *(int *)data = so->so_rcv.sb_cc;
257                break;
258
259        case FIONWRITE:
260                /* Unlocked read. */
261                *(int *)data = so->so_snd.sb_cc;
262                break;
263
264        case FIONSPACE:
265                if ((so->so_snd.sb_hiwat < so->so_snd.sb_cc) ||
266                    (so->so_snd.sb_mbmax < so->so_snd.sb_mbcnt))
267                        *(int *)data = 0;
268                else
269                        *(int *)data = sbspace(&so->so_snd);
270                break;
271
272        case FIOSETOWN:
273                error = fsetown(*(int *)data, &so->so_sigio);
274                break;
275
276        case FIOGETOWN:
277                *(int *)data = fgetown(&so->so_sigio);
278                break;
279
280        case SIOCSPGRP:
281                error = fsetown(-(*(int *)data), &so->so_sigio);
282                break;
283
284        case SIOCGPGRP:
285                *(int *)data = -fgetown(&so->so_sigio);
286                break;
287
288        case SIOCATMARK:
289                /* Unlocked read. */
290                *(int *)data = (so->so_rcv.sb_state & SBS_RCVATMARK) != 0;
291                break;
292        default:
293                /*
294                 * Interface/routing/protocol specific ioctls: interface and
295                 * routing ioctls should have a different entry since a
296                 * socket is unnecessary.
297                 */
298                if (IOCGROUP(cmd) == 'i')
299                        error = ifioctl(so, cmd, data, td);
300                else if (IOCGROUP(cmd) == 'r')
301                        error = rtioctl_fib(cmd, data, so->so_fibnum);
302                else
303                        error = ((*so->so_proto->pr_usrreqs->pru_control)
304                            (so, cmd, data, 0, td));
305                break;
306        }
307        CURVNET_RESTORE();
308        return (error);
309}
310#ifdef __rtems__
311static int
312rtems_bsd_soo_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
313{
314        struct thread *td = rtems_bsd_get_curthread_or_null();
315        struct file *fp = rtems_bsd_iop_to_fp(iop);
316        int error;
317
318        if (td != NULL) {
319                error = soo_ioctl(fp, request, buffer, NULL, td);
320        } else {
321                error = ENOMEM;
322        }
323
324        return rtems_bsd_error_to_status_and_errno(error);
325}
326#endif /* __rtems__ */
327
328#ifndef __rtems__
329int
330soo_poll(struct file *fp, int events, struct ucred *active_cred,
331    struct thread *td)
332{
333        struct socket *so = fp->f_data;
334#ifdef MAC
335        int error;
336
337        error = mac_socket_check_poll(active_cred, so);
338        if (error)
339                return (error);
340#endif
341        return (sopoll(so, events, fp->f_cred, td));
342}
343#endif /* __rtems__ */
344
345#ifndef __rtems__
346int
347soo_stat(struct file *fp, struct stat *ub, struct ucred *active_cred,
348    struct thread *td)
349{
350        struct socket *so = fp->f_data;
351#else /* __rtems__ */
352static int
353soo_stat(struct socket *so, struct stat *ub)
354{
355#endif /* __rtems__ */
356#ifdef MAC
357        int error;
358#endif
359
360#ifndef __rtems__
361        bzero((caddr_t)ub, sizeof (*ub));
362#endif /* __rtems__ */
363        ub->st_mode = S_IFSOCK;
364#ifdef MAC
365        error = mac_socket_check_stat(active_cred, so);
366        if (error)
367                return (error);
368#endif
369        /*
370         * If SBS_CANTRCVMORE is set, but there's still data left in the
371         * receive buffer, the socket is still readable.
372         */
373        SOCKBUF_LOCK(&so->so_rcv);
374        if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) == 0 ||
375            so->so_rcv.sb_cc != 0)
376                ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
377        ub->st_size = so->so_rcv.sb_cc - so->so_rcv.sb_ctl;
378        SOCKBUF_UNLOCK(&so->so_rcv);
379        /* Unlocked read. */
380        if ((so->so_snd.sb_state & SBS_CANTSENDMORE) == 0)
381                ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
382#ifndef __rtems__
383        ub->st_uid = so->so_cred->cr_uid;
384        ub->st_gid = so->so_cred->cr_gid;
385#else /* __rtems__ */
386        ub->st_uid = BSD_DEFAULT_UID;
387        ub->st_gid = BSD_DEFAULT_GID;
388#endif /* __rtems__ */
389        return (*so->so_proto->pr_usrreqs->pru_sense)(so, ub);
390}
391#ifdef __rtems__
392static int
393rtems_bsd_soo_stat(
394        const rtems_filesystem_location_info_t *loc,
395        struct stat *buf
396)
397{
398        struct socket *so = rtems_bsd_loc_to_f_data(loc);
399        int error = soo_stat(so, buf);
400
401        return rtems_bsd_error_to_status_and_errno(error);
402}
403#endif /* __rtems__ */
404
405/*
406 * API socket close on file pointer.  We call soclose() to close the socket
407 * (including initiating closing protocols).  soclose() will sorele() the
408 * file reference but the actual socket will not go away until the socket's
409 * ref count hits 0.
410 */
411/* ARGSUSED */
412#ifdef __rtems__
413static
414#endif /* __rtems__ */
415int
416soo_close(struct file *fp, struct thread *td)
417{
418        int error = 0;
419        struct socket *so;
420
421        so = fp->f_data;
422#ifndef __rtems__
423        fp->f_ops = &badfileops;
424#else /* __rtems__ */
425        fp->f_io.pathinfo.handlers = &rtems_filesystem_handlers_default;
426#endif /* __rtems__ */
427        fp->f_data = NULL;
428
429        if (so)
430                error = soclose(so);
431        return (error);
432}
433#ifdef __rtems__
434static int
435rtems_bsd_soo_close(rtems_libio_t *iop)
436{
437        struct file *fp = rtems_bsd_iop_to_fp(iop);
438        int error = soo_close(fp, NULL);
439
440        return rtems_bsd_error_to_status_and_errno(error);
441}
442
443const rtems_filesystem_file_handlers_r socketops = {
444        .open_h = rtems_filesystem_default_open,
445        .close_h = rtems_bsd_soo_close,
446        .read_h = rtems_bsd_soo_read,
447        .write_h = rtems_bsd_soo_write,
448        .ioctl_h = rtems_bsd_soo_ioctl,
449        .lseek_h = rtems_filesystem_default_lseek,
450        .fstat_h = rtems_bsd_soo_stat,
451        .ftruncate_h = rtems_filesystem_default_ftruncate,
452        .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
453        .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
454        .fcntl_h = rtems_filesystem_default_fcntl
455};
456#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.