Initial Commit
[Projects.git] / pkgbuilds / wiifuse / src / wiifuse-0.2.0 / server / source / server.c
blob146672f1419f53b4ecaf8f032658e6e1d54fc1db
1 /*
2 * Copyright (C) 2008 dhewg, #wiidev efnet
4 * this file is part of wiifuse
5 * http://wiibrew.org/index.php?title=Wiifuse
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <malloc.h>
27 #include <gccore.h>
28 #include <ogcsys.h>
29 #include <ogc/es.h>
31 #include "../../shared.h"
32 #include "global.h"
33 #include "fs_wrapper.h"
34 #include "usb.h"
36 // TODO
37 // use the "authenticated" flag before executing commands
38 // kick out clients when receiving another auth
39 // take usb.c from libdb instead
40 struct client_request * read_request () {
41 u8 buf[PACKET_REQUEST_PAYLOAD];
42 struct client_request *request;
43 u8 fn_size;
45 LOG (3, "waiting for a request...");
46 usb_receivebuffersafe (buf, PACKET_REQUEST_PAYLOAD);
48 if (buf[0] != 'W' || buf[1] != 'F' || buf[2] != 'R')
49 return NULL;
51 request = (struct client_request *)
52 malloc (sizeof (struct client_request));
53 memset (request, 0, sizeof (struct client_request));
55 request->command = buf[3];
56 fn_size = buf[4];
57 request->data_size = get_be16 (&buf[5]);
59 if (fn_size) {
60 request->filename = malloc (fn_size + 1);
61 LOG (3, "waiting for filename (%d)", fn_size);
62 usb_receivebuffersafe (request->filename, fn_size);
63 request->filename[fn_size] = 0;
66 if (request->data_size) {
67 request->data = malloc (request->data_size);
68 LOG (3, "waiting for data (%d)", request->data_size);
69 usb_receivebuffersafe (request->data, request->data_size);
72 return request;
75 void send_response (const enum remote_result result, const u8 *data,
76 const u16 data_size) {
77 u8 buf[PACKET_RESPONSE_PAYLOAD];
79 memset (buf, 0, PACKET_RESPONSE_PAYLOAD);
81 buf[0] = 'W';
82 buf[1] = 'F';
83 buf[2] = 'A';
85 buf[3] = result;
87 if (data)
88 put_be16 (&buf[4], data_size);
90 LOG (3, "sending response");
91 usb_sendbuffersafe (buf, PACKET_RESPONSE_PAYLOAD);
93 if (data) {
94 LOG (3, "sending response data (%d)", data_size);
95 usb_sendbuffersafe (data, data_size);
99 enum remote_result identify (struct client_request *request, u8 **data,
100 u16 *data_size) {
101 u8 *p;
103 u32 certs_size;
104 u32 tmd_size;
105 u32 tik_size;
106 u8 *sb_certs;
107 u8 *sb_tmd;
108 u8 *sb_tik;
110 s32 res;
111 u64 title_id;
112 u16 gid;
114 if (!request->data || request->data_size < 6)
115 return RES_UNKNOWN;
117 p = request->data;
119 certs_size = get_be16 (p);
120 p += 2;
122 tmd_size = get_be16 (p);
123 p += 2;
125 tik_size = get_be16 (p);;
126 p += 2;
128 if (request->data_size != certs_size + tmd_size + tik_size + 6)
129 return RES_UNKNOWN;
131 sb_certs = memalign (32, certs_size);
132 memcpy (sb_certs, p, certs_size);
133 p += certs_size;
135 sb_tmd = memalign (32, tmd_size);
136 memcpy (sb_tmd, p, tmd_size);
137 p += tmd_size;
139 sb_tik = memalign (32, tik_size);
140 memcpy (sb_tik, p, tik_size);
142 printf ("identifying...\n");
144 res = ES_Identify ((signed_blob *) sb_certs, certs_size,
145 (signed_blob *) sb_tmd, tmd_size,
146 (signed_blob *) sb_tik, tik_size, NULL);
148 gid = 0xffff;
149 if (IS_VALID_SIGNATURE ((signed_blob *) sb_tmd))
150 gid = ((tmd *)
151 SIGNATURE_PAYLOAD ((signed_blob *) sb_tmd))->group_id;
153 free (sb_certs);
154 free (sb_tmd);
155 free (sb_tik);
157 if (res) {
158 LOG_ERR ("ES_Identify failed: %d", res);
159 return RES_UNKNOWN;
162 res = ES_GetTitleID (&title_id);
163 if (res) {
164 LOG_ERR ("error getting the title id: %d", res);
165 return RES_UNKNOWN;
168 printf ("identified as: 0x%016llx, group id: 0x%04x\n", title_id, gid);
170 return RES_OK;
173 void server_run () {
174 struct client_request *request;
176 u8 authenticated = 0;
177 char *auth = WIIFUSE_AUTH_DATA;
179 u8 exit = 0;
180 u8 init = 0;
181 enum remote_result result;
182 u8 *data;
183 u16 data_size;
185 printf ("awaiting requests, fire up wiifuse on the other end\n");
186 while (1) {
187 request = read_request ();
189 if (!request) {
190 LOG_ERR ("received invalid packet");
191 return;
194 result = RES_UNKNOWN;
195 data = NULL;
196 data_size = 0;
198 switch (request->command) {
199 case CMD_AUTH:
200 if (request->data &&
201 request->data_size == strlen (auth) &&
202 !memcmp (request->data, auth, strlen (auth)))
203 result = RES_OK;
205 if (result == RES_OK)
206 printf ("granted access to client\n");
207 else
208 printf ("refused client access\n");
210 authenticated = result == RES_OK;
211 exit = result != RES_OK;
212 break;
214 case CMD_LOGLEVEL:
215 if (request->data && request->data_size == 1) {
216 verbose_level = request->data[0];
217 printf ("using verbose level %u\n",
218 verbose_level);
219 result = RES_OK;
221 break;
223 case CMD_UMOUNT:
224 printf ("\nreceived umount command, stopping server\n");
225 result = RES_OK;
226 exit = 1;
227 break;
229 case CMD_ES_IDENTIFY:
230 result = identify (request, &data, &data_size);
231 exit = result != RES_OK;
232 init = result == RES_OK;
233 break;
235 case CMD_FS_ACCESS:
236 result = wrapper_access (request);
237 break;
239 case CMD_FS_GETATTR:
240 result = wrapper_getattr (request, &data, &data_size);
241 break;
243 case CMD_FS_OPEN:
244 result = wrapper_open (request);
245 break;
247 case CMD_FS_READ:
248 result = wrapper_read (request, &data, &data_size);
249 break;
251 case CMD_FS_OPENDIR:
252 result = wrapper_opendir (request);
253 break;
255 case CMD_FS_READDIR:
256 result = wrapper_readdir (request, &data, &data_size);
257 break;
259 case CMD_FS_MKDIR:
260 result = wrapper_mkdir (request);
261 break;
263 case CMD_FS_RMDIR:
264 result = wrapper_rmdir (request);
265 break;
267 case CMD_FS_CREATE:
268 result = wrapper_create (request);
269 break;
271 case CMD_FS_WRITE:
272 result = wrapper_write (request, &data, &data_size);
273 break;
275 case CMD_FS_CHOWN:
276 result = wrapper_chown (request);
277 break;
279 case CMD_FS_CHMOD:
280 result = wrapper_chmod (request);
281 break;
283 case CMD_FS_RENAME:
284 result = wrapper_rename (request);
285 break;
287 case CMD_FS_UNLINK:
288 result = wrapper_unlink (request);
289 break;
291 case CMD_FS_STATFS:
292 result = wrapper_statfs (request, &data, &data_size);
293 break;
295 default:
296 LOG_ERR ("received an unknown command");
297 exit = 1;
298 break;
301 if (init) {
302 if (!wrapper_init (&data, &data_size)) {
303 printf ("wrapper_init failed\n");
304 exit = 1;
307 init = 0;
310 send_response (result, data, data_size);
312 if (data)
313 free (data);
315 if (exit)
316 break;
319 printf ("server was stopped\n");
321 if (!wrapper_deinit ())
322 printf ("wrapper_deinit failed\n");