source: rtems-libbsd/freebsd/sys/sys/socketvar.h @ 94b5368

5-freebsd-12
Last change on this file since 94b5368 was 94b5368, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 2, 2018 at 6:21:37 AM

Avoid malloc() in getsockaddr()

The getsockaddr() function is used to allocate a struct sockaddr of the
right length and initialize it with userspace provided data. It is used
for the connect(), bind() and sendit() family functions. In particular,
the sendit() function is used by the UDP send functions. This means
each UDP send needs a malloc() and free() invocation. This is a
performance problem in RTEMS (first-fit heap) and may lead to heap
fragmentation. Replace the malloc() allocation with a stack allocation.
This requires SOCK_MAXADDRLEN (= 255) of additional stack space for
libbsd.

A further optimization would be to get rid of the stack copy of the
socket address. However, this would require to check each consumer of
the address to ensure that it is not modified.

  • Property mode set to 100644
File size: 14.6 KB
Line 
1/*-
2 * Copyright (c) 1982, 1986, 1990, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *      @(#)socketvar.h 8.3 (Berkeley) 2/19/95
30 *
31 * $FreeBSD$
32 */
33
34#ifndef _SYS_SOCKETVAR_H_
35#define _SYS_SOCKETVAR_H_
36
37#include <sys/queue.h>                  /* for TAILQ macros */
38#include <sys/selinfo.h>                /* for struct selinfo */
39#include <sys/_lock.h>
40#include <sys/_mutex.h>
41#include <sys/osd.h>
42#include <sys/_sx.h>
43#include <sys/sockbuf.h>
44#include <sys/sockstate.h>
45#ifdef _KERNEL
46#include <sys/caprights.h>
47#include <sys/sockopt.h>
48#endif
49
50struct vnet;
51
52/*
53 * Kernel structure per socket.
54 * Contains send and receive buffer queues,
55 * handle on protocol and pointer to protocol
56 * private data and error information.
57 */
58typedef u_quad_t so_gen_t;
59
60struct socket;
61
62/*-
63 * Locking key to struct socket:
64 * (a) constant after allocation, no locking required.
65 * (b) locked by SOCK_LOCK(so).
66 * (c) locked by SOCKBUF_LOCK(&so->so_rcv).
67 * (e) locked by ACCEPT_LOCK().
68 * (f) not locked since integer reads/writes are atomic.
69 * (g) used only as a sleep/wakeup address, no value.
70 * (h) locked by global mutex so_global_mtx.
71 */
72struct socket {
73        int     so_count;               /* (b) reference count */
74        short   so_type;                /* (a) generic type, see socket.h */
75        short   so_options;             /* from socket call, see socket.h */
76        short   so_linger;              /* time to linger while closing */
77        short   so_state;               /* (b) internal state flags SS_* */
78        int     so_qstate;              /* (e) internal state flags SQ_* */
79        void    *so_pcb;                /* protocol control block */
80        struct  vnet *so_vnet;          /* (a) network stack instance */
81        struct  protosw *so_proto;      /* (a) protocol handle */
82/*
83 * Variables for connection queuing.
84 * Socket where accepts occur is so_head in all subsidiary sockets.
85 * If so_head is 0, socket is not related to an accept.
86 * For head socket so_incomp queues partially completed connections,
87 * while so_comp is a queue of connections ready to be accepted.
88 * If a connection is aborted and it has so_head set, then
89 * it has to be pulled out of either so_incomp or so_comp.
90 * We allow connections to queue up based on current queue lengths
91 * and limit on number of queued connections for this socket.
92 */
93        struct  socket *so_head;        /* (e) back pointer to listen socket */
94        TAILQ_HEAD(, socket) so_incomp; /* (e) queue of partial unaccepted connections */
95        TAILQ_HEAD(, socket) so_comp;   /* (e) queue of complete unaccepted connections */
96        TAILQ_ENTRY(socket) so_list;    /* (e) list of unaccepted connections */
97        u_int   so_qlen;                /* (e) number of unaccepted connections */
98        u_int   so_incqlen;             /* (e) number of unaccepted incomplete
99                                           connections */
100        u_int   so_qlimit;              /* (e) max number queued connections */
101        short   so_timeo;               /* (g) connection timeout */
102        u_short so_error;               /* (f) error affecting connection */
103        struct  sigio *so_sigio;        /* [sg] information for async I/O or
104                                           out of band data (SIGURG) */
105        u_long  so_oobmark;             /* (c) chars to oob mark */
106
107        struct sockbuf so_rcv, so_snd;
108
109        struct  ucred *so_cred;         /* (a) user credentials */
110        struct  label *so_label;        /* (b) MAC label for socket */
111        struct  label *so_peerlabel;    /* (b) cached MAC label for peer */
112        /* NB: generation count must not be first. */
113        so_gen_t so_gencnt;             /* (h) generation count */
114        void    *so_emuldata;           /* (b) private data for emulators */
115        struct so_accf {
116                struct  accept_filter *so_accept_filter;
117                void    *so_accept_filter_arg;  /* saved filter args */
118                char    *so_accept_filter_str;  /* saved user args */
119        } *so_accf;
120        struct  osd     osd;            /* Object Specific extensions */
121        /*
122         * so_fibnum, so_user_cookie and friends can be used to attach
123         * some user-specified metadata to a socket, which then can be
124         * used by the kernel for various actions.
125         * so_user_cookie is used by ipfw/dummynet.
126         */
127        int so_fibnum;          /* routing domain for this socket */
128        uint32_t so_user_cookie;
129
130        int so_ts_clock;        /* type of the clock used for timestamps */
131        uint32_t so_max_pacing_rate;    /* (f) TX rate limit in bytes/s */
132
133        void *so_pspare[2];     /* general use */
134        int so_ispare[2];       /* general use */
135};
136
137/*
138 * Global accept mutex to serialize access to accept queues and
139 * fields associated with multiple sockets.  This allows us to
140 * avoid defining a lock order between listen and accept sockets
141 * until such time as it proves to be a good idea.
142 */
143extern struct mtx accept_mtx;
144#define ACCEPT_LOCK_ASSERT()            mtx_assert(&accept_mtx, MA_OWNED)
145#define ACCEPT_UNLOCK_ASSERT()          mtx_assert(&accept_mtx, MA_NOTOWNED)
146#define ACCEPT_LOCK()                   mtx_lock(&accept_mtx)
147#define ACCEPT_UNLOCK()                 mtx_unlock(&accept_mtx)
148
149/*
150 * Per-socket mutex: we reuse the receive socket buffer mutex for space
151 * efficiency.  This decision should probably be revisited as we optimize
152 * locking for the socket code.
153 */
154#define SOCK_MTX(_so)                   SOCKBUF_MTX(&(_so)->so_rcv)
155#define SOCK_LOCK(_so)                  SOCKBUF_LOCK(&(_so)->so_rcv)
156#define SOCK_OWNED(_so)                 SOCKBUF_OWNED(&(_so)->so_rcv)
157#define SOCK_UNLOCK(_so)                SOCKBUF_UNLOCK(&(_so)->so_rcv)
158#define SOCK_LOCK_ASSERT(_so)           SOCKBUF_LOCK_ASSERT(&(_so)->so_rcv)
159
160/*
161 * Socket state bits stored in so_qstate.
162 */
163#define SQ_INCOMP               0x0800  /* unaccepted, incomplete connection */
164#define SQ_COMP                 0x1000  /* unaccepted, complete connection */
165
166/*
167 * Externalized form of struct socket used by the sysctl(3) interface.
168 */
169struct xsocket {
170        size_t  xso_len;        /* length of this structure */
171        struct  socket *xso_so; /* makes a convenient handle sometimes */
172        short   so_type;
173        short   so_options;
174        short   so_linger;
175        short   so_state;
176        caddr_t so_pcb;         /* another convenient handle */
177        int     xso_protocol;
178        int     xso_family;
179        u_int   so_qlen;
180        u_int   so_incqlen;
181        u_int   so_qlimit;
182        short   so_timeo;
183        u_short so_error;
184        pid_t   so_pgid;
185        u_long  so_oobmark;
186        struct xsockbuf so_rcv, so_snd;
187        uid_t   so_uid;         /* XXX */
188};
189
190#ifdef _KERNEL
191
192/*
193 * Macros for sockets and socket buffering.
194 */
195
196/*
197 * Flags to sblock().
198 */
199#define SBL_WAIT        0x00000001      /* Wait if not immediately available. */
200#define SBL_NOINTR      0x00000002      /* Force non-interruptible sleep. */
201#define SBL_VALID       (SBL_WAIT | SBL_NOINTR)
202
203/*
204 * Do we need to notify the other side when I/O is possible?
205 */
206#define sb_notify(sb)   (((sb)->sb_flags & (SB_WAIT | SB_SEL | SB_ASYNC | \
207    SB_UPCALL | SB_AIO | SB_KNOTE)) != 0)
208
209/* do we have to send all at once on a socket? */
210#define sosendallatonce(so) \
211    ((so)->so_proto->pr_flags & PR_ATOMIC)
212
213/* can we read something from so? */
214#define soreadabledata(so) \
215    (sbavail(&(so)->so_rcv) >= (so)->so_rcv.sb_lowat || \
216        !TAILQ_EMPTY(&(so)->so_comp) || (so)->so_error)
217#define soreadable(so) \
218        (soreadabledata(so) || ((so)->so_rcv.sb_state & SBS_CANTRCVMORE))
219
220/* can we write something to so? */
221#define sowriteable(so) \
222    ((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \
223        (((so)->so_state&SS_ISCONNECTED) || \
224          ((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || \
225     ((so)->so_snd.sb_state & SBS_CANTSENDMORE) || \
226     (so)->so_error)
227
228/*
229 * soref()/sorele() ref-count the socket structure.  Note that you must
230 * still explicitly close the socket, but the last ref count will free
231 * the structure.
232 */
233#define soref(so) do {                                                  \
234        SOCK_LOCK_ASSERT(so);                                           \
235        ++(so)->so_count;                                               \
236} while (0)
237
238#define sorele(so) do {                                                 \
239        ACCEPT_LOCK_ASSERT();                                           \
240        SOCK_LOCK_ASSERT(so);                                           \
241        if ((so)->so_count <= 0)                                        \
242                panic("sorele");                                        \
243        if (--(so)->so_count == 0)                                      \
244                sofree(so);                                             \
245        else {                                                          \
246                SOCK_UNLOCK(so);                                        \
247                ACCEPT_UNLOCK();                                        \
248        }                                                               \
249} while (0)
250
251/*
252 * In sorwakeup() and sowwakeup(), acquire the socket buffer lock to
253 * avoid a non-atomic test-and-wakeup.  However, sowakeup is
254 * responsible for releasing the lock if it is called.  We unlock only
255 * if we don't call into sowakeup.  If any code is introduced that
256 * directly invokes the underlying sowakeup() primitives, it must
257 * maintain the same semantics.
258 */
259#define sorwakeup_locked(so) do {                                       \
260        SOCKBUF_LOCK_ASSERT(&(so)->so_rcv);                             \
261        if (sb_notify(&(so)->so_rcv))                                   \
262                sowakeup((so), &(so)->so_rcv);                          \
263        else                                                            \
264                SOCKBUF_UNLOCK(&(so)->so_rcv);                          \
265} while (0)
266
267#define sorwakeup(so) do {                                              \
268        SOCKBUF_LOCK(&(so)->so_rcv);                                    \
269        sorwakeup_locked(so);                                           \
270} while (0)
271
272#define sowwakeup_locked(so) do {                                       \
273        SOCKBUF_LOCK_ASSERT(&(so)->so_snd);                             \
274        if (sb_notify(&(so)->so_snd))                                   \
275                sowakeup((so), &(so)->so_snd);                          \
276        else                                                            \
277                SOCKBUF_UNLOCK(&(so)->so_snd);                          \
278} while (0)
279
280#define sowwakeup(so) do {                                              \
281        SOCKBUF_LOCK(&(so)->so_snd);                                    \
282        sowwakeup_locked(so);                                           \
283} while (0)
284
285struct accept_filter {
286        char    accf_name[16];
287        int     (*accf_callback)
288                (struct socket *so, void *arg, int waitflag);
289        void *  (*accf_create)
290                (struct socket *so, char *arg);
291        void    (*accf_destroy)
292                (struct socket *so);
293        SLIST_ENTRY(accept_filter) accf_next;
294};
295
296#ifdef MALLOC_DECLARE
297MALLOC_DECLARE(M_ACCF);
298MALLOC_DECLARE(M_PCB);
299MALLOC_DECLARE(M_SONAME);
300#endif
301
302/*
303 * Socket specific helper hook point identifiers
304 * Do not leave holes in the sequence, hook registration is a loop.
305 */
306#define HHOOK_SOCKET_OPT                0
307#define HHOOK_SOCKET_CREATE             1
308#define HHOOK_SOCKET_RCV                2
309#define HHOOK_SOCKET_SND                3
310#define HHOOK_FILT_SOREAD               4
311#define HHOOK_FILT_SOWRITE              5
312#define HHOOK_SOCKET_CLOSE              6
313#define HHOOK_SOCKET_LAST               HHOOK_SOCKET_CLOSE
314
315struct socket_hhook_data {
316        struct socket   *so;
317        struct mbuf     *m;
318        void            *hctx;          /* hook point specific data*/
319        int             status;
320};
321
322extern int      maxsockets;
323extern u_long   sb_max;
324extern so_gen_t so_gencnt;
325
326struct file;
327struct filecaps;
328struct filedesc;
329struct mbuf;
330struct sockaddr;
331struct ucred;
332struct uio;
333
334/* 'which' values for socket upcalls. */
335#define SO_RCV          1
336#define SO_SND          2
337
338/* Return values for socket upcalls. */
339#define SU_OK           0
340#define SU_ISCONNECTED  1
341
342/*
343 * From uipc_socket and friends
344 */
345#ifndef __rtems__
346int     getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len);
347#endif /* __rtems__ */
348int     getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
349            struct file **fpp, u_int *fflagp, struct filecaps *havecaps);
350void    soabort(struct socket *so);
351int     soaccept(struct socket *so, struct sockaddr **nam);
352void    soaio_enqueue(struct task *task);
353void    soaio_rcv(void *context, int pending);
354void    soaio_snd(void *context, int pending);
355int     socheckuid(struct socket *so, uid_t uid);
356int     sobind(struct socket *so, struct sockaddr *nam, struct thread *td);
357int     sobindat(int fd, struct socket *so, struct sockaddr *nam,
358            struct thread *td);
359int     soclose(struct socket *so);
360int     soconnect(struct socket *so, struct sockaddr *nam, struct thread *td);
361int     soconnectat(int fd, struct socket *so, struct sockaddr *nam,
362            struct thread *td);
363int     soconnect2(struct socket *so1, struct socket *so2);
364int     socreate(int dom, struct socket **aso, int type, int proto,
365            struct ucred *cred, struct thread *td);
366int     sodisconnect(struct socket *so);
367struct  sockaddr *sodupsockaddr(const struct sockaddr *sa, int mflags);
368void    sofree(struct socket *so);
369void    sohasoutofband(struct socket *so);
370int     solisten(struct socket *so, int backlog, struct thread *td);
371void    solisten_proto(struct socket *so, int backlog);
372int     solisten_proto_check(struct socket *so);
373struct socket *
374        sonewconn(struct socket *head, int connstatus);
375
376
377int     sopoll(struct socket *so, int events, struct ucred *active_cred,
378            struct thread *td);
379int     sopoll_generic(struct socket *so, int events,
380            struct ucred *active_cred, struct thread *td);
381int     soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio,
382            struct mbuf **mp0, struct mbuf **controlp, int *flagsp);
383int     soreceive_stream(struct socket *so, struct sockaddr **paddr,
384            struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
385            int *flagsp);
386int     soreceive_dgram(struct socket *so, struct sockaddr **paddr,
387            struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
388            int *flagsp);
389int     soreceive_generic(struct socket *so, struct sockaddr **paddr,
390            struct uio *uio, struct mbuf **mp0, struct mbuf **controlp,
391            int *flagsp);
392int     soreserve(struct socket *so, u_long sndcc, u_long rcvcc);
393void    sorflush(struct socket *so);
394int     sosend(struct socket *so, struct sockaddr *addr, struct uio *uio,
395            struct mbuf *top, struct mbuf *control, int flags,
396            struct thread *td);
397int     sosend_dgram(struct socket *so, struct sockaddr *addr,
398            struct uio *uio, struct mbuf *top, struct mbuf *control,
399            int flags, struct thread *td);
400int     sosend_generic(struct socket *so, struct sockaddr *addr,
401            struct uio *uio, struct mbuf *top, struct mbuf *control,
402            int flags, struct thread *td);
403int     soshutdown(struct socket *so, int how);
404void    sotoxsocket(struct socket *so, struct xsocket *xso);
405void    soupcall_clear(struct socket *so, int which);
406void    soupcall_set(struct socket *so, int which,
407            int (*func)(struct socket *, void *, int), void *arg);
408void    sowakeup(struct socket *so, struct sockbuf *sb);
409#ifndef __rtems__
410void    sowakeup_aio(struct socket *so, struct sockbuf *sb);
411#else /* __rtems__ */
412#define sowakeup_aio(so, sb) (void)0
413#endif /* __rtems__ */
414int     selsocket(struct socket *so, int events, struct timeval *tv,
415            struct thread *td);
416
417/*
418 * Accept filter functions (duh).
419 */
420int     accept_filt_add(struct accept_filter *filt);
421int     accept_filt_del(char *name);
422struct  accept_filter *accept_filt_get(char *name);
423#ifdef ACCEPT_FILTER_MOD
424#ifdef SYSCTL_DECL
425SYSCTL_DECL(_net_inet_accf);
426#endif
427int     accept_filt_generic_mod_event(module_t mod, int event, void *data);
428#endif
429
430#endif /* _KERNEL */
431
432#endif /* !_SYS_SOCKETVAR_H_ */
Note: See TracBrowser for help on using the repository browser.