source: trunk/kernel/syscalls/sys_socket.c@ 669

Last change on this file since 669 was 664, checked in by alain, 6 years ago
  • Introduce the sys_socket.c file implementing all socket related syscalls.
  • Improve the non-standard sys_get_config() function.
File size: 11.3 KB
Line 
1/*
2 * sys_socket.c - implement the various socket related system calls
3 *
4 * Author Alain Greiner (2016,2017,2018,2019,2020)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_kernel_types.h>
25#include <hal_uspace.h>
26#include <hal_vmm.h>
27#include <errno.h>
28#include <vmm.h>
29#include <cluster.h>
30#include <thread.h>
31#include <process.h>
32#include <ksocket.h>
33#include <string.h>
34#include <shared_syscalls.h>
35#include <shared_socket.h>
36#include <remote_barrier.h>
37#include <vfs.h>
38#include <mapper.h>
39
40#include <syscalls.h>
41
42/////////////////////////////////////////////////////////////////////////////////
43// This function returns a printable string for the socket related command type.
44/////////////////////////////////////////////////////////////////////////////////
45
46#if DEBUG_SYS_SOCKET
47static char* socket_cmd_type_str( uint32_t type )
48{
49 if ( type == SOCK_CREATE ) return "CREATE";
50 else if( type == SOCK_BIND ) return "BIND";
51 else if( type == SOCK_LISTEN ) return "LISTEN";
52 else if( type == SOCK_CONNECT ) return "CONNECT";
53 else if( type == SOCK_ACCEPT ) return "ACCEPT";
54 else if( type == SOCK_SEND ) return "SEND";
55 else if( type == SOCK_SENDTO ) return "SENDTO";
56 else if( type == SOCK_RECV ) return "RECV";
57 else if( type == SOCK_RECVFROM ) return "RECVFROM";
58 else return "undefined";
59}
60#endif
61
62/////////////////////////////
63int sys_socket( reg_t arg0,
64 reg_t arg1,
65 reg_t arg2,
66 reg_t arg3 )
67{
68
69 int32_t ret;
70 vseg_t * vseg;
71
72 sockaddr_in_t k_sockaddr; // kernel buffer for one socket address
73
74 thread_t * this = CURRENT_THREAD;
75 process_t * process = this->process;
76
77 uint32_t cmd = arg0;
78
79#if (DEBUG_SYS_SOCKET || CONFIG_INSTRUMENTATION_SYSCALLS)
80uint64_t tm_start = hal_get_cycles();
81#endif
82
83#if DEBUG_SYS_SOCKET
84tm_start = hal_get_cycles();
85if( DEBUG_SYS_SOCKET < tm_start )
86printk("\n[%s] thread[%x,%x] enter / %s / a1 %x / a2 %x / a3 %x / cycle %d\n",
87__FUNCTION__, process->pid, this->trdid, socket_cmd_type_str(cmd),
88arg1, arg2, arg3, (uint32_t)tm_start );
89#endif
90
91 switch( cmd )
92 {
93 /////////////////
94 case SOCK_CREATE:
95 {
96 uint32_t domain = arg1;
97 uint32_t type = arg2;
98
99 if( domain != AF_INET )
100 {
101
102#if DEBUG_SYSCALLS_ERROR
103printk("\n[ERROR] in %s for CREATE domain %d =! AF_INET\n",
104__FUNCTION__ , domain );
105#endif
106 this->errno = EINVAL;
107 ret = -1;
108 break;
109 }
110
111 if( (type != SOCK_DGRAM) && (type != SOCK_STREAM) )
112 {
113
114#if DEBUG_SYSCALLS_ERROR
115printk("\n[ERROR] in %s for CREATE : socket must be SOCK_STREAM(TCP) or SOCK_DGRAM(UDP)\n",
116__FUNCTION__ );
117#endif
118 this->errno = EINVAL;
119 ret = -1;
120 break;
121 }
122
123 // call relevant kernel socket function
124 ret = socket_build( domain , type );
125
126 if( ret == -1 )
127 {
128
129#if DEBUG_SYSCALLS_ERROR
130printk("\n[ERROR] in %s for CREATE : cannot create socket\n",
131__FUNCTION__ );
132#endif
133 this->errno = EINVAL;
134 }
135 break;
136 }
137 ///////////////
138 case SOCK_BIND:
139 {
140 uint32_t fdid = arg1;
141 sockaddr_in_t * u_sockaddr = (sockaddr_in_t *)(intptr_t)arg2;
142
143 // check addr pointer in user space
144 if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
145 {
146
147#if DEBUG_SYSCALLS_ERROR
148printk("\n[ERROR] in %s for BIND : address %x unmapped\n",
149__FUNCTION__ , (intptr_t)arg2 );
150#endif
151 this->errno = EINVAL;
152 ret = -1;
153 break;
154 }
155
156 // copy sockaddr structure from uspace to kernel space
157 hal_copy_from_uspace( XPTR( local_cxy , &k_sockaddr ),
158 u_sockaddr,
159 sizeof(sockaddr_in_t) );
160
161 // call relevant kernel socket function
162 ret = socket_bind( fdid,
163 k_sockaddr.sin_addr,
164 k_sockaddr.sin_port );
165
166 if( ret )
167 {
168
169#if DEBUG_SYSCALLS_ERROR
170printk("\n[ERROR] in %s for BIND : cannot access socket[%x,%d]\n",
171__FUNCTION__ , process->pid, fdid );
172#endif
173 this->errno = EINVAL;
174 }
175 break;
176 }
177 /////////////////
178 case SOCK_LISTEN:
179 {
180 uint32_t fdid = (uint32_t)arg1;
181 uint32_t max_pending = (uint32_t)arg2;
182
183 // call relevant kernel socket function
184 ret = socket_listen( fdid , max_pending );
185
186 if( ret )
187 {
188
189#if DEBUG_SYSCALLS_ERROR
190printk("\n[ERROR] in %s for LISTEN : cannot access socket[%x,%d]\n",
191__FUNCTION__ , process->pid, fdid );
192#endif
193 this->errno = EINVAL;
194 }
195 break;
196 }
197 //////////////////
198 case SOCK_CONNECT:
199 {
200 uint32_t fdid = (uint32_t)arg1;
201 sockaddr_in_t * u_sockaddr = (sockaddr_in_t *)(intptr_t)arg2;
202
203 // check addr pointer in user space
204 if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
205 {
206
207#if DEBUG_SYSCALLS_ERROR
208printk("\n[ERROR] in %s for CONNECT : server address %x unmapped\n",
209__FUNCTION__ , (intptr_t)arg2 );
210#endif
211 this->errno = EINVAL;
212 ret = -1;
213 break;
214 }
215
216 // copy sockaddr structure from uspace to kernel space
217 hal_copy_from_uspace( XPTR( local_cxy , &k_sockaddr ),
218 u_sockaddr ,
219 sizeof(sockaddr_in_t) );
220
221 // call relevant kernel function
222 ret = socket_connect( fdid,
223 k_sockaddr.sin_addr,
224 k_sockaddr.sin_port );
225
226 if( ret )
227 {
228
229#if DEBUG_SYSCALLS_ERROR
230printk("\n[ERROR] in %s for CONNECT : cannot access socket[%x,%d]\n",
231__FUNCTION__ , process->pid, fdid );
232#endif
233 this->errno = EINVAL;
234 }
235 break;
236 }
237 /////////////////
238 case SOCK_ACCEPT:
239 {
240 uint32_t fdid = (uint32_t)arg1;
241 sockaddr_in_t * u_sockaddr = (sockaddr_in_t *)(intptr_t)arg2;
242
243 // check addr pointer in user space
244 if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
245 {
246
247#if DEBUG_SYSCALLS_ERROR
248printk("\n[ERROR] in %s for CONNECT : server address %x unmapped\n",
249__FUNCTION__ , (intptr_t)arg2 );
250#endif
251 this->errno = EINVAL;
252 ret = -1;
253 break;
254 }
255
256 // call relevant kernel function
257 ret = socket_accept( fdid,
258 &k_sockaddr.sin_addr,
259 &k_sockaddr.sin_port );
260
261 if( ret < 0 )
262 {
263
264#if DEBUG_SYSCALLS_ERROR
265printk("\n[ERROR] in %s for ACCEPT : cannot access socket[%x,%d]\n",
266__FUNCTION__ , process->pid, fdid );
267#endif
268 this->errno = EINVAL;
269 }
270
271 // copy sockaddr structure from kernel space to uspace
272 hal_copy_to_uspace( u_sockaddr,
273 XPTR( local_cxy , &k_sockaddr ),
274 sizeof(sockaddr_in_t) );
275
276 break;
277 }
278 ///////////////
279 case SOCK_SEND:
280 {
281 uint32_t fdid = (uint32_t)arg1;
282 uint8_t * u_buf = (uint8_t *)(intptr_t)arg2;
283 uint32_t length = (uint32_t)arg3;
284
285 // check buffer is mapped in user space
286 if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
287 {
288
289#if DEBUG_SYSCALLS_ERROR
290printk("\n[ERROR] in %s for SEND : buffer %x unmapped\n",
291__FUNCTION__ , (intptr_t)arg2 );
292#endif
293 this->errno = EINVAL;
294 ret = -1;
295 break;
296 }
297
298 // check length
299 if( length == 0 )
300 {
301
302#if DEBUG_SYSCALLS_ERROR
303printk("\n[ERROR] in %s for SEND : buffer length is 0\n",
304__FUNCTION__ , (intptr_t)arg2 );
305#endif
306 this->errno = EINVAL;
307 ret = -1;
308 break;
309 }
310
311 // cal relevant relevant socket function
312 ret = socket_send( fdid , u_buf , length );
313
314 if( ret < 0 )
315 {
316
317#if DEBUG_SYSCALLS_ERROR
318printk("\n[ERROR] in %s for SEND : cannot access socket[%x,%d] \n",
319__FUNCTION__ , process->pid, fdid );
320#endif
321 this->errno = EINVAL;
322 }
323 break;
324 }
325 ///////////////
326 case SOCK_RECV:
327 {
328 uint32_t fdid = (uint32_t)arg1;
329 uint8_t * u_buf = (uint8_t *)(intptr_t)arg2;
330 uint32_t length = (uint32_t)arg3;
331
332 // check buffer is mapped in user space
333 if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
334 {
335
336#if DEBUG_SYSCALLS_ERROR
337printk("\n[ERROR] in %s for SEND : buffer %x unmapped\n",
338__FUNCTION__ , (intptr_t)arg2 );
339#endif
340 this->errno = EINVAL;
341 ret = -1;
342 break;
343 }
344
345 // check length
346 if( length == 0 )
347 {
348
349#if DEBUG_SYSCALLS_ERROR
350printk("\n[ERROR] in %s for SEND : buffer length is 0\n",
351__FUNCTION__ , (intptr_t)arg2 );
352#endif
353 this->errno = EINVAL;
354 ret = -1;
355 break;
356 }
357
358 // cal relevant kernel socket function
359 ret = socket_recv( fdid , u_buf , length );
360
361 if( ret < 0 )
362 {
363
364#if DEBUG_SYSCALLS_ERROR
365printk("\n[ERROR] in %s for RECV : cannot access socket[%x,%d] \n",
366__FUNCTION__ , process->pid, fdid );
367#endif
368 this->errno = EINVAL;
369 }
370 break;
371 }
372 ////////
373 default:
374 {
375
376#if DEBUG_SYSCALLS_ERROR
377printk("\n[ERROR] in %s : undefined socket operation %d\n",
378 __FUNCTION__ , cmd );
379#endif
380 this->errno = EINVAL;
381 ret = -1;
382 break;
383 }
384 } // end switch on cmd
385
386#if (DEBUG_SYS_SOCKET || CONFIG_INSTRUMENTATION_SYSCALLS)
387uint64_t tm_end = hal_get_cycles();
388#endif
389
390#if DEBUG_SYS_SOCKET
391if( DEBUG_SYS_SOCKET < tm_end )
392printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
393__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
394#endif
395
396#if CONFIG_INSTRUMENTATION_SYSCALLS
397hal_atomic_add( &syscalls_cumul_cost[SYS_SOCKET] , tm_end - tm_start );
398hal_atomic_add( &syscalls_occurences[SYS_SOCKET] , 1 );
399#endif
400
401 return ret;
402
403} // end sys_socket()
Note: See TracBrowser for help on using the repository browser.