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

Last change on this file since 670 was 670, checked in by alain, 3 years ago

1) Introduce up to 4 command lines arguments in the KSH "load" command.
These arguments are transfered to the user process through the
argc/argv mechanism, using the user space "args" vseg.

2) Introduce the named and anonymous "pipes", for inter-process communication
through the pipe() and mkfifo() syscalls.

3) Introduce the "chat" application to validate the two above mechanisms.

4) Improve printk() and assert() fonctions in printk.c.

File size: 12.8 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_RECV        ) return "RECV"; 
56    else                                return "undefined";
57}
58#endif
59
60/////////////////////////////
61int sys_socket( reg_t  arg0,
62                reg_t  arg1,
63                reg_t  arg2,
64                reg_t  arg3 )
65{
66    int             ret;
67    vseg_t        * vseg;
68
69    sockaddr_in_t   k_sockaddr;  // kernel buffer for one socket address
70
71    thread_t      * this    = CURRENT_THREAD;
72    process_t     * process = this->process;
73
74    uint32_t        cmd = arg0;
75
76#if DEBUG_SYS_SOCKET || DEBUG_SYSCALLS_ERROR || CONFIG_INSTRUMENTATION_SYSCALLS
77uint64_t     tm_start = hal_get_cycles();
78#endif
79
80#if DEBUG_SYS_SOCKET
81if( DEBUG_SYS_SOCKET < (uint32_t)tm_start )
82printk("\n[%s] thread[%x,%x] enter / %s / a1 %x / a2 %x / a3 %x / cycle %d\n",
83__FUNCTION__, process->pid, this->trdid, socket_cmd_type_str(cmd), 
84arg1, arg2, arg3, (uint32_t)tm_start );
85#endif
86
87    switch( cmd )
88    {
89        /////////////////
90        case SOCK_CREATE:
91        {
92            uint32_t domain = arg1;
93            uint32_t type   = arg2;
94
95            if( domain != AF_INET )
96            {
97
98#if DEBUG_SYSCALLS_ERROR
99if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
100printk("\n[ERROR] in %s : thread[%x,%x] / CREATE / domain %d =! AF_INET\n",
101__FUNCTION__ , process->pid , this->trdid , domain );
102#endif
103                this->errno = EINVAL;
104                ret = -1;
105                break;
106            }
107
108            if( (type != SOCK_DGRAM) && (type != SOCK_STREAM) )
109            {
110
111#if DEBUG_SYSCALLS_ERROR
112if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
113printk("\n[ERROR] in %s : thread[%x,%x] / CREATE / illegal socket type\n",
114__FUNCTION__ , process->pid , this->trdid );
115#endif
116                this->errno = EINVAL;
117                ret = -1;
118                break;
119            }
120
121            // call relevant kernel socket function
122            ret = socket_build( domain , type );
123
124            if( ret < 0 )
125            {
126
127#if DEBUG_SYSCALLS_ERROR
128if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
129printk("\n[ERROR] in %s : thread[%x,%x] / CREATE / cannot create socket\n",
130__FUNCTION__ , process->pid , this->trdid );
131#endif
132                this->errno = EINVAL;
133                ret = -1;
134                break;
135            }
136
137            break;
138        }
139        ///////////////
140        case SOCK_BIND:
141        {
142            uint32_t        fdid = arg1;
143            sockaddr_in_t * u_sockaddr = (sockaddr_in_t *)(intptr_t)arg2;
144
145            // check addr pointer in user space
146            if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
147            {
148
149#if DEBUG_SYSCALLS_ERROR
150if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
151printk("\n[ERROR] in %s : thread[%x,%x] / BIND / socket address %x unmapped\n",
152__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg2 );
153#endif
154                this->errno = EINVAL;
155                ret = -1;
156                break;
157            }
158
159            // copy sockaddr structure from uspace to kernel space
160            hal_copy_from_uspace( XPTR( local_cxy , &k_sockaddr ),
161                                  u_sockaddr, 
162                                  sizeof(sockaddr_in_t) );
163
164            // call relevant kernel socket function
165                ret = socket_bind( fdid,
166                               k_sockaddr.sin_addr,
167                               k_sockaddr.sin_port );
168
169            if( ret < 0 )
170            {
171
172#if DEBUG_SYSCALLS_ERROR
173if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
174printk("\n[ERROR] in %s : thread[%x,%x] / BIND / cannot access socket[%x,%d]\n",
175__FUNCTION__ , process->pid , this->trdid ,  process->pid, fdid );
176#endif
177                this->errno = EINVAL;
178                ret = -1;
179                break;
180            }
181
182            break;
183        }
184        /////////////////
185        case SOCK_LISTEN:
186        {
187            uint32_t     fdid        = (uint32_t)arg1;
188            uint32_t     max_pending = (uint32_t)arg2;
189
190            // call relevant kernel socket function
191                ret = socket_listen( fdid , max_pending );
192
193            if( ret < 0 )
194            {
195
196#if DEBUG_SYSCALLS_ERROR
197if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
198printk("\n[ERROR] in %s : thread[%x,%x] / LISTEN / cannot access socket[%x,%d]\n",
199__FUNCTION__ , process->pid , this->trdid ,  process->pid, fdid );
200#endif
201                this->errno = EINVAL;
202                ret = -1;
203                break;
204            }
205
206            break;
207        }
208        //////////////////
209        case SOCK_CONNECT:
210        {
211            uint32_t        fdid = (uint32_t)arg1;
212            sockaddr_in_t * u_sockaddr = (sockaddr_in_t *)(intptr_t)arg2;
213
214            // check addr pointer in user space
215            if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
216            {
217
218#if DEBUG_SYSCALLS_ERROR
219if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
220printk("\n[ERROR] in %s : thread[%x,%x] / CONNECT / server address %x unmapped\n",
221__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg2 );
222#endif
223                this->errno = EINVAL;
224                ret = -1;
225                break;
226            }
227
228            // copy sockaddr structure from uspace to kernel space
229            hal_copy_from_uspace( XPTR( local_cxy , &k_sockaddr ),
230                                  u_sockaddr ,
231                                  sizeof(sockaddr_in_t) );
232
233            // call relevant kernel function
234                ret = socket_connect( fdid,
235                                  k_sockaddr.sin_addr,
236                                  k_sockaddr.sin_port );
237            if( ret < 0 )
238            {
239
240#if DEBUG_SYSCALLS_ERROR
241if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
242printk("\n[ERROR] in %s : thread[%x,%x] / LISTEN / cannot access socket[%x,%d]\n",
243__FUNCTION__ , process->pid , this->trdid ,  process->pid, fdid );
244#endif
245                this->errno = EINVAL;
246                ret = -1;
247                break;
248            }
249
250            break;
251        }
252        /////////////////
253        case SOCK_ACCEPT:
254        {
255            uint32_t        fdid = (uint32_t)arg1;
256            sockaddr_in_t * u_sockaddr = (sockaddr_in_t *)(intptr_t)arg2;
257
258            // check addr pointer in user space
259            if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
260            {
261
262#if DEBUG_SYSCALLS_ERROR
263if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
264printk("\n[ERROR] in %s : thread[%x,%x] / CONNECT / server address %x unmapped\n",
265__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg2 );
266#endif
267                this->errno = EINVAL;
268                ret = -1;
269                break;
270            }
271
272            // call relevant kernel function
273            ret = socket_accept( fdid,
274                                 &k_sockaddr.sin_addr, 
275                                 &k_sockaddr.sin_port );
276
277            if( ret )
278            {
279
280#if DEBUG_SYSCALLS_ERROR
281if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
282printk("\n[ERROR] in %s : thread[%x,%x] / ACCEPT / cannot access socket[%x,%d]\n",
283__FUNCTION__ , process->pid , this->trdid , process->pid, fdid );
284#endif
285                this->errno = EINVAL;
286            }
287
288            // copy sockaddr structure from kernel space to uspace
289            hal_copy_to_uspace( u_sockaddr,
290                                XPTR( local_cxy , &k_sockaddr ),
291                                sizeof(sockaddr_in_t) );
292
293            break;
294        }
295        ///////////////
296        case SOCK_SEND:
297        {
298            uint32_t     fdid   = (uint32_t)arg1;
299            uint8_t    * u_buf  = (uint8_t *)(intptr_t)arg2;
300            uint32_t     length = (uint32_t)arg3;
301
302            // check buffer is mapped in user space
303            if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
304            {
305
306#if DEBUG_SYSCALLS_ERROR
307if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
308printk("\n[ERROR] in %s : thread[%x,%x] / SEND / buffer %x unmapped\n",
309__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg2 );
310#endif
311                this->errno = EINVAL;
312                ret = -1;
313                break;
314            }
315
316            // check length
317            if( length == 0 )
318            {
319
320#if DEBUG_SYSCALLS_ERROR
321if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
322printk("\n[ERROR] in %s : thread[%x,%x] / SEND / buffer length is 0\n",
323__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg2 );
324#endif
325                this->errno = EINVAL;
326                ret = -1;
327                break;
328            }
329
330            // cal relevant relevant socket function
331            ret = socket_send( fdid , u_buf , length );
332
333            if( ret < 0 )
334            {
335
336#if DEBUG_SYSCALLS_ERROR
337if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
338printk("\n[ERROR] in %s : thread[%x,%x] / SEND / cannot access socket[%x,%d] \n",
339__FUNCTION__ , process->pid , this->trdid , process->pid, fdid );
340#endif
341                this->errno = EINVAL;
342            }
343            break;
344        }
345        ///////////////
346        case SOCK_RECV:
347        {
348            uint32_t     fdid   = (uint32_t)arg1;
349            uint8_t    * u_buf  = (uint8_t *)(intptr_t)arg2;
350            uint32_t     length = (uint32_t)arg3;
351
352            // check buffer is mapped in user space
353            if( vmm_get_vseg( process , (intptr_t)arg2 , &vseg ) )
354            {
355
356#if DEBUG_SYSCALLS_ERROR
357if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
358printk("\n[ERROR] in %s : thread[%x,%x] / RECV / buffer %x unmapped\n",
359__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg2 );
360#endif
361                this->errno = EINVAL;
362                ret = -1;
363                break;
364            }
365
366            // check length
367            if( length == 0 )
368            {
369
370#if DEBUG_SYSCALLS_ERROR
371if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
372printk("\n[ERROR] in %s : thread[%x,%x] / RECV / buffer length is 0\n",
373__FUNCTION__ , process->pid , this->trdid , (intptr_t)arg2 );
374#endif
375                this->errno = EINVAL;
376                ret = -1;
377                break;
378            }
379
380            // cal relevant kernel socket function
381            ret =  socket_recv( fdid , u_buf , length );
382
383            if( ret < 0 )
384            {
385
386#if DEBUG_SYSCALLS_ERROR
387if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
388printk("\n[ERROR] in %s : thread[%x,%x] / RECV / cannot access socket[%x,%d] \n",
389__FUNCTION__ , process->pid , this->trdid , process->pid, fdid );
390#endif
391                this->errno = EINVAL;
392            }
393            break;
394        }
395        ////////
396        default: 
397        {
398
399#if DEBUG_SYSCALLS_ERROR
400if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
401printk("\n[ERROR] in %s : thread[%x,%x] / undefined socket operation %d\n",
402__FUNCTION__ , process->pid , this->trdid , cmd );
403#endif
404            this->errno = EINVAL;
405            ret = -1;
406            break;
407        }
408    }  // end switch on cmd
409
410#if (DEBUG_SYS_SOCKET || CONFIG_INSTRUMENTATION_SYSCALLS)
411uint64_t     tm_end = hal_get_cycles();
412#endif
413
414#if DEBUG_SYS_SOCKET
415if( DEBUG_SYS_SOCKET < tm_end )
416printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
417__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
418#endif
419
420#if CONFIG_INSTRUMENTATION_SYSCALLS
421hal_atomic_add( &syscalls_cumul_cost[SYS_SOCKET] , tm_end - tm_start );
422hal_atomic_add( &syscalls_occurences[SYS_SOCKET] , 1 );
423#endif
424
425    return ret;
426
427}  // end sys_socket()
Note: See TracBrowser for help on using the repository browser.