1/* 2 * Copyright (c) 2011, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <unistd.h> 14#include <barrelfish/barrelfish.h> 15#include <barrelfish/spawn_client.h> 16#include <posixcompat.h> 17#include <lwip/sock_serialise.h> 18#include <vfs/fdtab.h> 19 20struct fd_store { 21 int num; 22 enum fdtab_type type; 23 void *handle; 24 int fd; 25}; 26 27struct posixcompat_sockinfo { 28}; 29 30/* Copying the actual handles is hard. 31 * We could try a deep copy, but really we should come up with a serialised 32 * format for each type. It also involves implementing the underlying 33 * resources such that the descriptors can actually be used in the new 34 * dispatcher. 35 */ 36 37static size_t copy_file_fd(void *dest, genpaddr_t offset, struct fd_store *fds) 38{ 39 assert(!"NYI"); 40 return 0; 41} 42 43static void debug_uipaddr_print(u32_t addr) 44{ 45 debug_printf("%"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 46 (u16_t)((ntohl(addr) >> 24) & 0xff), 47 (u16_t)((ntohl(addr) >> 16) & 0xff), 48 (u16_t)((ntohl(addr) >> 8) & 0xff), 49 (u16_t)(ntohl(addr) & 0xff)); 50} 51 52static void debug_ipaddr_print(struct ip_addr *ipaddr) { 53 u32_t addr = ipaddr->addr; 54 debug_uipaddr_print(addr); 55 56} 57 58static size_t copy_lwip_fd(void *dest, genpaddr_t offset, struct fd_store *fds) 59{ 60 size_t size = sizeof(struct lwip_sockinfo); 61 62 struct lwip_sockinfo si; 63 lwip_serialise_sock(fds->fd, &si); 64 65 printf("LWIP socket\n\tfd: %d\n", fds->fd); 66 debug_printf("local port and ip: %u\n", si.local_port); 67 debug_ipaddr_print(&si.local_ip); 68 debug_printf("remote port and ip: %u\n", si.remote_port); 69 debug_ipaddr_print(&si.remote_ip); 70 71 printf("copying %zu bytes from %p to %p\n", size, &fds->handle, dest); 72 memcpy(dest, &si, size); 73 fds->handle = (void *)(uintptr_t)(offset); 74 printf("fd %d fixed handle is: %d\n", fds->num, fds->fd); 75 76 return size; 77} 78 79static size_t copy_unixsock_fd(void *dest, genpaddr_t offset, 80 struct fd_store *fds) 81{ 82 assert(!"NYI"); 83 return 0; 84} 85 86 87/** 88 * \brief Setup inherited file descriptors 89 * 90 */ 91errval_t spawn_setup_fds(struct capref *frame, int rfd) 92{ 93 errval_t err; 94 void *fdspg; 95 96 // Create frame (actually multiple pages) for fds 97 err = frame_alloc(frame, FDS_SIZE, NULL); 98 if (err_is_fail(err)) { 99 return err_push(err, SPAWN_ERR_CREATE_FDSPG); 100 } 101 102 // map it in so we can write to it 103 err = vspace_map_one_frame(&fdspg, FDS_SIZE, *frame, NULL, NULL); 104 if (err_is_fail(err)) { 105 return err_push(err, SPAWN_ERR_MAP_FDSPG_TO_SELF); 106 } 107 108 /* Layout of FD page: 109 * int num_fds 110 * struct fd_store fdtab[num_fds] 111 * uint8_t buf[] // store of actual handle data. entries in fdtab above 112 * // point here (relative offset from the beginning of buf). 113 * TODO: add the actual handle data! 114 */ 115 int *num_fds = (int *)fdspg; 116 *num_fds = 0; 117 struct fd_store *fdtab = (struct fd_store *)(num_fds + 1); 118 119 /* first copy all the fd table entries */ 120 struct fdtab_entry *fde; 121 struct fd_store *fds; 122 int i = 0; 123 for (i = MIN_FD; i < MAX_FD; i++) { 124 fde = fdtab_get(i); 125 if (fde->type == FDTAB_TYPE_LWIP_SOCKET) { 126 fds = &fdtab[*num_fds]; 127 fds->num = i; 128 fds->type = fde->type; 129 fds->handle = fde->handle; 130 fds->fd = fde->fd; 131 // Mark the inherited fd accordingly 132 fde->inherited = 1; 133 printf("added fd %d to fdtabs[%d]: %p as fd_store (%p: num: %d, " 134 "type: %d, (unfixed)handle: %p)\n", 135 i, *num_fds, &fdtab[*num_fds], fds, fds->num, fds->type, 136 fds->handle); 137 (*num_fds)++; 138 } 139 } 140 141 /* then copy all the handle data to the buffer */ 142 char *buf = (char *)&fdtab[*num_fds]; 143 char *dest = buf; 144 genpaddr_t offset; 145 size_t size; 146 for (i = 0; i < *num_fds; i++) { 147 fds = &fdtab[i]; 148 offset = (genpaddr_t)(dest - buf); 149 switch (fds->type) { 150 case FDTAB_TYPE_FILE: 151 size = copy_file_fd(dest, offset, fds); 152 break; 153 case FDTAB_TYPE_UNIX_SOCKET: 154 size = copy_unixsock_fd(dest, offset, fds); 155 break; 156 case FDTAB_TYPE_LWIP_SOCKET: 157 size = copy_lwip_fd(dest, offset, fds); 158 break; 159 default: 160 // nothing to copy 161 size = 0; 162 break; 163 } 164 dest += size; 165 } 166 167 // unmap frame 168 err = vspace_unmap(fdspg); 169 170 return err; 171} 172 173errval_t posixcompat_unpack_fds(void) 174{ 175 errval_t err; 176 177 /* Map the FD buffer into our address space. */ 178 struct capref frame = { 179 .cnode = cnode_task, 180 .slot = TASKCN_SLOT_FDSPAGE, 181 }; 182 183 struct frame_identity fi; 184 err = frame_identify(frame, &fi); 185 if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) { 186 // we don't have a FD buffer, return OK 187 return SYS_ERR_OK; 188 } else if (!err_is_ok(err)) { 189 // frame identify failed, return error 190 return err_push(err, LIB_ERR_FRAME_IDENTIFY); 191 } 192 193 void *fdspg; 194 err = vspace_map_one_frame(&fdspg, FDS_SIZE, frame, NULL, NULL); 195 if (err_is_fail(err)) { 196 return err_push(err, SPAWN_ERR_MAP_FDSPG_TO_SELF); 197 } 198 199 int *num_fds = (int *)fdspg; 200 struct fd_store *fdtab = (struct fd_store *)(num_fds + 1); 201 char *buf = (char *)&fdtab[*num_fds]; 202 203 /* first copy all the fd table entries */ 204 int i; 205 for (i = 0; i < *num_fds; i++) { 206 struct fd_store *fds = &fdtab[i]; 207 struct fdtab_entry fde; 208 209 assert(fds->type == FDTAB_TYPE_LWIP_SOCKET); 210 211 fde.type = FDTAB_TYPE_LWIP_SOCKET; 212 fde.fd = lwip_socket(AF_INET, SOCK_STREAM, 0); 213 214 struct lwip_sockinfo *si = (struct lwip_sockinfo *)(buf + (uintptr_t)fds->handle); 215 lwip_deserialise_sock(fde.fd, si); 216 debug_printf("local port and ip: %u\n", si->local_port); 217 debug_ipaddr_print(&si->local_ip); 218 debug_printf("remote port and ip: %u\n", si->remote_port); 219 debug_ipaddr_print(&si->remote_ip); 220 221 int fd = fdtab_alloc_from(&fde, fds->num); 222 assert(fd == fds->num); 223 224 printf("restored fd %d from fdtabs[%d]: %p as fd_store (%p: num: %d, " 225 "type: %d, (unfixed)handle: %p)\n", 226 fds->num, i, &fdtab[i], fds, fds->num, fds->type, 227 fds->handle); 228 229 } 230 231 // unmap frame 232 err = vspace_unmap(fdspg); 233 234 return err; 235} 236