Rename "subsystems" directory to "base"
[oonf.git] / src / base / os_linux / os_fd_linux.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4  * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
5  * 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  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * 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
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd 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.
20  *
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 OWNER 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
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 /**
43  * @file
44  */
45
46 #include <errno.h>
47 #include <net/if.h>
48 #include <netinet/in.h>
49 #include <sys/ioctl.h>
50
51 #include <oonf/oonf.h>
52 #include <oonf/libcore/oonf_logging.h>
53 #include <oonf/libcore/oonf_subsystem.h>
54 #include <oonf/base/oonf_clock.h>
55
56 #include <oonf/base/os_fd.h>
57
58 /* Defintions */
59 #define LOG_OS_SOCKET _oonf_os_fd_subsystem.logging
60
61 /* prototypes */
62 static int _init(void);
63 static void _cleanup(void);
64
65 /* subsystem definition */
66 static const char *_dependencies[] = {
67   OONF_CLOCK_SUBSYSTEM,
68 };
69
70 static struct oonf_subsystem _oonf_os_fd_subsystem = {
71   .name = OONF_OS_FD_SUBSYSTEM,
72   .dependencies = _dependencies,
73   .dependencies_count = ARRAYSIZE(_dependencies),
74   .init = _init,
75   .cleanup = _cleanup,
76 };
77 DECLARE_OONF_PLUGIN(_oonf_os_fd_subsystem);
78
79 /**
80  * Initialize os_net subsystem
81  * @return -1 if an error happened, 0 otherwise
82  */
83 static int
84 _init(void) {
85   return 0;
86 }
87
88 /**
89  * Cleanup os_net subsystem
90  */
91 static void
92 _cleanup(void) {}
93
94 /**
95  * wait for a network event on multiple sockets
96  * @param sel socket selector set
97  * @return number of events that happened, 0 if a timeout happened
98  */
99 int
100 os_fd_linux_event_wait(struct os_fd_select *sel) {
101   struct os_fd *sock;
102   uint64_t maxdelay;
103   int i;
104
105   maxdelay = oonf_clock_get_relative(sel->deadline);
106   if (maxdelay > INT32_MAX) {
107     maxdelay = INT32_MAX;
108   }
109
110   sel->_event_count = epoll_wait(sel->_epoll_fd, sel->_events, ARRAYSIZE(sel->_events), maxdelay);
111
112   OONF_DEBUG(LOG_OS_SOCKET, "epoll_wait(maxdelay = %" PRIu64 "): %d", maxdelay, sel->_event_count);
113
114   for (i = 0; i < sel->_event_count; i++) {
115     sock = os_fd_event_get(sel, i);
116     sock->received_events = sel->_events[i].events;
117
118     OONF_DEBUG(LOG_OS_SOCKET, "event %d: %x", i, sock->received_events);
119   }
120   return sel->_event_count;
121 }
122
123 /**
124  * Move the wanted events of a socket into a selector set
125  * @param sel socket selector set
126  * @param sock os socket
127  * @return -1 if an error happened, 0 otherwise
128  */
129 int
130 os_fd_linux_event_socket_modify(struct os_fd_select *sel, struct os_fd *sock) {
131   struct epoll_event event;
132
133   memset(&event, 0, sizeof(event));
134
135   event.events = sock->wanted_events;
136   event.data.ptr = sock;
137
138   OONF_DEBUG(LOG_OS_SOCKET, "Modify socket %d to events 0x%x", sock->fd, sock->wanted_events);
139   return epoll_ctl(sel->_epoll_fd, EPOLL_CTL_MOD, sock->fd, &event);
140 }
141
142 /**
143  * Raw IP sockets sometimes deliver the whole IP header instead of just
144  * the content. This function skips the IP header and modifies the length
145  * of the buffer.
146  * @param ptr pointer to the beginning of the buffer
147  * @param len pointer to length of buffer
148  * @param af_type address family of data in buffer
149  * @return pointer to transport layer data
150  */
151 uint8_t *
152 os_fd_linux_skip_rawsocket_prefix(uint8_t *ptr, ssize_t *len, int af_type) {
153   int header_size;
154
155   if (af_type != AF_INET) {
156     return ptr;
157   }
158
159   /* skip IPv4 header */
160   header_size = (ptr[0] & 0x0f) << 2;
161
162   *len -= header_size;
163   return ptr + header_size;
164 }