akaros/tools/syscall_server/syscall_server.c
<<
>>
Prefs
   1#include <stdlib.h>
   2#include <unistd.h>
   3#include <errno.h>
   4#include <fcntl.h>
   5#include <stdio.h>
   6#include <sys/stat.h>
   7#include <malloc.h>
   8#include <termios.h>
   9#include <strings.h>
  10#include "syscall_server.h"
  11
  12#define debug(...) printf(__VA_ARGS__)  
  13
  14int main()
  15{
  16        run_server();
  17        return 0;
  18}
  19
  20// Poll for incoming messages and send responses. 
  21void run_server() 
  22{
  23        // Struct for reading the syscall over the channel
  24        syscall_req_t syscall_req;
  25        syscall_rsp_t syscall_rsp;
  26        
  27        int fd_read, fd_write;
  28        int ret = init_syscall_server(&fd_read, &fd_write);
  29        if(ret < 0)
  30                error(ret, "Could not open file desciptors for communication\n");
  31
  32        printf("Server started....");
  33        // Continuously read in data from the channel socket
  34        while(1) {
  35                syscall_req.payload_len = 0;
  36                syscall_req.payload = NULL;
  37                syscall_rsp.payload_len = 0;
  38                syscall_rsp.payload = NULL;
  39        
  40                debug("\nWaiting for syscall...\n");
  41                read_syscall_req(fd_read, &syscall_req);        
  42
  43                debug("Processing syscall: %d\n", syscall_req.header.id);
  44                handle_syscall(&syscall_req, &syscall_rsp);
  45
  46                debug("Writing response: %d\n", syscall_req.header.id);
  47                write_syscall_rsp(fd_write, &syscall_rsp);
  48
  49                if(syscall_req.payload != NULL) 
  50                        free(syscall_req.payload);
  51                if(syscall_rsp.payload != NULL)
  52                        free(syscall_rsp.payload);
  53        }
  54}
  55
  56void read_syscall_req(int fd, syscall_req_t* req) 
  57{
  58        read_syscall_req_header(fd, req);
  59        set_syscall_req_payload_len(req);
  60        read_syscall_req_payload(fd, req);
  61}
  62
  63void set_syscall_req_payload_len(syscall_req_t* req)
  64{
  65        switch(req->header.id) {
  66                case OPEN_ID:
  67                        req->payload_len = req->header.subheader.open.len;
  68                        break;
  69                case WRITE_ID:
  70                        req->payload_len = req->header.subheader.write.len;
  71                        break;
  72                case LINK_ID:
  73                        req->payload_len = req->header.subheader.link.old_len
  74                                           + req->header.subheader.link.new_len;
  75                        break;
  76                case UNLINK_ID:
  77                        req->payload_len = req->header.subheader.unlink.len;
  78                        break;
  79                case STAT_ID:
  80                        req->payload_len = req->header.subheader.stat.len;
  81                        break;
  82        }
  83}
  84
  85void read_syscall_req_header(int fd, syscall_req_t* req) 
  86{
  87        // Try to read the syscall id from the socket.
  88        // If no data available, spin until there is
  89        int bytes_read = 0;
  90        bytes_read = read_from_channel(fd, &req->header, sizeof(req->header.id), 0);
  91
  92        // If no data, or the ID we got is bad, terminate process.
  93        uint32_t id = req->header.id;
  94        if ((bytes_read < 0) || (id < 0) || (id > NUM_SYSCALLS)) {
  95                perror("Problems reading the id from the channel...");
  96        }
  97
  98        // Otherwise, start grabbing the rest of the data
  99        bytes_read = read_from_channel(fd, &req->header.subheader, 
 100                                  sizeof(req->header.subheader) , 0);
 101        if(bytes_read < 0)
 102                error(fd, "Problems reading header from the channel...");
 103}
 104
 105void read_syscall_req_payload(int fd, syscall_req_t* req) {
 106        if (req->payload_len == 0)
 107                return;
 108                
 109        req->payload = malloc(req->payload_len);
 110        if (req->payload == NULL) 
 111                error(fd, "No free memory!");
 112
 113        int bytes_read = read_from_channel(fd, req->payload, req->payload_len, 0);
 114        if (bytes_read < 0)
 115                error(fd, "Problems reading payload from channel");
 116}
 117
 118// Read len bytes from the given socket to the buffer.
 119// If peek is 0, will wait indefinitely until that much data is read.
 120// If peek is 1, if no data is available, will return immediately.
 121int read_from_channel(int fd, void* buf, int len, int peek) 
 122{
 123        int total_read = 0;
 124        int just_read = read_syscall_server(fd, buf, len);
 125
 126        if (just_read < 0) return just_read;
 127        if (just_read == 0 && peek) return just_read;
 128
 129        total_read += just_read;
 130
 131        while (total_read != len) {
 132                just_read = read_syscall_server(fd, buf + total_read, len - total_read);
 133                if (just_read < 0) return just_read;
 134                total_read += just_read;
 135        }
 136        return total_read;
 137}
 138
 139// Send CONNECTION_TERMINATED over the FD (if possible)
 140void error(int fd, const char* s)
 141{
 142        fprintf(stderr, "Error: FD: %i\n",fd);
 143        perror(s);
 144    fprintf(stderr, "Sending CONNECTION_TERMINATED.... \n");
 145        close(fd);
 146        exit(-1);
 147}
 148
 149void handle_syscall(syscall_req_t* req, syscall_rsp_t* rsp)
 150{
 151        switch (req->header.id) {
 152                case OPEN_ID:
 153                        handle_open(req, rsp);
 154                        break;
 155                case CLOSE_ID:
 156                        handle_close(req, rsp);
 157                        break;
 158                case READ_ID:
 159                        handle_read(req, rsp);
 160                        break;
 161                case WRITE_ID:
 162                        handle_write(req, rsp);
 163                        break;
 164                case LINK_ID:
 165                        handle_link(req, rsp);
 166                        break;
 167                case UNLINK_ID:
 168                        handle_unlink(req, rsp);
 169                        break;
 170                case LSEEK_ID:
 171                        handle_lseek(req, rsp);
 172                        break;
 173                case FSTAT_ID:
 174                        handle_fstat(req, rsp);
 175                        break;
 176                case ISATTY_ID:
 177                        handle_isatty(req, rsp);
 178                        break;
 179                case STAT_ID:
 180                        handle_stat(req, rsp);
 181                        break;
 182                default:
 183                        error(-1, "Illegal syscall, should never be here...");
 184        }
 185        
 186        rsp->header.return_errno = errno;
 187}
 188
 189void write_syscall_rsp(int fd, syscall_rsp_t* rsp) 
 190{
 191        write_syscall_rsp_header(fd, rsp);
 192        write_syscall_rsp_payload(fd, rsp);
 193}
 194
 195void write_syscall_rsp_header(int fd, syscall_rsp_t* rsp) 
 196{
 197        int written = write_syscall_server(fd, (char*)&rsp->header, 
 198                           sizeof(syscall_rsp_header_t), rsp->payload_len);
 199        if (written < 0)
 200                error(fd, "Problems writing the syscall response header...");   
 201}
 202
 203void write_syscall_rsp_payload(int fd, syscall_rsp_t* rsp) 
 204{
 205        if(rsp->payload_len == 0)
 206                return;
 207
 208        int written = write_syscall_server(fd, rsp->payload, rsp->payload_len, 0);
 209        if (written < 0)
 210                error(fd, "Problems writing the syscall response payload...");  
 211        if (written < rsp->payload_len)
 212                error(fd, "Problems writing all bytes in the response payload...");     
 213}
 214
 215char* sandbox_file_name(char* name, uint32_t len) {
 216        char* new_name = malloc(len + sizeof(SANDBOX_DIR) - 1);
 217        if (new_name == NULL) 
 218                perror("No free memory!");
 219        sprintf(new_name, "%s%s", SANDBOX_DIR, name);
 220        printf("%s\n", new_name);
 221        return new_name;
 222}
 223
 224void handle_open(syscall_req_t* req, syscall_rsp_t* rsp)
 225{
 226        char* name = sandbox_file_name(req->payload, req->payload_len);
 227        open_subheader_t* o = &req->header.subheader.open;      
 228        int native_flags = translate_flags(o->flags);
 229        int native_mode = translate_mode(o->mode);
 230        rsp->header.return_val = open(name, native_flags, native_mode);
 231        free(name);
 232}
 233
 234void handle_close(syscall_req_t* req, syscall_rsp_t* rsp)
 235{
 236        close_subheader_t* c = &req->header.subheader.close;    
 237        rsp->header.return_val = close(c->fd);
 238}
 239
 240void handle_read(syscall_req_t* req, syscall_rsp_t* rsp)
 241{
 242        read_subheader_t* r = &req->header.subheader.read;      
 243        rsp->payload = malloc(r->len);
 244        if (rsp->payload == NULL) 
 245                perror("No free memory!");
 246        rsp->header.return_val = read(r->fd, rsp->payload, r->len);
 247        if(rsp->header.return_val >= 0)
 248                rsp->payload_len = rsp->header.return_val;
 249}
 250
 251void handle_write(syscall_req_t* req, syscall_rsp_t* rsp)
 252{
 253        write_subheader_t* w = &req->header.subheader.write;    
 254        rsp->header.return_val = write(w->fd, req->payload, w->len);
 255}
 256
 257void handle_link(syscall_req_t* req, syscall_rsp_t* rsp)
 258{
 259        link_subheader_t* l = &req->header.subheader.link;      
 260        char* old_name = sandbox_file_name(req->payload, l->old_len);
 261        char* new_name = sandbox_file_name(req->payload + l->old_len, l->new_len);
 262        rsp->header.return_val = link(old_name, new_name); 
 263        free(old_name);
 264        free(new_name);
 265}
 266
 267void handle_unlink(syscall_req_t* req, syscall_rsp_t* rsp)
 268{
 269        char* name = sandbox_file_name(req->payload, req->payload_len);
 270        rsp->header.return_val = unlink(name); 
 271        free(name);
 272}
 273
 274void handle_lseek(syscall_req_t* req, syscall_rsp_t* rsp)
 275{
 276        lseek_subheader_t* l = &req->header.subheader.lseek;    
 277        int native_whence = translate_whence(l->dir); 
 278        rsp->header.return_val = lseek(l->fd, l->ptr, native_whence);
 279}
 280
 281void handle_fstat(syscall_req_t* req, syscall_rsp_t* rsp)
 282{
 283        struct stat native_struct;
 284        fstat_subheader_t* f = &req->header.subheader.fstat;    
 285        rsp->payload = malloc(sizeof(newlib_stat_t));
 286        if (rsp->payload == NULL) 
 287                perror("No free memory!");
 288        rsp->header.return_val = fstat(f->fd, &native_struct); 
 289        if(rsp->header.return_val >= 0)
 290                rsp->payload_len = sizeof(newlib_stat_t);
 291        
 292        translate_stat(&native_struct, (newlib_stat_t*)(rsp->payload));
 293}
 294
 295void handle_isatty(syscall_req_t* req, syscall_rsp_t* rsp)
 296{
 297        isatty_subheader_t* i = &req->header.subheader.isatty;  
 298        rsp->header.return_val = isatty(i->fd); 
 299}
 300
 301void handle_stat(syscall_req_t* req, syscall_rsp_t* rsp)
 302{
 303        struct stat native_struct;
 304        rsp->payload = malloc(sizeof(newlib_stat_t));
 305        if (rsp->payload == NULL) 
 306                perror("No free memory!");
 307        rsp->header.return_val = stat(req->payload, &native_struct); 
 308        if(rsp->header.return_val >= 0)
 309                rsp->payload_len = sizeof(newlib_stat_t);
 310
 311        translate_stat(&native_struct, (newlib_stat_t*)(rsp->payload));
 312}
 313
 314