PS2SDK
PS2 Homebrew Libraries
netcnf.c
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
11 #ifdef _IOP
12 #include "irx_imports.h"
13 #else
14 #include <ctype.h>
15 #include <fcntl.h>
16 #include <stdarg.h>
17 #include <stdint.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <sys/statvfs.h>
23 #include <unistd.h>
24 typedef int8_t s8;
25 typedef int16_t s16;
26 typedef int32_t s32;
27 typedef intptr_t siptr;
28 typedef uint8_t u8;
29 typedef uint16_t u16;
30 typedef uint32_t u32;
31 typedef uintptr_t uiptr;
32 #define iomanX_rename(old, new_) rename(old, new_)
33 #define iomanX_sync(...) 0
34 typedef struct
35 {
36  unsigned int mode;
37  unsigned int attr;
38  unsigned int size;
39  unsigned char ctime[8];
40  unsigned char atime[8];
41  unsigned char mtime[8];
42  unsigned int hisize;
43  unsigned int private_0;
44  unsigned int private_1;
45  unsigned int private_2;
46  unsigned int private_3;
47  unsigned int private_4;
48  unsigned int private_5;
49 } iox_stat_t;
50 typedef struct
51 {
52  iox_stat_t stat;
53  char name[256];
54  void *privdata;
55 } iox_dirent_t;
56 #endif
57 #include <errno.h>
58 #include <netcnf.h>
59 
60 #ifdef _IOP
61 IRX_ID("NET_configuration", 2, 30);
62 #endif
63 // Based on the module from SCE SDK 3.1.0.
64 
66 {
67  int m_fd;
68  char m_device[16];
69  char m_pathname[256];
70  void *m_buf;
71  int m_filesize;
72  int m_bufpos;
73  int m_allocstate;
74 };
75 
77 {
78  int m_type;
79  int m_offset;
80  const char *m_key;
81 };
82 
83 static void do_init_xor_magic(const char *in_id_buf);
84 static int magic_shift_write_netcnf_2(int inshft, int buflen);
85 static int magic_shift_read_netcnf_2(int inshft, int buflen);
86 static int magic_shift_write_netcnf_1(int inshft, int buflen);
87 static int magic_shift_read_netcnf_1(int inshft, int buflen);
88 static int do_check_capacity_inner(const char *fpath);
89 static int do_get_count_list_inner(const char *fname, int type, sceNetCnfList_t *p);
90 static int do_load_entry_inner(const char *fname, int type, const char *usr_name, sceNetCnfEnv_t *e);
91 static int do_add_entry_inner(
92  const char *fname,
93  int type,
94  const char *usr_name,
95  sceNetCnfEnv_t *e,
96  const char *icon_value,
97  const char *iconsys_value,
98  int no_check_capacity);
99 static int do_edit_entry_inner(
100  const char *fname,
101  int type,
102  const char *usr_name,
103  const char *new_usr_name,
104  sceNetCnfEnv_t *e,
105  const char *icon_value,
106  const char *iconsys_value,
107  int no_check_capacity);
108 static int do_delete_entry_inner(
109  const char *fname,
110  int type,
111  const char *usr_name,
112  const char *icon_value,
113  const char *iconsys_value,
114  int no_check_capacity);
115 static int do_set_latest_entry_inner(const char *fname, int type, const char *usr_name);
116 static int do_delete_all_inner(const char *dev);
117 static int do_check_special_provider_inner(const char *fname, int type, const char *usr_name, sceNetCnfEnv_t *e);
118 static char *do_alloc_mem_inner(sceNetCnfEnv_t *e, unsigned int size, int align);
119 static void do_init_ifc_inner(sceNetCnfInterface_t *ifc);
120 static int do_merge_conf_inner(sceNetCnfEnv_t *e);
121 static int do_load_conf_inner(sceNetCnfEnv_t *e);
122 static int do_load_dial_inner(sceNetCnfEnv_t *e, sceNetCnfPair_t *pair);
123 static int do_export_netcnf(sceNetCnfEnv_t *e);
124 static void do_address_to_string_inner(char *dst, unsigned int srcint);
125 static int do_name_2_address_inner(unsigned int *dst, const char *buf);
126 static int do_conv_a2s_inner(char *sp_, char *dp_, int len);
127 static int do_conv_s2a_inner(char *sp_, char *dp_, int len);
128 static int do_read_check_netcnf(const char *netcnf_path, int type, int no_check_magic, int no_decode);
129 static int do_check_provider_inner(const sceNetCnfEnv_t *e, int type);
130 static const char *do_handle_netcnf_dirname(const char *fpath, const char *entry_buffer, char *netcnf_file_path);
131 static int do_open_netcnf(const char *netcnf_path, int file_flags, int file_mode);
132 static int do_readfile_netcnf(int fd, void *ptr, int size);
133 static int do_write_netcnf_no_encode(int fd, void *ptr, int size);
134 static int do_dopen_wrap(const char *fn);
135 static int do_dread_wrap(int fn, iox_dirent_t *buf);
136 static int do_remove_wrap(const char *fn);
137 static void do_close_netcnf(int fd);
138 static void do_dclose_wrap(int fd);
139 static int do_filesize_netcnf(int fd);
140 static void do_getstat_wrap(const char *fn, iox_stat_t *stx);
141 static void do_chstat_mode_copyprotect_wrap(const char *fn);
142 static void do_set_callback_inner(sceNetCnfCallback_t *pcallback);
143 #ifdef _IOP
144 static int do_init_heap(void);
145 #endif
146 static void *do_alloc_heapmem(int nbytes);
147 static void do_free_heapmem(void *ptr);
148 #ifdef _IOP
149 static void do_delete_heap(void);
150 #endif
151 
152 #ifdef _IOP
153 extern struct irx_export_table _exp_netcnf;
154 #endif
155 // Unofficial: move to bss
156 static int g_no_check_capacity;
157 // Unofficial: move to bss
158 static int g_no_check_provider;
159 // Unofficial: move to bss
160 static u32 g_id_result;
161 // Unofficial: move to bss
162 static char *g_count_list_heapptr;
163 // Unofficial: move to bss
164 static char *g_load_entry_heapptr;
165 // Unofficial: move to bss
166 static char *g_add_entry_heapptr;
167 // Unofficial: move to bss
168 static char *g_edit_entry_heapptr;
169 // Unofficial: move to bss
170 static char *g_delete_entry_heapptr;
171 // Unofficial: move to bss
172 static char *g_set_latest_entry_heapptr;
173 // Unofficial: move to bss
174 static char *g_check_special_provider_heapptr;
175 static const struct netcnf_option g_options_net_cnf[] = {
176  {112, 12, "chat_additional"},
177  {52, 16, "redial_count"},
178  {52, 20, "redial_interval"},
179  {112, 24, "outside_number"},
180  {112, 28, "outside_delay"},
181  {68, 32, "dialing_type"},
182  {0, 0, NULL}};
183 static const struct netcnf_option g_options_attach_cnf[] = {
184  {84, 0, "type"},
185  {112, 4, "vendor"},
186  {112, 8, "product"},
187  {112, 12, "location"},
188  {98, 16, "dhcp"},
189  {112, 20, "dhcp_host_name"},
190  {98, 24, "dhcp_host_name_null_terminated"},
191  {98, 25, "dhcp_release_on_stop"},
192  {112, 28, "address"},
193  {112, 32, "netmask"},
194  {112, 36, "chat_additional"},
195  {52, 40, "redial_count"},
196  {52, 44, "redial_interval"},
197  {112, 48, "outside_number"},
198  {112, 52, "outside_delay"},
199  {98, 96, "answer_mode"},
200  {52, 100, "answer_timeout"},
201  {68, 104, "dialing_type"},
202  {112, 108, "chat_login"},
203  {112, 112, "auth_name"},
204  {112, 116, "auth_key"},
205  {112, 120, "peer_name"},
206  {112, 124, "peer_key"},
207  {52, 128, "lcp_timeout"},
208  {52, 132, "ipcp_timeout"},
209  {52, 136, "idle_timeout"},
210  {52, 140, "connect_timeout"},
211  {98, 144, "want.mru_nego"},
212  {98, 145, "want.accm_nego"},
213  {98, 146, "want.magic_nego"},
214  {98, 147, "want.prc_nego"},
215  {98, 148, "want.acc_nego"},
216  {98, 149, "want.address_nego"},
217  {98, 150, "want.vjcomp_nego"},
218  {98, 151, "want.dns1_nego"},
219  {98, 152, "want.dns2_nego"},
220  {77, 160, "want.mru"},
221  {67, 164, "want.accm"},
222  {65, 168, "want.auth"},
223  {112, 172, "want.ip_address"},
224  {112, 176, "want.ip_mask"},
225  {112, 180, "want.dns1"},
226  {112, 184, "want.dns2"},
227  {98, 220, "allow.mru_nego"},
228  {98, 221, "allow.accm_nego"},
229  {98, 222, "allow.magic_nego"},
230  {98, 223, "allow.prc_nego"},
231  {98, 224, "allow.acc_nego"},
232  {98, 225, "allow.address_nego"},
233  {98, 226, "allow.vjcomp_nego"},
234  {98, 227, "allow.dns1_nego"},
235  {98, 228, "allow.dns2_nego"},
236  {77, 236, "allow.mru"},
237  {67, 240, "allow.accm"},
238  {65, 244, "allow.auth"},
239  {112, 248, "allow.ip_address"},
240  {112, 252, "allow.ip_mask"},
241  {112, 256, "allow.dns1"},
242  {112, 260, "allow.dns2"},
243  {76, 296, "log_flags"},
244  {99, 300, "force_chap_type"},
245  {98, 301, "omit_empty_frame"},
246  {80, 332, "phy_config"},
247  {98, 302, "pppoe"},
248  {98, 303, "pppoe_host_uniq_auto"},
249  {112, 308, "pppoe_service_name"},
250  {112, 312, "pppoe_ac_name"},
251  {52, 316, "mtu"},
252  {49, 324, "auth_timeout"},
253  {49, 321, "lcp_max_terminate"},
254  {49, 323, "ipcp_max_terminate"},
255  {49, 320, "lcp_max_configure"},
256  {49, 322, "ipcp_max_configure"},
257  {49, 325, "auth_max_failure"},
258  {0, 0, NULL}};
259 static const struct netcnf_option g_options_dial_cnf[] = {
260  {112, 12, "chat_init"}, {112, 16, "chat_dial"}, {112, 20, "chat_answer"}, {112, 24, "redial_string"}, {0, 0, NULL}};
261 static int g_callbacks_set;
262 #ifdef _IOP
263 // Unofficial: move to bss
264 static void *g_netcnf_heap;
265 static int g_semid;
266 #endif
267 static char g_icon_value[0x100];
268 static char g_iconsys_value[0x100];
269 static char g_id_xorbuf[24];
270 static char g_id_buffer[8];
271 static char g_ifc_buffer[0x3e8];
272 static char g_arg_fname[0x400];
273 static char g_entry_buffer[0x400];
274 static char g_netcnf_file_path[0x100];
275 static char g_dir_name[0x100];
276 static char g_combination_buf1[0x100];
277 static char g_combination_buf2[0x100];
278 static char *g_read_check_netcnf_heapptr;
279 static sceNetCnfCallback_t g_callbacks;
280 static struct netcnf_callback_handle_info g_callback_handle_infos[4];
281 static int g_open_callback_handle_count;
282 
283 static int get_check_provider_eq_zero(void)
284 {
285  return !g_no_check_provider;
286 }
287 
288 #ifdef _IOP
289 static void do_print_usage(void)
290 {
291  printf("Usage: netcnf [<option>] icon=<icon-path> iconsys=<iconsys-path>\n");
292  printf(" <option>:\n");
293  printf(" -no_check_capacity do not check capacity\n");
294  printf(" -no_check_provider do not check special provider\n");
295 }
296 
297 static int do_module_load(int ac, char *av[], void *startaddr, ModuleInfo_t *mi)
298 {
299  int semid;
300  int i;
301  iop_sema_t semaparam;
302  int err;
303 
304  (void)startaddr;
305  if ( ac < 3 )
306  {
307  do_print_usage();
308  return MODULE_NO_RESIDENT_END;
309  }
310  err = 0;
311  semaparam.attr = SA_THPRI;
312  semaparam.initial = 1;
313  semaparam.max = 1;
314  semaparam.option = 0;
315  semid = CreateSema(&semaparam);
316  g_semid = semid;
317  if ( semid <= 0 )
318  {
319  printf("netcnf: CreateSema (%d)\n", semid);
320  return MODULE_NO_RESIDENT_END;
321  }
322  g_icon_value[0] = 0;
323  g_iconsys_value[0] = 0;
324  for ( i = 1; i < ac; i += 1 )
325  {
326  if ( !strncmp("icon=", av[i], 5) )
327  {
328  strcpy(g_icon_value, av[i] + 5);
329  }
330  else if ( !strncmp("iconsys=", av[i], 8) )
331  {
332  strcpy(g_iconsys_value, av[i] + 8);
333  }
334  else if ( !strcmp("-no_check_capacity", av[i]) )
335  {
336  g_no_check_capacity = 1;
337  }
338  else if ( !strcmp("-no_check_provider", av[i]) )
339  {
340  g_no_check_provider = 1;
341  }
342  else
343  {
344  err = 1;
345  break;
346  }
347  }
348  if ( !g_icon_value[0] || !g_iconsys_value[0] )
349  {
350  err = 1;
351  }
352  if ( !err )
353  {
354  int heap_inited;
355 
356  heap_inited = do_init_heap();
357  if ( heap_inited < 0 )
358  {
359  printf("netcnf: init_heap(%d)\n", heap_inited);
360  }
361  else
362  {
363  int regres;
364 
365  regres = RegisterLibraryEntries(&_exp_netcnf);
366  if ( !regres )
367  {
368 #if 0
369  return MODULE_REMOVABLE_END;
370 #else
371  if ( mi && ((mi->newflags & 2) != 0) )
372  mi->newflags |= 0x10;
373  return MODULE_RESIDENT_END;
374 #endif
375  }
376  printf("netcnf: RegisterLibraryEntries(%d)\n", regres);
377  do_delete_heap();
378  }
379  }
380  if ( err == 1 )
381  {
382  do_print_usage();
383  }
384  DeleteSema(g_semid);
385  return MODULE_NO_RESIDENT_END;
386 }
387 
388 static int do_module_unload(void)
389 {
390  int relres;
391  int errstate;
392 
393  errstate = 0;
394  relres = ReleaseLibraryEntries(&_exp_netcnf);
395  if ( relres )
396  {
397  printf("netcnf: ReleaseLibraryEntries (%d)\n", relres);
398  }
399  else
400  {
401  errstate = 1;
402  relres = DeleteSema(g_semid);
403  if ( relres )
404  {
405  printf("netcnf: DeleteSema (%d)\n", relres);
406  }
407  else
408  {
409  errstate = 2;
410  }
411  }
412  if ( errstate == 2 )
413  {
414  do_delete_heap();
415  return MODULE_NO_RESIDENT_END;
416  }
417  if ( errstate == 1 )
418  {
419  RegisterLibraryEntries(&_exp_netcnf);
420  }
421  return MODULE_REMOVABLE_END;
422 }
423 
424 int _start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi)
425 {
426  return (ac >= 0) ? do_module_load(ac, av, startaddr, mi) : do_module_unload();
427 }
428 #endif
429 
430 int sceNetCnfGetCount(const char *fname, int type)
431 {
432  int retres;
433 
434 #ifdef _IOP
435  WaitSema(g_semid);
436 #endif
437  retres = do_get_count_list_inner(fname, type, 0);
438 #ifdef _IOP
439  SignalSema(g_semid);
440 #endif
441  return retres;
442 }
443 
444 int sceNetCnfGetList(const char *fname, int type, sceNetCnfList_t *p)
445 {
446  int retres;
447 
448 #ifdef _IOP
449  WaitSema(g_semid);
450 #endif
451  retres = do_get_count_list_inner(fname, type, p);
452 #ifdef _IOP
453  SignalSema(g_semid);
454 #endif
455  return retres;
456 }
457 
458 int sceNetCnfLoadEntry(const char *fname, int type, const char *usr_name, sceNetCnfEnv_t *e)
459 {
460  int retres;
461 
462 #ifdef _IOP
463  WaitSema(g_semid);
464 #endif
465  retres = do_load_entry_inner(fname, type, usr_name, e);
466 #ifdef _IOP
467  SignalSema(g_semid);
468 #endif
469  return retres;
470 }
471 
472 int sceNetCnfAddEntry(const char *fname, int type, const char *usr_name, sceNetCnfEnv_t *e)
473 {
474  int retres;
475 
476 #ifdef _IOP
477  WaitSema(g_semid);
478 #endif
479  retres = do_add_entry_inner(fname, type, usr_name, e, g_icon_value, g_iconsys_value, g_no_check_capacity);
480 #ifdef _IOP
481  SignalSema(g_semid);
482 #endif
483  return retres;
484 }
485 
486 int sceNetCnfEditEntry(const char *fname, int type, const char *usr_name, const char *new_usr_name, sceNetCnfEnv_t *e)
487 {
488  int retres;
489 
490 #ifdef _IOP
491  WaitSema(g_semid);
492 #endif
493  retres =
494  do_edit_entry_inner(fname, type, usr_name, new_usr_name, e, g_icon_value, g_iconsys_value, g_no_check_capacity);
495 #ifdef _IOP
496  SignalSema(g_semid);
497 #endif
498  return retres;
499 }
500 
501 int sceNetCnfDeleteEntry(const char *fname, int type, const char *usr_name)
502 {
503  int retres;
504 
505 #ifdef _IOP
506  WaitSema(g_semid);
507 #endif
508  retres = do_delete_entry_inner(fname, type, usr_name, g_icon_value, g_iconsys_value, g_no_check_capacity);
509 #ifdef _IOP
510  SignalSema(g_semid);
511 #endif
512  return retres;
513 }
514 
515 int sceNetCnfSetLatestEntry(const char *fname, int type, const char *usr_name)
516 {
517  int retres;
518 
519 #ifdef _IOP
520  WaitSema(g_semid);
521 #endif
522  retres = do_set_latest_entry_inner(fname, type, usr_name);
523 #ifdef _IOP
524  SignalSema(g_semid);
525 #endif
526  return retres;
527 }
528 
529 void *sceNetCnfAllocMem(sceNetCnfEnv_t *e, int size, int align)
530 {
531  return do_alloc_mem_inner(e, (unsigned int)size, align);
532 }
533 
534 int sceNetCnfInitIFC(sceNetCnfInterface_t *ifc)
535 {
536  if ( ifc )
537  {
538  memset(ifc, 0, sizeof(sceNetCnfInterface_t));
539  do_init_ifc_inner(ifc);
540  }
541  return 0;
542 }
543 
544 int sceNetCnfLoadConf(sceNetCnfEnv_t *e)
545 {
546  return do_load_conf_inner(e);
547 }
548 
549 int sceNetCnfLoadDial(sceNetCnfEnv_t *e, sceNetCnfPair_t *pair)
550 {
551  return do_load_dial_inner(e, pair);
552 }
553 
554 int sceNetCnfMergeConf(sceNetCnfEnv_t *e)
555 {
556  return do_merge_conf_inner(e);
557 }
558 
559 int sceNetCnfName2Address(sceNetCnfAddress_t *paddr, const char *buf)
560 {
561  unsigned int paddr_tmp;
562 
563  paddr_tmp = 0;
564  if ( buf && !do_name_2_address_inner(&paddr_tmp, buf) )
565  {
566  return -1;
567  }
568  memset(paddr, 0, sizeof(sceNetCnfAddress_t));
569  memcpy(paddr->data, &paddr_tmp, sizeof(paddr_tmp));
570  return 0;
571 }
572 
573 int sceNetCnfAddress2String(char *buf, int len, const sceNetCnfAddress_t *paddr)
574 {
575  unsigned int buflen;
576  char buf_tmp[24];
577  unsigned int srcintx;
578 
579  if ( paddr->reserved )
580  {
581  return -1;
582  }
583  memcpy(&srcintx, paddr->data, sizeof(srcintx));
584  do_address_to_string_inner(buf_tmp, srcintx);
585  buflen = (u32)strlen(buf_tmp) + 1;
586  if ( (unsigned int)len < buflen )
587  {
588  return -1;
589  }
590  memcpy(buf, buf_tmp, buflen);
591  return 0;
592 }
593 
594 int sceNetCnfDeleteAll(const char *dev)
595 {
596  int retres;
597 
598 #ifdef _IOP
599  WaitSema(g_semid);
600 #endif
601  retres = do_delete_all_inner(dev);
602 #ifdef _IOP
603  SignalSema(g_semid);
604 #endif
605  return retres;
606 }
607 
608 int sceNetCnfCheckCapacity(const char *fname)
609 {
610  int retres;
611 
612 #ifdef _IOP
613  WaitSema(g_semid);
614 #endif
615  retres = do_check_capacity_inner(fname);
616 #ifdef _IOP
617  SignalSema(g_semid);
618 #endif
619  return retres;
620 }
621 
622 int sceNetCnfConvA2S(char *sp_, char *dp_, int len)
623 {
624  int retres;
625 
626  retres = do_conv_a2s_inner(sp_, dp_, len);
627  if ( retres )
628  {
629  return retres;
630  }
631  if ( len < (int)(strlen(sp_) + 1) )
632  {
633  return -19;
634  }
635  strcpy(dp_, sp_);
636  return 0;
637 }
638 
639 int sceNetCnfConvS2A(char *sp_, char *dp_, int len)
640 {
641  int retres;
642 
643  retres = do_conv_s2a_inner(sp_, dp_, len);
644  if ( retres )
645  {
646  return retres;
647  }
648  if ( len < (int)(strlen(sp_) + 1) )
649  {
650  return -19;
651  }
652  strcpy(dp_, sp_);
653  return 0;
654 }
655 
656 int sceNetCnfCheckSpecialProvider(const char *fname, int type, const char *usr_name, sceNetCnfEnv_t *e)
657 {
658  int retres;
659 
660 #ifdef _IOP
661  WaitSema(g_semid);
662 #endif
663  retres = do_check_special_provider_inner(fname, type, usr_name, e);
664 #ifdef _IOP
665  SignalSema(g_semid);
666 #endif
667  return retres;
668 }
669 
670 void sceNetCnfSetCallback(sceNetCnfCallback_t *pcallback)
671 {
672 #ifdef _IOP
673  WaitSema(g_semid);
674 #endif
675  do_set_callback_inner(pcallback);
676 #ifdef _IOP
677  SignalSema(g_semid);
678 #endif
679 }
680 
681 static int do_read_ilink_id(void)
682 {
683 #ifdef _IOP
684  int i;
685 
686  for ( i = 0; i < 20; i += 1 )
687  {
688  g_id_result = 0;
689  if ( sceCdRI((u8 *)g_id_buffer, &g_id_result) == 1 )
690  {
691  if ( !g_id_result )
692  return 0;
693  }
694  DelayThread(100000);
695  }
696  return -13;
697 #else
698  memset(&g_id_buffer, 0, sizeof(g_id_buffer));
699  g_id_result = 0;
700  return 0;
701 #endif
702 }
703 
704 static int do_read_netcnf_decode(const char *netcnf_path, char **netcnf_heap_ptr)
705 {
706  int result;
707  int fd;
708  int netcnf_size;
709  char *heapmem;
710  int xorind1;
711  int readres;
712  int i;
713 
714  *netcnf_heap_ptr = 0;
715  result = do_read_ilink_id();
716  // cppcheck-suppress knownConditionTrueFalse
717  if ( result < 0 )
718  return result;
719  do_init_xor_magic(g_id_buffer);
720  fd = do_open_netcnf(netcnf_path, 1, 0);
721  if ( fd < 0 )
722  {
723  return (fd == -EIO) ? -18 : -3;
724  }
725  netcnf_size = do_filesize_netcnf(fd);
726  if ( netcnf_size < 0 )
727  {
728  do_close_netcnf(fd);
729  return netcnf_size;
730  }
731  heapmem = (char *)do_alloc_heapmem(netcnf_size + 1);
732  *netcnf_heap_ptr = heapmem;
733  if ( !heapmem )
734  {
735  do_close_netcnf(fd);
736  return -2;
737  }
738  xorind1 = 0;
739  readres = 0;
740  for ( i = 0; i < netcnf_size; i += 2 )
741  {
742  readres = do_readfile_netcnf(fd, &heapmem[i], 2);
743  if ( readres < 0 )
744  break;
745  *((u16 *)&heapmem[i]) ^= 0xFFFF;
746  *((u16 *)&heapmem[i]) = (u16)magic_shift_read_netcnf_1(*((u16 *)&heapmem[i]), (u8)g_id_xorbuf[xorind1 + 2]);
747  xorind1 += 1;
748  xorind1 = (xorind1 != sizeof(g_id_xorbuf)) ? xorind1 : 0;
749  }
750  if ( readres >= 0 )
751  {
752  if ( (netcnf_size & 1) != 0 )
753  {
754  readres = do_readfile_netcnf(fd, &heapmem[netcnf_size - 1], 1);
755  if ( readres >= 0 )
756  {
757  heapmem[netcnf_size - 1] ^= 0xFF;
758  heapmem[netcnf_size - 1] =
759  (char)magic_shift_read_netcnf_2(heapmem[netcnf_size - 1], (u8)g_id_xorbuf[xorind1 + 2]);
760  }
761  }
762  if ( readres >= 0 )
763  {
764  heapmem[netcnf_size] = 0;
765  do_close_netcnf(fd);
766  return netcnf_size;
767  }
768  }
769  do_free_heapmem(heapmem);
770  *netcnf_heap_ptr = 0;
771  do_close_netcnf(fd);
772  return (readres != -EIO) ? -4 : -18;
773 }
774 
775 static int do_write_netcnf_encode(const char *netcnf_path, void *buf, int netcnf_len)
776 {
777  int result;
778  int fd;
779  u16 *buf_1;
780  int netcnf_len_1;
781  int xorind1;
782  int xoroffs;
783  int writeres;
784  u16 bufflipx1;
785  char bufflipx2;
786 
787  result = do_read_ilink_id();
788  // cppcheck-suppress knownConditionTrueFalse
789  if ( result < 0 )
790  return result;
791  do_init_xor_magic(g_id_buffer);
792  fd = do_open_netcnf(netcnf_path, 1538, 511);
793  buf_1 = (u16 *)buf;
794  if ( fd < 0 )
795  {
796  return (fd == -EIO) ? -18 : -3;
797  }
798  netcnf_len_1 = netcnf_len;
799  xorind1 = 0;
800  xoroffs = 0;
801  writeres = 0;
802  while ( writeres >= 0 )
803  {
804  while ( netcnf_len_1 >= 2 )
805  {
806  bufflipx1 = (u16)magic_shift_write_netcnf_1(*buf_1, (u8)g_id_xorbuf[xorind1 + 2]);
807  xorind1 += 1;
808  xorind1 = (xorind1 != sizeof(g_id_xorbuf)) ? xorind1 : 0;
809  bufflipx1 ^= 0xFFFF;
810  writeres = do_write_netcnf_no_encode(fd, &bufflipx1, sizeof(bufflipx1));
811  buf_1 += 1;
812  if ( writeres < 0 )
813  break;
814  netcnf_len_1 -= 2;
815  xoroffs += 2;
816  }
817  if ( writeres >= 0 && !netcnf_len_1 )
818  {
819  do_close_netcnf(fd);
820  return xoroffs;
821  }
822  if ( writeres >= 0 )
823  {
824  bufflipx2 = (char)magic_shift_write_netcnf_2(*(u8 *)buf_1, (u8)g_id_xorbuf[xorind1 + 2]);
825  xorind1 += 1;
826  xorind1 = (xorind1 != sizeof(g_id_xorbuf)) ? xorind1 : 0;
827  bufflipx2 ^= 0xFF;
828  writeres = do_write_netcnf_no_encode(fd, &bufflipx2, sizeof(bufflipx2));
829  netcnf_len_1 -= 1;
830  xoroffs += 1;
831  }
832  }
833  do_close_netcnf(fd);
834  return (writeres != -EIO) ? -5 : -18;
835 }
836 
837 static int do_read_netcnf_no_decode(const char *netcnf_path, char **netcnf_heap_ptr)
838 {
839  int fd;
840  int netcnf_size;
841  char *netcnf_data;
842 
843  *netcnf_heap_ptr = 0;
844  fd = do_open_netcnf(netcnf_path, 1, 0);
845  if ( fd < 0 )
846  {
847  return (fd != -EIO) ? -3 : -18;
848  }
849  netcnf_size = do_filesize_netcnf(fd);
850  if ( netcnf_size < 0 )
851  {
852  do_close_netcnf(fd);
853  return netcnf_size;
854  }
855  netcnf_data = (char *)do_alloc_heapmem(netcnf_size + 1);
856  *netcnf_heap_ptr = netcnf_data;
857  if ( !netcnf_data )
858  {
859  do_close_netcnf(fd);
860  return -2;
861  }
862  netcnf_size = do_readfile_netcnf(fd, netcnf_data, netcnf_size);
863  if ( netcnf_size < 0 )
864  {
865  do_free_heapmem(*netcnf_heap_ptr);
866  *netcnf_heap_ptr = 0;
867  do_close_netcnf(fd);
868  return (netcnf_size != -EIO) ? -4 : -18;
869  }
870  netcnf_data[netcnf_size] = 0;
871  do_close_netcnf(fd);
872  return netcnf_size;
873 }
874 
875 static void do_init_xor_magic(const char *in_id_buf)
876 {
877  int i;
878 
879  for ( i = 0; (i + 1) < 8; i += 1 )
880  {
881  g_id_xorbuf[(i * 3) + 2] = ((u8)in_id_buf[i] >> 5) + 1;
882  g_id_xorbuf[(i * 3) + 3] = (((u8)in_id_buf[i] >> 2) & 7) + 1;
883  g_id_xorbuf[(i * 3) + 4] = (in_id_buf[i] & 3) + 1;
884  }
885 }
886 
887 static int magic_shift_write_netcnf_2(int inshft, int buflen)
888 {
889  for ( ; buflen; buflen -= 1 )
890  inshft = ((u8)inshft >> 7) | (inshft << 1);
891  return (u8)inshft;
892 }
893 
894 static int magic_shift_read_netcnf_2(int inshft, int buflen)
895 {
896  for ( ; buflen; buflen -= 1 )
897  inshft = ((u8)inshft >> 1) | (inshft << 7);
898  return (u8)inshft;
899 }
900 
901 static int magic_shift_write_netcnf_1(int inshft, int buflen)
902 {
903  for ( ; buflen; buflen -= 1 )
904  inshft = ((u16)inshft >> 15) | (inshft << 1);
905  return (u16)inshft;
906 }
907 
908 static int magic_shift_read_netcnf_1(int inshft, int buflen)
909 {
910  for ( ; buflen; buflen -= 1 )
911  inshft = ((u16)inshft >> 1) | (inshft << 15);
912  return (u16)inshft;
913 }
914 
915 static void do_safe_strcpy(char *dst, size_t maxlen, const char *src, int linenum)
916 {
917  if ( strlen(src) >= maxlen )
918  {
919  printf("[netcnf] strcpy failed(%d)\n", linenum);
920  return;
921  }
922  strcpy(dst, src);
923 }
924 
925 static void do_safe_strcat(char *dst, size_t maxlen, const char *src, int linenum)
926 {
927  if ( strlen(dst) + strlen(src) >= maxlen )
928  {
929  printf("[netcnf] strcat failed(%d)\n", linenum);
930  return;
931  }
932  strcat(dst, src);
933 }
934 
935 static void do_safe_make_pathname(char *dst, size_t maxlen, const char *srcdir, const char *srcbase)
936 {
937  if ( strlen(srcdir) + strlen(srcbase) + 1 >= maxlen )
938  {
939  printf("[netcnf] make_pathname failed\n");
940  return;
941  }
942  strcpy(dst, srcdir);
943  strcat(dst, "/");
944  strcat(dst, srcbase);
945 }
946 
947 static void do_safe_make_name(char *dst, size_t maxlen, const char *src1, const char *src2)
948 {
949  if ( strlen(src1) + strlen(src2) >= maxlen )
950  {
951  printf("[netcnf] make_name failed\n");
952  return;
953  }
954  strcpy(dst, src1);
955  strcat(dst, src2);
956 }
957 
958 static int do_check_capacity_inner2(const char *fpath, int minsize)
959 {
960  int i;
961  int zonefree;
962  char devname[8];
963 
964  for ( i = 0; i < 5; i += 1 )
965  {
966  devname[i] = fpath[i];
967  if ( fpath[i] == ':' )
968  {
969  devname[i + 1] = 0;
970 #ifdef _IOP
971  zonefree = iomanX_devctl(devname, 0x5002, 0, 0, 0, 0) * ((int)iomanX_devctl(devname, 0x5001, 0, 0, 0, 0) / 1024);
972 #else
973  {
974  struct statvfs st;
975 
976  statvfs(devname, &st);
977  zonefree = (int)(u32)(st.f_bfree * st.f_frsize);
978  }
979 #endif
980  return (zonefree < minsize) ? -16 : 0;
981  }
982  }
983  return -9;
984 }
985 
986 static int do_check_capacity_inner(const char *fpath)
987 {
988  int minsize;
989 
990  if ( !strncmp(fpath, "mc", 2) )
991  minsize = 0x5E;
992  else if ( !strncmp(fpath, "pfs", 3) )
993  minsize = 0xF4;
994  else
995  return -9;
996  return do_check_capacity_inner2(fpath, minsize);
997 }
998 
999 static int do_handle_combination_path(int type, const char *fpath, char *dst, size_t maxlen, const char *usr_name)
1000 {
1001  char *i;
1002  int j;
1003  int devnr;
1004  char devnum[8];
1005 
1006  if ( !usr_name )
1007  return -11;
1008  do_safe_strcpy(dst, maxlen, usr_name, 139);
1009  if ( type )
1010  return 0;
1011  for ( i = dst; !isdigit(*i); i += 1 )
1012  ;
1013  for ( j = 0; j < 4 && isdigit(i[j]); j += 1 )
1014  {
1015  devnum[j] = i[j];
1016  }
1017  if ( j >= 4 )
1018  return -11;
1019  devnum[j] = 0;
1020  devnr = (int)strtol(devnum, 0, 10);
1021  if (
1022  !strncmp(fpath, "mc", 2) ? ((unsigned int)(devnr - 1) >= 6) :
1023  (!strncmp(fpath, "pfs", 3) ? (unsigned int)(devnr - 1) >= 0xA :
1024  (unsigned int)(devnr - 1) >= sizeof(g_ifc_buffer)) )
1025  return -11;
1026  do_safe_make_name(dst, maxlen, "Combination", devnum);
1027  return 0;
1028 }
1029 
1030 static int do_copy_netcnf_path(const char *netcnf_path_1, const char *netcnf_path_2)
1031 {
1032  int fd2;
1033  int fd1;
1034  int readres;
1035  char tmpbuf[512];
1036 
1037  fd2 = do_open_netcnf(netcnf_path_2, 1538, 511);
1038  if ( fd2 < 0 )
1039  return -3;
1040  fd1 = do_open_netcnf(netcnf_path_1, 1, 0);
1041  if ( fd1 < 0 )
1042  {
1043  do_close_netcnf(fd2);
1044  return -3;
1045  }
1046  while ( 1 )
1047  {
1048  int writeres;
1049 
1050  readres = do_readfile_netcnf(fd1, tmpbuf, sizeof(tmpbuf));
1051  if ( readres <= 0 )
1052  break;
1053  writeres = do_write_netcnf_no_encode(fd2, tmpbuf, readres);
1054  if ( readres != writeres )
1055  {
1056  do_close_netcnf(fd2);
1057  do_close_netcnf(fd1);
1058  return -5;
1059  }
1060  }
1061  do_close_netcnf(fd2);
1062  do_close_netcnf(fd1);
1063  return (readres < 0) ? -4 : 0;
1064 }
1065 
1066 static char *do_write_memcard_pathcopy(char *dst, size_t maxlen, const char *src)
1067 {
1068  char *dst_end_slash;
1069 
1070  do_safe_strcpy(dst, maxlen, src, 218);
1071  for ( dst_end_slash = &dst[strlen(dst)]; *dst_end_slash != '/'; dst_end_slash -= 1 )
1072  ;
1073  for ( ; *dst_end_slash == '/'; dst_end_slash -= 1 )
1074  ;
1075  if ( *dst_end_slash == ':' )
1076  return 0;
1077  dst_end_slash[1] = 0;
1078  return dst;
1079 }
1080 
1081 static int do_write_memcard_files(const char *fpath, const char *icon_value, const char *iconsys_value)
1082 {
1083  int result;
1084  char cur_basepath[256];
1085  char cur_combpath[256];
1086 
1087  if ( !do_write_memcard_pathcopy(cur_basepath, sizeof(cur_basepath), fpath) )
1088  return 0;
1089  do_safe_make_pathname(cur_combpath, sizeof(cur_combpath), cur_basepath, "SYS_NET.ICO");
1090  result = do_copy_netcnf_path(icon_value, cur_combpath);
1091  if ( result < 0 )
1092  return result;
1093  do_safe_make_pathname(cur_combpath, sizeof(cur_combpath), cur_basepath, "icon.sys");
1094  result = do_copy_netcnf_path(iconsys_value, cur_combpath);
1095  if ( result < 0 )
1096  return result;
1097  return 0;
1098 }
1099 
1100 static int do_handle_fname(char *fpath, size_t maxlen, const char *fname)
1101 {
1102  char *index_res;
1103  const char *pathname;
1104  int maxbuf;
1105 
1106  do_safe_strcpy(fpath, maxlen, fname, 266);
1107  index_res = index(fpath, ':');
1108  if ( !index_res )
1109  return -9;
1110  if ( !strncmp(fpath, "mc", 2) )
1111  {
1112  index_res[1] = 0;
1113  pathname = "/BWNETCNF/BWNETCNF";
1114  maxbuf = 275;
1115  }
1116  else if ( !strncmp(fpath, "pfs", 3) )
1117  {
1118  index_res[1] = 0;
1119  pathname = "/etc/network/net.db";
1120  maxbuf = 279;
1121  }
1122  else
1123  return 0;
1124  do_safe_strcat(fpath, maxlen, pathname, maxbuf);
1125  return 0;
1126 }
1127 
1128 static const char *do_get_str_line(const char *buf)
1129 {
1130  for ( ; *buf && *buf != '\n'; buf += 1 )
1131  ;
1132  return &buf[*buf == '\n'];
1133 }
1134 
1135 static int do_split_str_comma_index(char *dst, const char *src, int commaind)
1136 {
1137  int i;
1138 
1139  for ( i = 0; i < commaind; i += 1 )
1140  {
1141  for ( ; *src && *src != '\n' && *src != ','; src += 1 )
1142  ;
1143  if ( *src != ',' )
1144  return -1;
1145  src += 1;
1146  }
1147  for ( ; *src && *src != ',' && *src != '\n' && *src != '\r'; src += 1 )
1148  {
1149  *dst = *src;
1150  dst += 1;
1151  }
1152  *dst = 0;
1153  return 0;
1154 }
1155 
1156 static int
1157 do_remove_old_config(const char *fpath, const char *netcnf_heap_buf, const char *icon_value, const char *iconsys_value)
1158 {
1159  int sysneticoflag;
1160  int dfd;
1161  int fileop_res;
1162  const char *curheapbuf1;
1163  char cur_basepath[256];
1164  char cur_combpath[256];
1165  iox_dirent_t statname;
1166  iox_stat_t statsize;
1167  int iconsysflag;
1168 
1169  sysneticoflag = 1;
1170  iconsysflag = 1;
1171  if ( !do_write_memcard_pathcopy(cur_basepath, sizeof(cur_basepath), fpath) )
1172  return 0;
1173  dfd = do_dopen_wrap(cur_basepath);
1174  // cppcheck-suppress knownConditionTrueFalse
1175  if ( dfd < 0 )
1176  {
1177  return (dfd == -EIO) ? -18 : 0;
1178  }
1179  while ( 1 )
1180  {
1181  int sizeflag;
1182 
1183  fileop_res = do_dread_wrap(dfd, &statname);
1184  // cppcheck-suppress knownConditionTrueFalse
1185  if ( fileop_res <= 0 )
1186  break;
1187  sizeflag = 1;
1188  if ( strlen(statname.name) == 10 )
1189  {
1190  if ( !strncmp(&statname.name[6], ".cnf", 4) || !strncmp(&statname.name[6], ".dat", 4) )
1191  {
1192  for ( curheapbuf1 = netcnf_heap_buf; curheapbuf1 && *curheapbuf1; curheapbuf1 = do_get_str_line(curheapbuf1) )
1193  {
1194  do_split_str_comma_index(cur_combpath, curheapbuf1, 2);
1195  if ( !strcmp(statname.name, cur_combpath) )
1196  {
1197  do_safe_make_pathname(cur_combpath, sizeof(cur_combpath), cur_basepath, statname.name);
1198  sizeflag = 0;
1199  break;
1200  }
1201  }
1202  }
1203  }
1204  else if ( !strncmp(fpath, "mc", 2) )
1205  {
1206  if ( !strcmp(statname.name, "SYS_NET.ICO") )
1207  {
1208  do_safe_make_pathname(cur_combpath, sizeof(cur_combpath), cur_basepath, statname.name);
1209  do_getstat_wrap(cur_combpath, &statsize);
1210  if ( statsize.size != 0x8398 )
1211  {
1212  sizeflag = 0;
1213  }
1214  else
1215  {
1216  sysneticoflag = 0;
1217  }
1218  }
1219  else if ( !strcmp(statname.name, "icon.sys") )
1220  {
1221  do_safe_make_pathname(cur_combpath, sizeof(cur_combpath), cur_basepath, statname.name);
1222  do_getstat_wrap(cur_combpath, &statsize);
1223  if ( statsize.size != 0x3C4 )
1224  {
1225  sizeflag = 0;
1226  }
1227  else
1228  {
1229  iconsysflag = 0;
1230  }
1231  }
1232  else if ( strcmp(statname.name, "BWNETCNF") )
1233  {
1234  do_safe_make_pathname(cur_combpath, sizeof(cur_combpath), cur_basepath, statname.name);
1235  sizeflag = 0;
1236  }
1237  }
1238  else if ( !strncmp(fpath, "pfs", 3) && strcmp(statname.name, "net.db") )
1239  {
1240  do_safe_make_pathname(cur_combpath, sizeof(cur_combpath), cur_basepath, statname.name);
1241  sizeflag = 0;
1242  }
1243  if ( !sizeflag )
1244  {
1245  fileop_res = do_remove_wrap(cur_combpath);
1246  if ( fileop_res == -EIO )
1247  break;
1248  }
1249  }
1250  if ( fileop_res == -EIO )
1251  {
1252  do_dclose_wrap(dfd);
1253  return -18;
1254  }
1255  do_dclose_wrap(dfd);
1256  if ( !strncmp(fpath, "mc", 2) )
1257  {
1258  if ( sysneticoflag || iconsysflag )
1259  fileop_res = do_write_memcard_files(fpath, icon_value, iconsys_value);
1260  do_chstat_mode_copyprotect_wrap(cur_basepath);
1261  }
1262  return fileop_res;
1263 }
1264 
1265 static int do_type_check(int type, const char *buf)
1266 {
1267  return (do_split_str_comma_index(g_arg_fname, buf, 0)) ? -1 : (strtol(g_arg_fname, 0, 10) == type);
1268 }
1269 
1270 static int do_read_current_netcnf_nodecode(const char *fpath, char **netcnf_heap_ptr)
1271 {
1272  int retres;
1273 
1274  if ( !fpath )
1275  return -9;
1276  retres = do_read_netcnf_no_decode(fpath, netcnf_heap_ptr);
1277  return (retres < 0) ? ((retres != -3) ? retres : 0) : retres;
1278 }
1279 
1280 static int do_write_noencode_netcnf_atomic(const char *fpath, void *ptr, int size)
1281 {
1282  int fd;
1283  int writeres;
1284  char fpath_comb[256];
1285 
1286  if ( !fpath )
1287  return -9;
1288  do_safe_make_name(fpath_comb, sizeof(fpath_comb), fpath, ".tmp");
1289  fd = do_open_netcnf(fpath_comb, 1538, 511);
1290  if ( fd < 0 )
1291  {
1292  return (fd == -EIO) ? -18 : -3;
1293  }
1294  writeres = do_write_netcnf_no_encode(fd, ptr, size);
1295  do_close_netcnf(fd);
1296  // Unofficial: dead code removed
1297  return (size != writeres) ? ((writeres != -EIO) ? -5 : -18) : ((iomanX_rename(fpath_comb, fpath) == -EIO) ? -18 : 0);
1298 }
1299 
1300 static int do_remove_netcnf_dirname(const char *dirpath, const char *entry_buffer)
1301 {
1302  const char *p_dirname;
1303  int remove_res_1;
1304 
1305  p_dirname = do_handle_netcnf_dirname(dirpath, entry_buffer, g_netcnf_file_path);
1306  if ( !p_dirname )
1307  return -7;
1308  remove_res_1 = do_remove_wrap(p_dirname);
1309  return (remove_res_1 < 0) ? ((remove_res_1 == -EIO) ? -18 : -7) : 0;
1310 }
1311 
1312 static int do_get_count_list_inner(const char *fname, int type, sceNetCnfList_t *p)
1313 {
1314  int result;
1315  const char *curheapbuf1;
1316  int curind1;
1317 
1318  result = do_handle_fname(g_dir_name, sizeof(g_dir_name), fname);
1319  if ( result < 0 )
1320  return result;
1321  result = do_read_current_netcnf_nodecode(g_dir_name, &g_count_list_heapptr);
1322  if ( result <= 0 )
1323  return result;
1324  curind1 = 0;
1325  for ( curheapbuf1 = g_count_list_heapptr; *curheapbuf1; curheapbuf1 = do_get_str_line(curheapbuf1) )
1326  {
1327  if ( do_type_check(type, curheapbuf1) <= 0 )
1328  continue;
1329  curind1 += 1;
1330  if ( !p )
1331  continue;
1332  p->type = type;
1333  if ( do_split_str_comma_index(g_arg_fname, curheapbuf1, 1) )
1334  continue;
1335  p->stat = (int)strtol(g_arg_fname, 0, 10);
1336  if (
1337  do_split_str_comma_index(p->sys_name, curheapbuf1, 2) || do_split_str_comma_index(p->usr_name, curheapbuf1, 3) )
1338  continue;
1339  p += 1;
1340  }
1341  do_free_heapmem(g_count_list_heapptr);
1342  return curind1;
1343 }
1344 
1345 static int do_load_entry_inner(const char *fname, int type, const char *usr_name, sceNetCnfEnv_t *e)
1346 {
1347  int result;
1348  const char *curheapbuf1;
1349 
1350  result = do_handle_fname(g_dir_name, sizeof(g_dir_name), fname);
1351  if ( result < 0 )
1352  return result;
1353  result = do_handle_combination_path(type, g_dir_name, g_combination_buf1, sizeof(g_combination_buf1), usr_name);
1354  if ( result < 0 )
1355  return result;
1356  result = do_read_current_netcnf_nodecode(g_dir_name, &g_load_entry_heapptr);
1357  if ( result <= 0 )
1358  return !result ? -8 : result;
1359  for ( curheapbuf1 = g_load_entry_heapptr; *curheapbuf1; curheapbuf1 = do_get_str_line(curheapbuf1) )
1360  {
1361  if (
1362  do_type_check(type, curheapbuf1) >= 0 && !do_split_str_comma_index(g_arg_fname, curheapbuf1, 3)
1363  && !strcmp(g_arg_fname, g_combination_buf1) && !do_split_str_comma_index(g_arg_fname, curheapbuf1, 2) )
1364  {
1365  do_free_heapmem(g_load_entry_heapptr);
1366  e->dir_name = g_dir_name;
1367  e->arg_fname = g_arg_fname;
1368  e->req = type ? 2 : 1;
1369  return do_load_conf_inner(e);
1370  }
1371  }
1372  do_free_heapmem(g_load_entry_heapptr);
1373  return -8;
1374 }
1375 
1376 static void do_extra_ifc_handling(const char *arg_fname)
1377 {
1378  const char *i;
1379  const char *curptr1;
1380  unsigned int curbufsz1;
1381  unsigned int curindx;
1382 
1383  if ( !arg_fname || !*arg_fname )
1384  return;
1385  for ( i = &arg_fname[strlen(arg_fname) - 1]; i >= arg_fname && *i != '.'; i -= 1 )
1386  ;
1387  curptr1 = i - 1;
1388  if ( curptr1 < arg_fname || *i != '.' || !isdigit(*curptr1) )
1389  return;
1390  curbufsz1 = 0;
1391  curindx = 1;
1392  for ( ; curptr1 >= arg_fname && isdigit(*curptr1); curptr1 -= 1 )
1393  {
1394  curbufsz1 += curindx * (u8)(*curptr1 - '0');
1395  curindx *= 10;
1396  }
1397  if ( curbufsz1 < sizeof(g_ifc_buffer) )
1398  g_ifc_buffer[curbufsz1] = 1;
1399 }
1400 
1401 static void do_extra_pair_handling(char *fpath, int type, const char *src, const sceNetCnfEnv_t *e)
1402 {
1403  sceNetCnfEnv_t *heapmem;
1404  int conf_inner;
1405  struct sceNetCnfPair *i;
1406 
1407  if ( do_split_str_comma_index(g_arg_fname, src, 2) )
1408  return;
1409  heapmem = (sceNetCnfEnv_t *)do_alloc_heapmem(sizeof(sceNetCnfEnv_t) + 4096);
1410  if ( !heapmem )
1411  return;
1412  heapmem->req = 1;
1413  heapmem->mem_ptr = &heapmem[1];
1414  heapmem->mem_base = &heapmem[1];
1415  heapmem->dir_name = fpath;
1416  heapmem->arg_fname = g_arg_fname;
1417  heapmem->mem_last = ((char *)&heapmem[1]) + 4096;
1418  heapmem->f_no_check_magic = e->f_no_check_magic;
1419  heapmem->f_no_decode = e->f_no_decode;
1420  heapmem->f_verbose = e->f_verbose;
1421  conf_inner = do_load_conf_inner(heapmem);
1422  if ( (!conf_inner || conf_inner == -21) && heapmem->root )
1423  {
1424  for ( i = heapmem->root->pair_head; i; i = i->forw )
1425  {
1426  switch ( type )
1427  {
1428  case 1:
1429  do_extra_ifc_handling((char *)i->attach_ifc);
1430  break;
1431  case 2:
1432  do_extra_ifc_handling((char *)i->attach_dev);
1433  break;
1434  default:
1435  continue;
1436  }
1437  }
1438  }
1439  do_free_heapmem(heapmem);
1440 }
1441 
1442 static int do_add_entry_inner(
1443  const char *fname,
1444  int type,
1445  const char *usr_name,
1446  sceNetCnfEnv_t *e,
1447  const char *icon_value,
1448  const char *iconsys_value,
1449  int no_check_capacity)
1450 {
1451  int result;
1452  int retres2;
1453  const char *curentry1;
1454  int i;
1455  const char *curentry2;
1456  const char *k;
1457  int fd;
1458  char atomicrenamepath[256];
1459  int retres1;
1460  int maxflag;
1461 
1462  maxflag = 1;
1463  fd = -EPERM;
1464  if ( get_check_provider_eq_zero() )
1465  {
1466  result = do_check_provider_inner(e, type);
1467  if ( result < 0 )
1468  return result;
1469  }
1470  result = do_handle_fname(g_dir_name, sizeof(g_dir_name), fname);
1471  if ( result < 0 )
1472  return result;
1473  if ( !no_check_capacity )
1474  {
1475  result = do_check_capacity_inner(g_dir_name);
1476  if ( result < 0 )
1477  return result;
1478  }
1479  atomicrenamepath[0] = 0;
1480  result = do_handle_combination_path(type, g_dir_name, g_combination_buf1, sizeof(g_combination_buf1), usr_name);
1481  if ( result < 0 )
1482  return result;
1483  retres1 = do_read_current_netcnf_nodecode(g_dir_name, &g_add_entry_heapptr);
1484  if ( retres1 < 0 )
1485  return result;
1486  retres2 = do_remove_old_config(g_dir_name, g_add_entry_heapptr, icon_value, iconsys_value);
1487  if ( retres2 < 0 )
1488  maxflag = 0;
1489  if ( maxflag )
1490  {
1491  memset(g_ifc_buffer, 0, sizeof(g_ifc_buffer));
1492  if ( retres1 )
1493  {
1494  if ( !strncmp(g_dir_name, "mc", 2) )
1495  {
1496  i = 0;
1497  for ( curentry1 = g_add_entry_heapptr; *curentry1; curentry1 = do_get_str_line(curentry1) )
1498  {
1499  if ( do_type_check(type, curentry1) == 1 )
1500  i += 1;
1501  }
1502  switch ( type )
1503  {
1504  case 0:
1505  retres2 = -12;
1506  if ( i >= 6 )
1507  maxflag = 0;
1508  break;
1509  case 1:
1510  case 2:
1511  retres2 = -12;
1512  if ( i >= 4 )
1513  maxflag = 0;
1514  break;
1515  default:
1516  break;
1517  }
1518  }
1519  else if ( !strncmp(g_dir_name, "pfs", 3) )
1520  {
1521  i = 0;
1522  for ( curentry2 = g_add_entry_heapptr; *curentry2; curentry2 = do_get_str_line(curentry2) )
1523  {
1524  if ( do_type_check(type, curentry2) == 1 )
1525  i += 1;
1526  }
1527  switch ( type )
1528  {
1529  case 0:
1530  retres2 = -12;
1531  if ( i >= 10 )
1532  maxflag = 0;
1533  break;
1534  case 1:
1535  case 2:
1536  retres2 = -12;
1537  if ( i >= 30 )
1538  maxflag = 0;
1539  break;
1540  default:
1541  break;
1542  }
1543  }
1544  if ( maxflag )
1545  {
1546  for ( k = g_add_entry_heapptr; *k; k = do_get_str_line(k) )
1547  {
1548  if ( (unsigned int)(type - 1) < 2 && do_type_check(0, k) > 0 )
1549  do_extra_pair_handling(g_dir_name, type, k, e);
1550  if (
1551  do_type_check(type, k) > 0 && !do_split_str_comma_index(g_arg_fname, k, 1)
1552  && strtol(g_arg_fname, 0, 10) == 1 && !do_split_str_comma_index(g_arg_fname, k, 2) )
1553  {
1554  do_extra_ifc_handling(g_arg_fname);
1555  if ( !do_split_str_comma_index(g_arg_fname, k, 3) && !strcmp(g_combination_buf1, g_arg_fname) )
1556  {
1557  do_free_heapmem(g_add_entry_heapptr);
1558  return -11;
1559  }
1560  }
1561  }
1562  }
1563  }
1564  }
1565  if ( maxflag )
1566  {
1567  char *endbuf;
1568  const char *fileext;
1569 
1570  do_safe_strcpy(g_arg_fname, sizeof(g_arg_fname), g_dir_name, 740);
1571  for ( endbuf = &g_arg_fname[strlen(g_arg_fname) - 1];
1572  endbuf >= g_arg_fname && *endbuf != ':' && *endbuf != '/' && *endbuf != '\\';
1573  endbuf -= 1 )
1574  ;
1575  if ( endbuf >= g_arg_fname && *endbuf != ':' && *endbuf != '/' && *endbuf != '\\' )
1576  {
1577  *endbuf = 0;
1578  }
1579  else
1580  {
1581  endbuf[1] = 0;
1582  }
1583  fileext = (type && !e->f_no_decode) ? ".dat" : ".cnf";
1584  for ( i = 0; i < (int)(sizeof(g_ifc_buffer)); i += 1 )
1585  {
1586  if ( !g_ifc_buffer[i] )
1587  {
1588  switch ( type )
1589  {
1590  case 1:
1591  // Unofficial: specify max length for g_arg_fname to avoid overflow
1592  sprintf(g_netcnf_file_path, "%.245sifc%03d%s", g_arg_fname, i, fileext);
1593  break;
1594  case 2:
1595  // Unofficial: specify max length for g_arg_fname to avoid overflow
1596  sprintf(g_netcnf_file_path, "%.245sdev%03d%s", g_arg_fname, i, fileext);
1597  break;
1598  case 3:
1599  // Unofficial: specify max length for g_arg_fname to avoid overflow
1600  sprintf(g_netcnf_file_path, "%.245snet%03d%s", g_arg_fname, i, fileext);
1601  break;
1602  default:
1603  do_free_heapmem(g_add_entry_heapptr);
1604  return -10;
1605  }
1606  fd = do_open_netcnf(g_netcnf_file_path, 1, 0);
1607  if ( fd < 0 )
1608  {
1609  if ( fd == -EIO )
1610  return -18;
1611  break;
1612  }
1613  do_close_netcnf(fd);
1614  }
1615  }
1616  retres2 = -12;
1617  if ( i < (int)(sizeof(g_ifc_buffer)) )
1618  {
1619  char *dirname_buf1;
1620  char *cur_entry_buffer;
1621 
1622  cur_entry_buffer = g_entry_buffer;
1623  for ( dirname_buf1 = g_dir_name; *dirname_buf1; dirname_buf1 += 1 )
1624  {
1625  if ( (*dirname_buf1 == '/' || *dirname_buf1 == '\\') && dirname_buf1[1] )
1626  {
1627  *cur_entry_buffer = 0;
1628  retres2 = mkdir(g_entry_buffer, 511);
1629  if ( !retres2 && !strncmp(g_dir_name, "mc", 2) )
1630  {
1631  do_chstat_mode_copyprotect_wrap(g_entry_buffer);
1632  retres2 = do_write_memcard_files(g_dir_name, icon_value, iconsys_value);
1633  if ( retres2 < 0 )
1634  break;
1635  }
1636  if ( retres2 == -5 )
1637  break;
1638  retres2 = -18;
1639  }
1640  *cur_entry_buffer = *dirname_buf1;
1641  cur_entry_buffer += 1;
1642  }
1643  if ( *dirname_buf1 )
1644  {
1645  e->dir_name = g_dir_name;
1646  e->arg_fname = &g_netcnf_file_path[strlen(g_arg_fname)];
1647  e->req = type ? 2 : 1;
1648  retres2 = -1;
1649  if ( !do_export_netcnf(e) )
1650  {
1651  do_safe_make_name(atomicrenamepath, sizeof(atomicrenamepath), g_dir_name, ".tmp");
1652  fd = do_open_netcnf(atomicrenamepath, 1538, 511);
1653  if ( fd < 0 )
1654  {
1655  retres2 = (fd == -EIO) ? -18 : -3;
1656  }
1657  else
1658  {
1659  int strlenx;
1660  int writeres;
1661 
1662  strlenx = sprintf(
1663  g_entry_buffer, "%d,%d,%s,%s\n", type, 1, &g_netcnf_file_path[strlen(g_arg_fname)], g_combination_buf1);
1664  writeres = do_write_netcnf_no_encode(fd, g_entry_buffer, strlenx);
1665  retres2 = 0;
1666  if ( strlenx != writeres )
1667  {
1668  retres2 = (writeres == -EIO) ? -18 : -5;
1669  }
1670  else
1671  {
1672  writeres = do_write_netcnf_no_encode(fd, g_add_entry_heapptr, retres1);
1673  if ( retres1 != writeres )
1674  {
1675  retres2 = (writeres == -EIO) ? -18 : -5;
1676  }
1677  }
1678  }
1679  }
1680  }
1681  }
1682  }
1683  do_free_heapmem(g_add_entry_heapptr);
1684  if ( fd >= 0 )
1685  do_close_netcnf(fd);
1686  // Unofficial: dead code removed
1687  return (atomicrenamepath[0] && iomanX_rename(atomicrenamepath, g_dir_name) == -EIO) ?
1688  -18 :
1689  ((strncmp(g_dir_name, "pfs", 3) || iomanX_sync(g_dir_name, 0) != -EIO) ? retres2 : -18);
1690 }
1691 
1692 static int do_handle_set_usrname(const char *fpath, int type, const char *usrname_buf2, const char *usrname_bufnew)
1693 {
1694  int result;
1695  int retres1;
1696  char *heapmem;
1697  const char *ptr_1;
1698  char *heapmem_1;
1699  int writeres1;
1700  char *ptr;
1701 
1702  ptr = 0;
1703  if ( !usrname_buf2 )
1704  return -11;
1705  result = do_handle_combination_path(type, g_dir_name, g_combination_buf1, sizeof(g_combination_buf1), usrname_bufnew);
1706  if ( result < 0 )
1707  return result;
1708  retres1 = do_read_current_netcnf_nodecode(fpath, &ptr);
1709  if ( retres1 <= 0 )
1710  return (!retres1) ? -3 : retres1;
1711  heapmem = (char *)do_alloc_heapmem((int)((unsigned int)retres1 + strlen(usrname_bufnew) + 1));
1712  if ( !heapmem )
1713  {
1714  do_free_heapmem(ptr);
1715  return -2;
1716  }
1717  ptr_1 = ptr;
1718  heapmem_1 = heapmem;
1719  while ( *ptr_1 )
1720  {
1721  if ( do_type_check(type, ptr_1) > 0 && !do_split_str_comma_index(g_arg_fname, ptr_1, 3) )
1722  {
1723  if ( !strcmp(g_arg_fname, usrname_buf2) )
1724  {
1725  if ( !do_split_str_comma_index(g_arg_fname, ptr_1, 2) )
1726  {
1727  heapmem_1 += sprintf(heapmem_1, "%d,%d,%s,%s\n", type, 1, g_arg_fname, g_combination_buf1);
1728  ptr_1 = do_get_str_line(ptr_1);
1729  continue;
1730  }
1731  }
1732  else if ( !strcmp(g_arg_fname, g_combination_buf1) )
1733  {
1734  do_free_heapmem(ptr);
1735  do_free_heapmem(heapmem);
1736  return -11;
1737  }
1738  }
1739  for ( ; *ptr_1 && *ptr_1 != '\n'; ptr_1 += 1 )
1740  {
1741  *heapmem_1 = *ptr_1;
1742  heapmem_1 += 1;
1743  }
1744  if ( *ptr_1 == '\n' )
1745  {
1746  *heapmem_1 = *ptr_1;
1747  heapmem_1 += 1;
1748  ptr_1 += 1;
1749  }
1750  }
1751  do_free_heapmem(ptr);
1752  writeres1 = do_write_noencode_netcnf_atomic(fpath, heapmem, (int)(heapmem_1 - heapmem));
1753  do_free_heapmem(heapmem);
1754  return writeres1;
1755 }
1756 
1757 static int do_edit_entry_inner(
1758  const char *fname,
1759  int type,
1760  const char *usr_name,
1761  const char *new_usr_name,
1762  sceNetCnfEnv_t *e,
1763  const char *icon_value,
1764  const char *iconsys_value,
1765  int no_check_capacity)
1766 {
1767  int result;
1768  int rmoldcfgres;
1769  const char *curentry1;
1770  char curentrybuf1[256];
1771  char curfilepath1[256];
1772 
1773  if ( get_check_provider_eq_zero() )
1774  {
1775  result = do_check_provider_inner(e, type);
1776  if ( result < 0 )
1777  return result;
1778  }
1779  result = do_handle_fname(g_dir_name, sizeof(g_dir_name), fname);
1780  if ( result < 0 )
1781  return result;
1782  if ( !no_check_capacity )
1783  {
1784  result = do_check_capacity_inner(g_dir_name);
1785  if ( result < 0 )
1786  return result;
1787  }
1788  result = do_handle_combination_path(type, g_dir_name, g_combination_buf2, sizeof(g_combination_buf2), usr_name);
1789  if ( result < 0 )
1790  return result;
1791  result = do_read_current_netcnf_nodecode(g_dir_name, &g_edit_entry_heapptr);
1792  if ( result <= 0 )
1793  {
1794  return !result ? -3 : result;
1795  }
1796  rmoldcfgres = do_remove_old_config(g_dir_name, g_edit_entry_heapptr, icon_value, iconsys_value);
1797  if ( rmoldcfgres >= 0 )
1798  {
1799  int flg;
1800 
1801  rmoldcfgres = 0;
1802  for ( curentry1 = g_edit_entry_heapptr; *curentry1; curentry1 = do_get_str_line(curentry1) )
1803  {
1804  if (
1805  do_type_check(type, curentry1) > 0 && !do_split_str_comma_index(g_arg_fname, curentry1, 3)
1806  && !strcmp(g_arg_fname, g_combination_buf2) && !do_split_str_comma_index(curentrybuf1, curentry1, 2) )
1807  {
1808  rmoldcfgres += 1;
1809  }
1810  }
1811  flg = 0;
1812  if ( !rmoldcfgres )
1813  {
1814  rmoldcfgres = -8;
1815  }
1816  else
1817  {
1818  if ( !get_check_provider_eq_zero() )
1819  {
1820  flg = 1;
1821  }
1822  if ( !flg )
1823  {
1824  rmoldcfgres = !do_handle_netcnf_dirname(g_dir_name, curentrybuf1, curfilepath1) ?
1825  -11 :
1826  do_read_check_netcnf(curfilepath1, type, e->f_no_check_magic, e->f_no_decode);
1827  }
1828  }
1829  if ( flg || rmoldcfgres >= 0 )
1830  {
1831  do_safe_make_name(curfilepath1, sizeof(curfilepath1), curentrybuf1, ".tmp");
1832  e->dir_name = g_dir_name;
1833  // cppcheck-suppress autoVariables
1834  e->arg_fname = curfilepath1;
1835  e->req = type ? 2 : 1;
1836  if ( do_export_netcnf(e) )
1837  {
1838  rmoldcfgres = -1;
1839  }
1840  else
1841  {
1842  char *curfilepath1end;
1843 
1844  do_safe_strcpy(curfilepath1, sizeof(curfilepath1), g_dir_name, 1010);
1845  for ( curfilepath1end = &curfilepath1[strlen(curfilepath1)]; curfilepath1end != curfilepath1;
1846  curfilepath1end -= 1 )
1847  {
1848  if ( *curfilepath1end == '/' || *curfilepath1end == '\\' )
1849  {
1850  curfilepath1end[1] = 0;
1851  break;
1852  }
1853  }
1854  do_safe_strcat(curfilepath1, sizeof(curfilepath1), curentrybuf1, 1017);
1855  do_safe_strcpy(curentrybuf1, sizeof(curentrybuf1), curfilepath1, 1018);
1856  do_safe_strcat(curfilepath1, sizeof(curfilepath1), ".tmp", 1019);
1857  if ( iomanX_rename(curfilepath1, curentrybuf1) == -EIO )
1858  rmoldcfgres = -18;
1859  }
1860  }
1861  }
1862  do_free_heapmem(g_edit_entry_heapptr);
1863  if ( rmoldcfgres >= 0 )
1864  {
1865  do_set_latest_entry_inner(g_dir_name, type, g_combination_buf2);
1866  if ( new_usr_name )
1867  rmoldcfgres = do_handle_set_usrname(g_dir_name, type, g_combination_buf2, new_usr_name);
1868  }
1869  return (!strncmp(g_dir_name, "pfs", 3) && iomanX_sync(g_dir_name, 0) == -EIO) ? -18 : rmoldcfgres;
1870 }
1871 
1872 static int do_delete_entry_inner(
1873  const char *fname,
1874  int type,
1875  const char *usr_name,
1876  const char *icon_value,
1877  const char *iconsys_value,
1878  int no_check_capacity)
1879 {
1880  int has_comma;
1881  int result;
1882  char *heapmem;
1883  const char *curentry1;
1884 
1885  has_comma = 0;
1886  g_delete_entry_heapptr = 0;
1887  result = do_handle_fname(g_dir_name, sizeof(g_dir_name), fname);
1888  if ( result < 0 )
1889  {
1890  return result;
1891  }
1892  if ( !no_check_capacity )
1893  {
1894  result = do_check_capacity_inner(g_dir_name);
1895  if ( result < 0 )
1896  return result;
1897  }
1898  result = do_handle_combination_path(type, g_dir_name, g_combination_buf1, sizeof(g_combination_buf1), usr_name);
1899  if ( result < 0 )
1900  return result;
1901  result = do_read_current_netcnf_nodecode(g_dir_name, &g_delete_entry_heapptr);
1902  if ( result <= 0 )
1903  return !result ? -3 : result;
1904  heapmem = (char *)do_alloc_heapmem(result);
1905  if ( !heapmem )
1906  {
1907  do_free_heapmem(g_delete_entry_heapptr);
1908  return -2;
1909  }
1910  result = do_remove_old_config(g_dir_name, g_delete_entry_heapptr, icon_value, iconsys_value);
1911  if ( result >= 0 )
1912  {
1913  char *heapmem_1;
1914 
1915  curentry1 = g_delete_entry_heapptr;
1916  heapmem_1 = heapmem;
1917  while ( *curentry1 )
1918  {
1919  if (
1920  do_type_check(type, curentry1) <= 0 || do_split_str_comma_index(g_arg_fname, curentry1, 3)
1921  || strcmp(g_arg_fname, g_combination_buf1) )
1922  {
1923  for ( ; *curentry1 && *curentry1 != '\n'; curentry1 += 1 )
1924  {
1925  *heapmem_1 = *curentry1;
1926  heapmem_1 += 1;
1927  }
1928  if ( *curentry1 == '\n' )
1929  {
1930  *heapmem_1 = *curentry1;
1931  heapmem_1 += 1;
1932  curentry1 += 1;
1933  }
1934  }
1935  else
1936  {
1937  if ( !do_split_str_comma_index(g_entry_buffer, curentry1, 2) )
1938  has_comma = 1;
1939  curentry1 = do_get_str_line(curentry1);
1940  }
1941  }
1942  result = do_write_noencode_netcnf_atomic(g_dir_name, heapmem, (int)(heapmem_1 - heapmem));
1943  if ( result >= 0 && has_comma )
1944  result = do_remove_netcnf_dirname(g_dir_name, g_entry_buffer);
1945  }
1946  do_free_heapmem(g_delete_entry_heapptr);
1947  do_free_heapmem(heapmem);
1948  return (!strncmp(g_dir_name, "pfs", 3) && iomanX_sync(g_dir_name, 0) == -EIO) ? -18 : result;
1949 }
1950 
1951 static int do_set_latest_entry_inner(const char *fname, int type, const char *usr_name)
1952 {
1953  int isbeforeend1;
1954  int result;
1955  char *heapmem2;
1956  int readsz;
1957  char *heapmem1;
1958  char *heapmem1_1;
1959  char *curentry1;
1960 
1961  isbeforeend1 = 0;
1962  result = do_handle_fname(g_dir_name, sizeof(g_dir_name), fname);
1963  if ( result < 0 )
1964  {
1965  return result;
1966  }
1967  result = do_handle_combination_path(type, g_dir_name, g_combination_buf1, sizeof(g_combination_buf1), usr_name);
1968  heapmem2 = 0;
1969  if ( result < 0 )
1970  {
1971  return result;
1972  }
1973  g_set_latest_entry_heapptr = 0;
1974  result = do_read_current_netcnf_nodecode(g_dir_name, &g_set_latest_entry_heapptr);
1975  readsz = result;
1976  if ( result <= 0 )
1977  {
1978  return !result ? -3 : result;
1979  }
1980  result = -2;
1981  heapmem1 = (char *)do_alloc_heapmem(readsz);
1982  heapmem1_1 = heapmem1;
1983  if ( heapmem1 )
1984  {
1985  char *heapmem2_1;
1986 
1987  heapmem2 = (char *)do_alloc_heapmem(readsz);
1988  heapmem2_1 = heapmem2;
1989  if ( heapmem2 )
1990  {
1991  curentry1 = g_set_latest_entry_heapptr;
1992  result = 0;
1993  while ( *curentry1 )
1994  {
1995  if (
1996  do_type_check(type, curentry1) > 0 && !do_split_str_comma_index(g_arg_fname, curentry1, 3)
1997  && !strcmp(g_arg_fname, g_combination_buf1) )
1998  {
1999  for ( ; *curentry1 && *curentry1 != '\n'; curentry1 += 1 )
2000  {
2001  *heapmem1_1 = *curentry1;
2002  heapmem1_1 += 1;
2003  }
2004  if ( *curentry1 == '\n' )
2005  {
2006  *heapmem1_1 = *curentry1;
2007  heapmem1_1 += 1;
2008  curentry1 += 1;
2009  }
2010  result += 1;
2011  if ( heapmem2 < heapmem2_1 )
2012  isbeforeend1 = 1;
2013  }
2014  else
2015  {
2016  for ( ; *curentry1 && *curentry1 != '\n'; curentry1 += 1 )
2017  {
2018  *heapmem2_1 = *curentry1;
2019  heapmem2_1 += 1;
2020  }
2021  if ( *curentry1 == '\n' )
2022  {
2023  *heapmem2_1 = *curentry1;
2024  heapmem2_1 += 1;
2025  curentry1 += 1;
2026  }
2027  }
2028  }
2029  if ( isbeforeend1 )
2030  {
2031  memcpy(heapmem1_1, heapmem2, (u32)(heapmem2_1 - heapmem2));
2032  result =
2033  do_write_noencode_netcnf_atomic(g_dir_name, heapmem1, (int)(heapmem1_1 - heapmem1 + heapmem2_1 - heapmem2));
2034  }
2035  }
2036  }
2037  do_free_heapmem(g_set_latest_entry_heapptr);
2038  do_free_heapmem(heapmem1);
2039  do_free_heapmem(heapmem2);
2040  return (!strncmp(g_dir_name, "pfs", 3) && iomanX_sync(g_dir_name, 0) == -EIO) ? -18 : result;
2041 }
2042 
2043 static int do_delete_all_inner(const char *dev)
2044 {
2045  int i;
2046  int dread_res;
2047  iox_dirent_t statname;
2048 
2049  if ( !strncmp(dev, "mc", 2) )
2050  {
2051  int dfd1;
2052 
2053  for ( i = 0; dev[i] != ':'; i += 1 )
2054  {
2055  g_netcnf_file_path[i] = dev[i];
2056  }
2057  g_netcnf_file_path[i] = dev[i];
2058  g_netcnf_file_path[i + 1] = 0;
2059  do_safe_strcat(g_netcnf_file_path, sizeof(g_netcnf_file_path), "/BWNETCNF", 1199);
2060  dfd1 = do_dopen_wrap(g_netcnf_file_path);
2061  // cppcheck-suppress knownConditionTrueFalse
2062  if ( dfd1 < 0 )
2063  return 0;
2064  while ( 1 )
2065  {
2066  dread_res = do_dread_wrap(dfd1, &statname);
2067  // cppcheck-suppress knownConditionTrueFalse
2068  if ( dread_res <= 0 )
2069  break;
2070  if ( strcmp(statname.name, ".") && strcmp(statname.name, "..") )
2071  {
2072  do_safe_make_pathname(g_dir_name, sizeof(g_dir_name), g_netcnf_file_path, statname.name);
2073  if ( do_remove_wrap(g_dir_name) < 0 )
2074  {
2075  do_dclose_wrap(dfd1);
2076  return -7;
2077  }
2078  }
2079  }
2080  do_dclose_wrap(dfd1);
2081  return (rmdir(g_netcnf_file_path) < 0) ? -7 : 0;
2082  }
2083  else if ( !strncmp(dev, "pfs", 3) )
2084  {
2085  int dfd2;
2086  int remove_res2;
2087  int rmdir_res1;
2088 
2089  for ( i = 0; dev[i] != ':'; i += 1 )
2090  {
2091  g_netcnf_file_path[i] = dev[i];
2092  }
2093  g_netcnf_file_path[i] = dev[i];
2094  g_netcnf_file_path[i + 1] = 0;
2095  do_safe_strcat(g_netcnf_file_path, sizeof(g_netcnf_file_path), "/etc/network", 1229);
2096  dfd2 = do_dopen_wrap(g_netcnf_file_path);
2097  // cppcheck-suppress knownConditionTrueFalse
2098  if ( dfd2 < 0 )
2099  {
2100  return (dfd2 == -EIO) ? -18 : 0;
2101  }
2102  while ( 1 )
2103  {
2104  dread_res = do_dread_wrap(dfd2, &statname);
2105  // cppcheck-suppress knownConditionTrueFalse
2106  if ( dread_res <= 0 )
2107  break;
2108  if ( strcmp(statname.name, ".") && strcmp(statname.name, "..") )
2109  {
2110  do_safe_make_pathname(g_dir_name, sizeof(g_dir_name), g_netcnf_file_path, statname.name);
2111  remove_res2 = do_remove_wrap(g_dir_name);
2112  if ( remove_res2 < 0 )
2113  {
2114  do_dclose_wrap(dfd2);
2115  return (remove_res2 == -EIO) ? -18 : -7;
2116  }
2117  }
2118  }
2119  if ( dread_res == -EIO )
2120  {
2121  do_dclose_wrap(dfd2);
2122  return -18;
2123  }
2124  do_dclose_wrap(dfd2);
2125  rmdir_res1 = rmdir(g_netcnf_file_path);
2126  return (rmdir_res1 >= 0) ? ((iomanX_sync(g_netcnf_file_path, 0) != -EIO) ? 0 : -18) :
2127  ((rmdir_res1 == -EIO) ? -18 : -7);
2128  }
2129  return -17;
2130 }
2131 
2132 static int do_check_special_provider_inner(const char *fname, int type, const char *usr_name, sceNetCnfEnv_t *e)
2133 {
2134  int result;
2135  const char *curentry1;
2136  int curentcount;
2137  int retres;
2138 
2139  result = do_handle_fname(g_dir_name, sizeof(g_dir_name), fname);
2140  if ( result < 0 )
2141  return result;
2142  result = do_handle_combination_path(type, g_dir_name, g_combination_buf2, sizeof(g_combination_buf2), usr_name);
2143  if ( result < 0 )
2144  return result;
2145  result = do_read_current_netcnf_nodecode(g_dir_name, &g_check_special_provider_heapptr);
2146  if ( result <= 0 )
2147  {
2148  return !result ? -3 : result;
2149  }
2150  curentcount = 0;
2151  for ( curentry1 = g_check_special_provider_heapptr; *curentry1; curentry1 = do_get_str_line(curentry1) )
2152  {
2153  if (
2154  do_type_check(type, curentry1) > 0 && !do_split_str_comma_index(g_arg_fname, curentry1, 3)
2155  && !strcmp(g_arg_fname, g_combination_buf2) && !do_split_str_comma_index((char *)e->lbuf, curentry1, 2) )
2156  {
2157  curentcount += 1;
2158  }
2159  }
2160  retres = curentcount ? ((do_handle_netcnf_dirname(g_dir_name, (const char *)e->lbuf, (char *)e->dbuf)) ?
2161  do_read_check_netcnf((const char *)e->dbuf, type, e->f_no_check_magic, e->f_no_decode) :
2162  -11) :
2163  -8;
2164  do_free_heapmem(g_check_special_provider_heapptr);
2165  return retres;
2166 }
2167 
2168 static char *do_alloc_mem_inner(sceNetCnfEnv_t *e, unsigned int size, int align)
2169 {
2170  void *mem_ptr;
2171  char *retptrbegin;
2172 
2173  mem_ptr = e->mem_ptr;
2174  if ( !mem_ptr )
2175  {
2176  e->alloc_err += 1;
2177  return 0;
2178  }
2179  retptrbegin = (char *)(((uiptr)mem_ptr + (1 << align) - 1) & (uiptr) ~((1 << align) - 1));
2180  if ( &retptrbegin[size] >= (char *)e->mem_last )
2181  {
2182  e->alloc_err += 1;
2183  return 0;
2184  }
2185  e->mem_ptr = &retptrbegin[size];
2186  memset(retptrbegin, 0, size);
2187  return retptrbegin;
2188 }
2189 
2190 static const char *do_netcnf_parse_string(sceNetCnfEnv_t *e, const char *e_arg)
2191 {
2192  u8 *dbuf;
2193  const char *argbegin;
2194  int i;
2195  int hexnum;
2196  int err;
2197 
2198  dbuf = e->dbuf;
2199  if ( *e_arg != '"' )
2200  return e_arg;
2201  err = 0;
2202  for ( argbegin = e_arg + 1; *argbegin && *argbegin != '"' && (char *)(dbuf + 1) < (char *)&(e->dbuf[1023]); )
2203  {
2204  char argchr_1;
2205 
2206  argchr_1 = *argbegin;
2207  argbegin += 1;
2208  if ( argchr_1 == '\\' )
2209  {
2210  if ( !*argbegin )
2211  {
2212  err = 1;
2213  break;
2214  }
2215  argchr_1 = 0;
2216  if ( (unsigned int)(((u8)*argbegin) - '0') >= 8 )
2217  {
2218  if ( ((u8)*argbegin) == 'x' || ((u8)*argbegin) == 'X' )
2219  {
2220  argbegin += 1;
2221  argchr_1 = 0;
2222  if ( !isxdigit(*argbegin) )
2223  {
2224  err = 2;
2225  break;
2226  }
2227  for ( i = 0; i < 2 && isxdigit(*argbegin); i += 1 )
2228  {
2229  hexnum = 16 * argchr_1;
2230  argchr_1 =
2231  (char)(hexnum
2232  + (isdigit(*argbegin) ? (((u8)*argbegin) - '0') : ((!islower(*argbegin)) ? ((u8)*argbegin) - '7' : ((u8)*argbegin) - 'W')));
2233  argbegin += 1;
2234  }
2235  }
2236  else
2237  {
2238  argchr_1 = *argbegin;
2239  argbegin += 1;
2240  switch ( argchr_1 )
2241  {
2242  case 'a':
2243  argchr_1 = 7;
2244  break;
2245  case 'b':
2246  argchr_1 = 8;
2247  break;
2248  case 'f':
2249  argchr_1 = 12;
2250  break;
2251  case 'n':
2252  argchr_1 = 10;
2253  break;
2254  case 'r':
2255  argchr_1 = 13;
2256  break;
2257  case 't':
2258  argchr_1 = 9;
2259  break;
2260  case 'v':
2261  argchr_1 = 11;
2262  break;
2263  default:
2264  break;
2265  }
2266  }
2267  }
2268  else
2269  {
2270  for ( i = 0; i < 3 && (((u8)*argbegin) - (unsigned int)'0' < 8); i += 1 )
2271  {
2272  argchr_1 = 8 * argchr_1 + *argbegin - '0';
2273  argbegin += 1;
2274  }
2275  }
2276  }
2277  else if ( (unsigned int)(argchr_1 - 129) < 0x1F || (unsigned int)(argchr_1 - 224) < 0x1D )
2278  {
2279  if ( (u8)(((u8)*argbegin) - 64) < 0xBDu && ((u8)*argbegin) != 127 )
2280  {
2281  *dbuf = (u8)argchr_1;
2282  dbuf += 1;
2283  argchr_1 = *argbegin;
2284  argbegin += 1;
2285  }
2286  }
2287  *dbuf = (u8)argchr_1;
2288  dbuf += 1;
2289  }
2290  if ( !err )
2291  {
2292  if ( ((u8)*argbegin) != '"' )
2293  {
2294  err = 3;
2295  }
2296  else if ( argbegin[1] )
2297  {
2298  err = 4;
2299  }
2300  }
2301  if ( err )
2302  {
2303  printf("netcnf: \"%s\" line %d: ", e->fname, e->lno);
2304  switch ( err )
2305  {
2306  case 1:
2307  printf("invalid escape (%s)", e_arg);
2308  break;
2309  case 2:
2310  printf("missing hexa-decimal(%s)", e_arg);
2311  break;
2312  case 3:
2313  printf("invalid quote (%s)", e_arg);
2314  break;
2315  case 4:
2316  printf("invalid extra chars (%s)", e_arg);
2317  break;
2318  default:
2319  break;
2320  }
2321  printf("\n");
2322  e->syntax_err += 1;
2323  return 0;
2324  }
2325  *dbuf = 0;
2326  return (const char *)e->dbuf;
2327 }
2328 
2329 static char *do_alloc_mem_for_write(sceNetCnfEnv_t *e, const char *str)
2330 {
2331  char *strptr;
2332 
2333  strptr = do_alloc_mem_inner(e, (unsigned int)strlen(str) + 1, 0);
2334  if ( !strptr )
2335  return 0;
2336  strcpy(strptr, str);
2337  return strptr;
2338 }
2339 
2340 static char *do_check_e_arg(sceNetCnfEnv_t *e, const char *e_arg)
2341 {
2342  const char *strptr;
2343 
2344  strptr = do_netcnf_parse_string(e, e_arg);
2345  return strptr ? do_alloc_mem_for_write(e, strptr) : 0;
2346 }
2347 
2348 static int do_parse_number(sceNetCnfEnv_t *e, const char *e_arg, unsigned int *n_result)
2349 {
2350  const char *e_arg_1;
2351  unsigned int curbasex;
2352  unsigned int curnum;
2353 
2354  e_arg_1 = e_arg;
2355  curbasex = 10;
2356  if ( *e_arg == '0' && e_arg[1] )
2357  {
2358  e_arg_1 = e_arg + 1;
2359  curbasex = 8;
2360  if ( e_arg[1] == 'x' )
2361  {
2362  e_arg_1 = e_arg + 2;
2363  curbasex = 16;
2364  }
2365  }
2366  curnum = 0;
2367  if ( *e_arg_1 )
2368  {
2369  while ( 1 )
2370  {
2371  u32 e_arg_1_num;
2372 
2373  e_arg_1_num = (((u8)*e_arg_1)) - '0';
2374  if ( ((u8)*e_arg_1) - (unsigned int)'0' >= 0xA )
2375  {
2376  e_arg_1_num = (((u8)*e_arg_1)) - 'W';
2377  if ( ((u8)*e_arg_1) - (unsigned int)'a' >= 6 )
2378  break;
2379  }
2380  if ( e_arg_1_num >= curbasex )
2381  break;
2382  e_arg_1 += 1;
2383  curnum = curnum * curbasex + e_arg_1_num;
2384  if ( !*e_arg_1 )
2385  {
2386  *n_result = curnum;
2387  return 0;
2388  }
2389  }
2390  }
2391  printf("netcnf: \"%s\" line %d: ", e->fname, e->lno);
2392  printf("invalid digit (%s)", e_arg);
2393  printf("\n");
2394  e->syntax_err += 1;
2395  return -1;
2396 }
2397 
2398 static int do_netcnfname2address_wrap(sceNetCnfEnv_t *e, const char *buf, sceNetCnfAddress_t *paddr)
2399 {
2400  int errret;
2401 
2402  errret = sceNetCnfName2Address(paddr, buf);
2403  if ( errret < 0 )
2404  {
2405  printf("netcnf: \"%s\" line %d: ", e->fname, e->lno);
2406  printf("sceNetCnfName2Address(%s) -> %d\n", buf, errret);
2407  printf("\n");
2408  e->syntax_err += 1;
2409  return -1;
2410  }
2411  return 0;
2412 }
2413 
2414 static int do_parse_phone_argument(sceNetCnfEnv_t *e, int opt_argc, const char **opt_argv, unsigned int *p_result)
2415 {
2416  int i;
2417  unsigned int bitflags1;
2418  unsigned int numval;
2419 
2420  bitflags1 = 0;
2421  for ( i = 0; i < opt_argc; i += 1 )
2422  {
2423  if ( !strcmp("phase", opt_argv[i]) )
2424  {
2425  bitflags1 |= 1;
2426  }
2427  else if ( !strcmp("cp", opt_argv[i]) )
2428  {
2429  bitflags1 |= 2;
2430  }
2431  else if ( !strcmp("auth", opt_argv[i]) )
2432  {
2433  bitflags1 |= 4;
2434  }
2435  else if ( !strcmp("chat", opt_argv[i]) )
2436  {
2437  bitflags1 |= 8;
2438  }
2439  else if ( !strcmp("private", opt_argv[i]) )
2440  {
2441  bitflags1 |= 0x10;
2442  }
2443  else if ( !strcmp("dll", opt_argv[i]) )
2444  {
2445  bitflags1 |= 0x20;
2446  }
2447  else if ( !strcmp("dump", opt_argv[i]) )
2448  {
2449  bitflags1 |= 0x40;
2450  }
2451  else if ( !strcmp("timer", opt_argv[i]) )
2452  {
2453  bitflags1 |= 0x10000;
2454  }
2455  else if ( !strcmp("event", opt_argv[i]) )
2456  {
2457  bitflags1 |= 0x20000;
2458  }
2459  else if ( do_parse_number(e, opt_argv[i], &numval) )
2460  return -1;
2461  }
2462  *p_result = bitflags1;
2463  return 0;
2464 }
2465 
2466 static int do_check_interface_keyword(
2467  sceNetCnfEnv_t *e, const char *display_name_arg, const char *attach_ifc_arg, const char *attach_dev_arg)
2468 {
2469  struct sceNetCnfPair *cnfpair1;
2470  struct sceNetCnfPair *pair_tail;
2471 
2472  cnfpair1 = (sceNetCnfPair_t *)do_alloc_mem_inner(e, sizeof(sceNetCnfPair_t), 2);
2473  if ( !cnfpair1 )
2474  return -1;
2475  cnfpair1->display_name = (u8 *)do_check_e_arg(e, display_name_arg);
2476  if ( !cnfpair1->display_name )
2477  return -1;
2478  cnfpair1->attach_ifc = (u8 *)do_check_e_arg(e, attach_ifc_arg);
2479  if ( !cnfpair1->attach_ifc )
2480  return -1;
2481  if ( attach_dev_arg && *attach_dev_arg )
2482  {
2483  cnfpair1->attach_dev = (u8 *)do_check_e_arg(e, attach_dev_arg);
2484  if ( !cnfpair1->attach_dev )
2485  return -1;
2486  }
2487  pair_tail = e->root->pair_tail;
2488  cnfpair1->back = pair_tail;
2489  if ( !pair_tail )
2490  pair_tail = (sceNetCnfPair_t *)e->root;
2491  pair_tail->forw = cnfpair1;
2492  cnfpair1->forw = 0;
2493  e->root->pair_tail = cnfpair1;
2494  return 0;
2495 }
2496 
2497 static int do_check_nameserver(sceNetCnfEnv_t *e, struct sceNetCnfInterface *ifc, int opt_argc, const char **opt_argv)
2498 {
2499  int addordel;
2500  nameserver_t *nameservermem_1;
2501 
2502  if ( opt_argc < 3 )
2503  return 0;
2504 
2505  if ( !strcmp("add", opt_argv[1]) )
2506  addordel = 1;
2507  else if ( !strcmp("del", opt_argv[1]) )
2508  addordel = 2;
2509  else
2510  return 0;
2511  nameservermem_1 = (nameserver_t *)do_alloc_mem_inner(e, sizeof(nameserver_t), 2);
2512  if ( !nameservermem_1 )
2513  return -1;
2514  nameservermem_1->cmd.code = addordel;
2515  if ( do_netcnfname2address_wrap(e, opt_argv[2], &nameservermem_1->address) )
2516  return -1;
2517  nameservermem_1->cmd.back = ifc->cmd_tail;
2518  if ( ifc->cmd_tail )
2519  ifc->cmd_tail->forw = &nameservermem_1->cmd;
2520  else
2521  ifc->cmd_head = &nameservermem_1->cmd;
2522  nameservermem_1->cmd.forw = 0;
2523  ifc->cmd_tail = &nameservermem_1->cmd;
2524  return 0;
2525 }
2526 
2527 static int do_check_route(sceNetCnfEnv_t *e, struct sceNetCnfInterface *ifc, int opt_argc, const char **opt_argv)
2528 {
2529  int addordel;
2530  route_t *route_mem_1;
2531  int i;
2532 
2533  if ( opt_argc < 3 )
2534  return 0;
2535  if ( !strcmp("add", opt_argv[1]) )
2536  addordel = 3;
2537  else if ( !strcmp("del", opt_argv[1]) )
2538  addordel = 4;
2539  else
2540  return 0;
2541  route_mem_1 = (route_t *)do_alloc_mem_inner(e, sizeof(route_t), 2);
2542  if ( !route_mem_1 )
2543  return -1;
2544  i = 2;
2545  route_mem_1->cmd.code = addordel;
2546  if ( !strcmp("-net", opt_argv[i]) )
2547  {
2548  i += 1;
2549  route_mem_1->re.flags &= ~2;
2550  }
2551  else if ( !strcmp("-host", opt_argv[i]) )
2552  {
2553  i += 1;
2554  route_mem_1->re.flags |= 2;
2555  }
2556  if ( i >= opt_argc )
2557  return 0;
2558  if ( do_netcnfname2address_wrap(e, 0, &route_mem_1->re.dstaddr) )
2559  return -1;
2560  if ( do_netcnfname2address_wrap(e, 0, &route_mem_1->re.gateway) )
2561  return -1;
2562  if ( do_netcnfname2address_wrap(e, 0, &route_mem_1->re.genmask) )
2563  return -1;
2564  if ( (strcmp("default", opt_argv[i])
2565  && do_netcnfname2address_wrap(e, (const char *)opt_argv[i], &route_mem_1->re.dstaddr)) )
2566  return -1;
2567  i += 1;
2568  for ( ; i < opt_argc; i += 2 )
2569  {
2570  if ( !strcmp("gw", opt_argv[i]) )
2571  {
2572  if ( do_netcnfname2address_wrap(e, opt_argv[i + 1], &route_mem_1->re.gateway) )
2573  return -1;
2574  route_mem_1->re.flags |= 4;
2575  }
2576  else if ( !strcmp("netmask", opt_argv[i]) )
2577  {
2578  if ( do_netcnfname2address_wrap(e, opt_argv[i + 1], &route_mem_1->re.genmask) )
2579  return -1;
2580  }
2581  }
2582  route_mem_1->cmd.back = ifc->cmd_tail;
2583  if ( ifc->cmd_tail )
2584  ifc->cmd_tail->forw = &route_mem_1->cmd;
2585  else
2586  ifc->cmd_head = &route_mem_1->cmd;
2587  route_mem_1->cmd.forw = 0;
2588  ifc->cmd_tail = &route_mem_1->cmd;
2589  return 0;
2590 }
2591 
2592 static void do_init_ifc_inner(sceNetCnfInterface_t *ifc)
2593 {
2594  const struct netcnf_option *curentry1;
2595 
2596  for ( curentry1 = g_options_attach_cnf; curentry1->m_key; curentry1 += 1 )
2597  {
2598  switch ( curentry1->m_type )
2599  {
2600  case '1':
2601  case 'b':
2602  case 'c':
2603  *((char *)ifc + curentry1->m_offset) = 0xFF;
2604  break;
2605  case '4':
2606  case 'D':
2607  case 'L':
2608  case 'P':
2609  case 'T':
2610  *(u32 *)((char *)ifc + curentry1->m_offset) = 0xFFFFFFFF;
2611  break;
2612  default:
2613  break;
2614  }
2615  }
2616 }
2617 
2618 static int do_check_args(sceNetCnfEnv_t *e, struct sceNetCnfUnknownList *unknown_list)
2619 {
2620  unsigned int lenx1;
2621  int i;
2622  struct sceNetCnfUnknown *listtmp;
2623  struct sceNetCnfUnknown *cpydst_1;
2624 
2625  lenx1 = 0;
2626  for ( i = 0; i < e->ac; i += 1 )
2627  {
2628  lenx1 += 3 + strlen(e->av[i]);
2629  }
2630  listtmp = (sceNetCnfUnknown_t *)do_alloc_mem_inner(e, sizeof(sceNetCnfUnknown_t) + lenx1, 2);
2631  if ( !listtmp )
2632  return -1;
2633  cpydst_1 = listtmp + 1;
2634  for ( i = 0; i < e->ac; i += 1 )
2635  {
2636  unsigned int cpysz;
2637 
2638  cpysz = (unsigned int)strlen(e->av[i]);
2639  memcpy(cpydst_1, e->av[i], cpysz);
2640  ((char *)cpydst_1)[cpysz] = 32 * (i < e->ac - 1);
2641  cpydst_1 = (struct sceNetCnfUnknown *)&((char *)cpydst_1)[cpysz + 1];
2642  }
2643  listtmp->back = unknown_list->tail;
2644  if ( unknown_list->tail )
2645  unknown_list->tail->forw = listtmp;
2646  else
2647  unknown_list->head = listtmp;
2648  listtmp->forw = 0;
2649  unknown_list->tail = listtmp;
2650  return 0;
2651 }
2652 
2653 static int do_check_other_keywords(
2654  sceNetCnfEnv_t *e, const struct netcnf_option *options, void *cnfdata, struct sceNetCnfUnknownList *unknown_list)
2655 {
2656  int wasprefixed;
2657  unsigned int numval;
2658 
2659  wasprefixed = (e->av[0][0] == '-') ? 1 : 0;
2660  if ( e->av[0][wasprefixed] )
2661  {
2662  for ( ; options->m_key && strcmp(&(e->av[0])[wasprefixed], options->m_key); options += 1 )
2663  ;
2664  if ( !options->m_key )
2665  return do_check_args(e, unknown_list);
2666  switch ( options->m_type )
2667  {
2668  case '1':
2669  numval = 0xFF;
2670  if ( !wasprefixed && (e->ac < 2 || do_parse_number(e, e->av[1], &numval)) )
2671  break;
2672  *((u8 *)cnfdata + options->m_offset) = (u8)numval;
2673  return 0;
2674  case '4':
2675  numval = 0xFFFFFFFF;
2676  if ( !wasprefixed && (e->ac < 2 || do_parse_number(e, e->av[1], &numval)) )
2677  break;
2678  *(u32 *)((char *)cnfdata + options->m_offset) = numval;
2679  return 0;
2680  case 'A':
2681  if ( !wasprefixed )
2682  {
2683  if ( e->ac < 2 )
2684  break;
2685  if ( !strcmp("any", (const char *)e->av[1]) )
2686  {
2687  numval = 0;
2688  }
2689  else if ( !strcmp("pap", (const char *)e->av[1]) )
2690  {
2691  numval = 1;
2692  }
2693  else if ( !strcmp("chap", (const char *)e->av[1]) )
2694  {
2695  numval = 2;
2696  }
2697  else if ( !strcmp("pap/chap", (const char *)e->av[1]) )
2698  {
2699  numval = 3;
2700  }
2701  else if ( !strcmp("chap/pap", (const char *)e->av[1]) )
2702  {
2703  numval = 4;
2704  }
2705  else if ( do_parse_number(e, e->av[1], &numval) )
2706  {
2707  return -1;
2708  }
2709  *((u8 *)cnfdata + options->m_offset) = (u8)numval;
2710  }
2711  if ( !strcmp("want.auth", (const char *)e->av[0]) )
2712  *((u8 *)cnfdata + 171) = !wasprefixed;
2713  else
2714  *((u8 *)cnfdata + 247) = !wasprefixed;
2715  return 0;
2716  case 'C':
2717  if ( !wasprefixed )
2718  {
2719  if ( e->ac < 2 || do_parse_number(e, e->av[1], &numval) )
2720  break;
2721  *(u32 *)((char *)cnfdata + options->m_offset) = numval;
2722  }
2723  if ( !strcmp("want.accm", (const char *)e->av[0]) )
2724  *((u8 *)cnfdata + 170) = !wasprefixed;
2725  else
2726  *((u8 *)cnfdata + 246) = !wasprefixed;
2727  return 0;
2728  case 'D':
2729  numval = 0xFFFFFFFF;
2730  if ( !wasprefixed )
2731  {
2732  if ( e->ac < 2 )
2733  break;
2734  if ( !strcmp("tone", (const char *)e->av[1]) )
2735  {
2736  numval = 0;
2737  }
2738  else if ( !strcmp("pulse", (const char *)e->av[1]) )
2739  {
2740  numval = 1;
2741  }
2742  else if ( !strcmp("any", (const char *)e->av[1]) )
2743  {
2744  numval = 2;
2745  }
2746  else if ( do_parse_number(e, e->av[1], &numval) )
2747  {
2748  return -1;
2749  }
2750  }
2751  *(u32 *)((char *)cnfdata + options->m_offset) = numval;
2752  return 0;
2753  case 'L':
2754  numval = 0xFFFFFFFF;
2755  if ( !wasprefixed && do_parse_phone_argument(e, e->ac - 1, (const char **)&e->av[1], &numval) )
2756  return -1;
2757  *(u32 *)((char *)cnfdata + options->m_offset) = numval;
2758  return 0;
2759  case 'M':
2760  if ( !wasprefixed )
2761  {
2762  if ( e->ac < 2 || do_parse_number(e, e->av[1], &numval) )
2763  break;
2764  *(u16 *)((char *)cnfdata + options->m_offset) = (u16)numval;
2765  }
2766  if ( !strcmp("want.mru", (const char *)e->av[0]) )
2767  *((u8 *)cnfdata + 169) = !wasprefixed;
2768  else
2769  *((u8 *)cnfdata + 245) = !wasprefixed;
2770  return 0;
2771  case 'P':
2772  numval = 0xFFFFFFFF;
2773  if ( !wasprefixed )
2774  {
2775  if ( e->ac < 2 )
2776  break;
2777  if ( !strcmp("auto", (const char *)e->av[1]) )
2778  {
2779  numval = 1;
2780  }
2781  else if ( !strcmp("10", (const char *)e->av[1]) )
2782  {
2783  numval = 2;
2784  }
2785  else if ( !strcmp("10_fd", (const char *)e->av[1]) )
2786  {
2787  numval = 3;
2788  }
2789  else if ( !strcmp("10_fd_pause", (const char *)e->av[1]) )
2790  {
2791  numval = 4;
2792  }
2793  else if ( !strcmp("tx", (const char *)e->av[1]) )
2794  {
2795  numval = 5;
2796  }
2797  else if ( !strcmp("tx_fd", (const char *)e->av[1]) )
2798  {
2799  numval = 6;
2800  }
2801  else if ( !strcmp("tx_fd_pause", (const char *)e->av[1]) )
2802  {
2803  numval = 7;
2804  }
2805  else if ( do_parse_number(e, e->av[1], &numval) )
2806  {
2807  return -1;
2808  }
2809  }
2810  *(u32 *)((char *)cnfdata + options->m_offset) = numval;
2811  return 0;
2812  case 'T':
2813  numval = 0xFFFFFFFF;
2814  if ( !wasprefixed )
2815  {
2816  if ( e->ac < 2 )
2817  break;
2818  if ( !strcmp("any", (const char *)e->av[1]) )
2819  {
2820  numval = 0;
2821  }
2822  if ( !strcmp("eth", (const char *)e->av[1]) )
2823  {
2824  numval = 1;
2825  }
2826  else if ( !strcmp("ppp", (const char *)e->av[1]) )
2827  {
2828  numval = 2;
2829  }
2830  else if ( !strcmp("nic", (const char *)e->av[1]) )
2831  {
2832  numval = 3;
2833  }
2834  else if ( do_parse_number(e, e->av[1], &numval) )
2835  {
2836  return -1;
2837  }
2838  }
2839  *(u32 *)((char *)cnfdata + options->m_offset) = numval;
2840  return 0;
2841  case 'b':
2842  numval = !wasprefixed;
2843  *((u8 *)cnfdata + options->m_offset) = (u8)numval;
2844  return 0;
2845  case 'c':
2846  numval = 255;
2847  if ( !wasprefixed )
2848  {
2849  if ( e->ac < 2 )
2850  break;
2851  if ( !strcmp("no", (const char *)e->av[1]) )
2852  {
2853  numval = 0;
2854  }
2855  else if ( !strcmp("md5", (const char *)e->av[1]) )
2856  {
2857  numval = 5;
2858  }
2859  else if ( !strcmp("ms", (const char *)e->av[1]) )
2860  {
2861  numval = 128;
2862  }
2863  else if ( !strcmp("ms-v1", (const char *)e->av[1]) )
2864  {
2865  numval = 128;
2866  }
2867  else if ( !strcmp("ms-v2", (const char *)e->av[1]) )
2868  {
2869  numval = 129;
2870  }
2871  else if ( do_parse_number(e, e->av[1], &numval) )
2872  {
2873  return -1;
2874  }
2875  }
2876  *((u8 *)cnfdata + options->m_offset) = (u8)numval;
2877  return 0;
2878  case 'p':
2879  if ( !wasprefixed )
2880  {
2881  if ( e->ac < 2 )
2882  {
2883  break;
2884  }
2885  *(char **)((char *)cnfdata + options->m_offset) = do_check_e_arg(e, e->av[1]);
2886  return (!*(char **)((char *)cnfdata + options->m_offset)) ? -1 : 0;
2887  }
2888  *(u32 *)((char *)cnfdata + options->m_offset) = 0;
2889  return 0;
2890  default:
2891  return printf("netcnf: internal load err (%d, type=%c)\n", 606, options->m_type);
2892  }
2893  }
2894  printf("netcnf: \"%s\" line %d: ", e->fname, e->lno);
2895  printf("ac=%d", e->ac);
2896  printf("\n");
2897  e->syntax_err += 1;
2898  return -1;
2899 }
2900 
2901 static int do_handle_net_cnf(sceNetCnfEnv_t *e, void *userdata)
2902 {
2903  int wasprefixed;
2904 
2905  (void)userdata;
2906  wasprefixed = (e->av[0][0] == '-') ? 1 : 0;
2907  if ( strcmp("interface", &(e->av[0])[wasprefixed]) )
2908  {
2909  if ( strcmp("zero_prefix", &(e->av[0])[wasprefixed]) )
2910  return do_check_other_keywords(e, g_options_net_cnf, e->root, &e->root->unknown_list);
2911  printf("netcnf: \"%s\" line %d: ", e->fname, e->lno);
2912  printf("obsoleted keyword (%s)", &(e->av[0])[wasprefixed]);
2913  printf("\n");
2914  e->syntax_err += 1;
2915  return 0;
2916  }
2917  if ( wasprefixed )
2918  return 0;
2919  if ( e->ac < 3 )
2920  {
2921  printf("netcnf: \"%s\" line %d: ", e->fname, e->lno);
2922  printf("ac=%d", e->ac);
2923  printf("\n");
2924  e->syntax_err += 1;
2925  return -1;
2926  }
2927  return !do_check_interface_keyword(e, e->av[1], e->av[2], (e->ac >= 4) ? e->av[3] : 0) ? 0 : -1;
2928 }
2929 
2930 static int do_handle_attach_cnf(sceNetCnfEnv_t *e, void *userdata)
2931 {
2932  int wasprefixed;
2933  struct sceNetCnfInterface *ifc;
2934 
2935  ifc = (struct sceNetCnfInterface *)userdata;
2936  wasprefixed = (e->av[0][0] == '-') ? 1 : 0;
2937  if ( !strncmp("phone_number", &(e->av[0])[wasprefixed], 12) )
2938  {
2939  int keyasnum;
2940 
2941  keyasnum = 0;
2942  if ( e->av[0][wasprefixed + 12] )
2943  {
2944  if ( !isdigit(e->av[0][wasprefixed + 12]) || e->av[0][wasprefixed + 13] )
2945  return 0;
2946  keyasnum = e->av[0][wasprefixed + 12] - 48;
2947  }
2948  if ( wasprefixed )
2949  {
2950  ifc->phone_numbers[keyasnum] = 0;
2951  return 0;
2952  }
2953  if ( e->ac >= 2 )
2954  {
2955  ifc->phone_numbers[keyasnum] = (u8 *)do_check_e_arg(e, e->av[1]);
2956  return (ifc->phone_numbers[keyasnum]) ? 0 : -1;
2957  }
2958  }
2959  else if ( !strcmp("nameserver", &(e->av[0])[wasprefixed]) )
2960  {
2961  if ( !wasprefixed )
2962  return do_check_nameserver(e, ifc, e->ac, &e->av[0]);
2963  }
2964  else if ( !strcmp("route", &(e->av[0])[wasprefixed]) )
2965  {
2966  if ( !wasprefixed )
2967  return do_check_route(e, ifc, e->ac, &e->av[0]);
2968  }
2969  else if ( !strcmp("zero_prefix", &(e->av[0])[wasprefixed]) || !strcmp("dial_cnf", &(e->av[0])[wasprefixed]) )
2970  {
2971  printf("netcnf: \"%s\" line %d: ", e->fname, e->lno);
2972  printf("obsoleted keyword (%s)", &(e->av[0])[wasprefixed]);
2973  printf("\n");
2974  e->syntax_err += 1;
2975  }
2976  else
2977  {
2978  return do_check_other_keywords(e, g_options_attach_cnf, ifc, &ifc->unknown_list);
2979  }
2980  return 0;
2981 }
2982 
2983 static int do_handle_dial_cnf(sceNetCnfEnv_t *e, void *userdata)
2984 {
2985  int wasprefixed;
2986  struct sceNetCnfDial *dial;
2987 
2988  dial = (struct sceNetCnfDial *)userdata;
2989  wasprefixed = (e->av[0][0] == '-') ? 1 : 0;
2990  if ( strcmp("dialing_type_string", &(e->av[0])[wasprefixed]) )
2991  return do_check_other_keywords(e, g_options_dial_cnf, dial, &dial->unknown_list);
2992  if ( wasprefixed || e->ac < 2 )
2993  return 0;
2994  dial->tone_dial = (u8 *)do_check_e_arg(e, e->av[1]);
2995  if ( !dial->tone_dial )
2996  return -1;
2997  if ( e->ac < 3 )
2998  return 0;
2999  dial->pulse_dial = (u8 *)do_check_e_arg(e, e->av[2]);
3000  if ( !dial->pulse_dial )
3001  return -1;
3002  if ( e->ac < 4 )
3003  return 0;
3004  dial->any_dial = (u8 *)do_check_e_arg(e, e->av[3]);
3005  return dial->any_dial ? 0 : -1;
3006 }
3007 
3008 static int
3009 do_check_line_buffer(sceNetCnfEnv_t *e, u8 *lbuf, int (*readcb)(sceNetCnfEnv_t *e, void *userdata), void *userdata)
3010 {
3011  u8 *i;
3012  char *j;
3013 
3014  for ( i = lbuf; e->lbuf < i && i[-1] < 0x21u; i -= 1 )
3015  ;
3016  *i = 0;
3017  for ( j = (char *)e->lbuf; *j && isspace(*j); j += 1 )
3018  ;
3019  e->ac = 0;
3020  while ( *j && e->ac < '\n' && (u8)*j != '#' )
3021  {
3022  u32 condtmp1;
3023 
3024  e->av[e->ac] = j;
3025  condtmp1 = 0;
3026  if ( *j == '#' )
3027  {
3028  *j = 0;
3029  break;
3030  }
3031  if ( !isspace(*j) )
3032  {
3033  while ( *j )
3034  {
3035  if ( *j == '\\' )
3036  {
3037  if ( j[1] )
3038  j += 1;
3039  }
3040  else
3041  {
3042  condtmp1 = (*j == '"') ? (condtmp1 ? 0 : 1) : (condtmp1 ? 1 : 0);
3043  }
3044  j += 1;
3045  if ( !condtmp1 && (*j == '#' || isspace(*j)) )
3046  {
3047  break;
3048  }
3049  }
3050  }
3051  if ( *j == '#' )
3052  {
3053  *j = 0;
3054  break;
3055  }
3056  if ( *j )
3057  {
3058  *j = 0;
3059  j += 1;
3060  }
3061  for ( ; *j && isspace(*j); j += 1 )
3062  ;
3063  e->ac += 1;
3064  }
3065  *j = 0;
3066  return (e->ac <= 0) ? 0 : readcb(e, userdata);
3067 }
3068 
3069 static int do_read_netcnf(sceNetCnfEnv_t *e, const char *netcnf_path, char **netcnf_heap_ptr, int is_attach_cnf)
3070 {
3071  int result;
3072 
3073  result = (!is_attach_cnf || e->f_no_decode) ? do_read_netcnf_no_decode(netcnf_path, netcnf_heap_ptr) :
3074  do_read_netcnf_decode(netcnf_path, netcnf_heap_ptr);
3075  if ( result < 0 )
3076  e->file_err += 1;
3077  return result;
3078 }
3079 
3080 static const char *do_handle_netcnf_prerw(sceNetCnfEnv_t *e, const char *entry_buffer)
3081 {
3082  const char *result;
3083 
3084  result = do_handle_netcnf_dirname(e->dir_name, entry_buffer, (char *)e->lbuf);
3085  return (result == (const char *)e->lbuf) ? do_alloc_mem_for_write(e, result) : result;
3086 }
3087 
3088 static int do_netcnf_read_related(
3089  sceNetCnfEnv_t *e, const char *path, int (*readcb)(sceNetCnfEnv_t *e, void *userdata), void *userdata)
3090 {
3091  int cur_linelen;
3092  const char *fullpath;
3093  int read_res1;
3094  u8 *lbuf;
3095  char *ptr;
3096  int i;
3097 
3098  cur_linelen = 0;
3099  if ( e->f_verbose )
3100  printf("netcnf: dir=%s path=%s\n", e->dir_name ? e->dir_name : "NULL", path ? path : "NULL");
3101  fullpath = do_handle_netcnf_prerw(e, path);
3102  if ( !fullpath )
3103  return -1;
3104  if ( e->f_verbose )
3105  {
3106  printf("netcnf: reading \"%s\" as ", fullpath);
3107  if ( (char *)readcb == (char *)do_handle_net_cnf )
3108  {
3109  printf("NET_CNF");
3110  }
3111  else if ( (char *)readcb == (char *)do_handle_attach_cnf )
3112  {
3113  printf("ATTACH_CNF");
3114  }
3115  else if ( (char *)readcb == (char *)do_handle_dial_cnf )
3116  {
3117  printf("DIAL_CNF");
3118  }
3119  else
3120  {
3121  printf("???");
3122  }
3123  printf("\n");
3124  }
3125  e->fname = fullpath;
3126  read_res1 = do_read_netcnf(e, fullpath, &ptr, readcb == do_handle_attach_cnf);
3127  if ( read_res1 < 0 )
3128  {
3129  printf("netcnf: can't load %s (%d)\n", e->fname, read_res1);
3130  return -1;
3131  }
3132  e->lno = 0;
3133  if ( !e->f_no_check_magic && (read_res1 < 36 || strncmp(ptr, "# <Sony Computer Entertainment Inc.>", 36)) )
3134  {
3135  printf("netcnf: decoding error (magic=\"");
3136  for ( i = 0; i < read_res1 && i < 36; i += 1 )
3137  {
3138  printf("%c", ((u8)ptr[i] - (unsigned int)' ' < '_') ? ((u8)ptr[i]) : '?');
3139  }
3140  printf("\")\n");
3141  do_free_heapmem(ptr);
3142  return -15;
3143  }
3144  lbuf = e->lbuf;
3145  for ( i = 0; i < read_res1; i += 1 )
3146  {
3147  if ( ptr[i] == '\n' )
3148  {
3149  e->lno += 1;
3150  if ( e->lbuf < lbuf && lbuf[-1] == '\\' )
3151  {
3152  lbuf -= 1;
3153  }
3154  else
3155  {
3156  cur_linelen += do_check_line_buffer(e, lbuf, readcb, userdata);
3157  lbuf = e->lbuf;
3158  }
3159  }
3160  else
3161  {
3162  if ( lbuf < &e->lbuf[1023] && ptr[i] != '\r' )
3163  {
3164  *lbuf = (u8)ptr[i];
3165  lbuf += 1;
3166  }
3167  }
3168  }
3169  if ( e->lbuf < lbuf )
3170  cur_linelen += do_check_line_buffer(e, lbuf, readcb, userdata);
3171  do_free_heapmem(ptr);
3172  return cur_linelen;
3173 }
3174 
3175 static int do_netcnf_dial_related(sceNetCnfEnv_t *e)
3176 {
3177  e->root = (sceNetCnfRoot_t *)do_alloc_mem_inner(e, sizeof(sceNetCnfRoot_t), 2);
3178  if ( !e->root )
3179  return -2;
3180  e->root->version = 3;
3181  e->root->redial_count = -1;
3182  e->root->redial_interval = -1;
3183  e->root->dialing_type = -1;
3184  return do_netcnf_read_related(e, e->arg_fname, do_handle_net_cnf, 0);
3185 }
3186 
3187 static int do_netcnf_ifc_related(sceNetCnfEnv_t *e)
3188 {
3189  e->ifc = (sceNetCnfInterface_t *)do_alloc_mem_inner(e, sizeof(sceNetCnfInterface_t), 2);
3190  if ( !e->ifc )
3191  return -2;
3192  do_init_ifc_inner(e->ifc);
3193  return do_netcnf_read_related(e, e->arg_fname, do_handle_attach_cnf, e->ifc);
3194 }
3195 
3196 static void do_dialauth_related(sceNetCnfInterface_t *ncid, struct sceNetCnfInterface *ncis)
3197 {
3198  int i;
3199  u32 typadd1_1;
3200  u32 typadd1_3;
3201  u8 typadd1;
3202 
3203  if ( !ncis )
3204  {
3205  return;
3206  }
3207  for ( i = 0; g_options_attach_cnf[i].m_key; i += 1 )
3208  {
3209  switch ( g_options_attach_cnf[i].m_type )
3210  {
3211  case '1':
3212  case 'b':
3213  case 'c':
3214  typadd1 = *((u8 *)&ncis->type + g_options_attach_cnf[i].m_offset);
3215  if ( typadd1 != 0xFF )
3216  *((u8 *)&ncid->type + g_options_attach_cnf[i].m_offset) = typadd1;
3217  break;
3218  case '4':
3219  case 'D':
3220  case 'L':
3221  case 'P':
3222  case 'T':
3223  typadd1_1 = *(u32 *)((char *)&ncis->type + g_options_attach_cnf[i].m_offset);
3224  if ( typadd1_1 != 0xFFFFFFFF )
3225  *(u32 *)((char *)&ncid->type + g_options_attach_cnf[i].m_offset) = typadd1_1;
3226  break;
3227  case 'A':
3228  if ( !strcmp("want.auth", g_options_attach_cnf[i].m_key) )
3229  {
3230  if ( ncis->want.f_auth )
3231  {
3232  ncid->want.f_auth = 1;
3233  ncid->want.auth = ncis->want.auth;
3234  }
3235  }
3236  else if ( ncis->allow.f_auth )
3237  {
3238  ncid->allow.f_auth = 1;
3239  ncid->allow.auth = ncis->allow.auth;
3240  }
3241  break;
3242  case 'C':
3243  if ( !strcmp("want.accm", g_options_attach_cnf[i].m_key) )
3244  {
3245  if ( ncis->want.f_accm )
3246  {
3247  ncid->want.f_accm = 1;
3248  ncid->want.accm = ncis->want.accm;
3249  }
3250  }
3251  else if ( ncis->allow.f_accm )
3252  {
3253  ncid->allow.f_accm = 1;
3254  ncid->allow.accm = ncis->allow.accm;
3255  }
3256  break;
3257  case 'M':
3258  if ( !strcmp("want.mru", g_options_attach_cnf[i].m_key) )
3259  {
3260  if ( ncis->want.f_mru )
3261  {
3262  ncid->want.f_mru = 1;
3263  ncid->want.mru = ncis->want.mru;
3264  }
3265  }
3266  else if ( ncis->allow.f_mru )
3267  {
3268  ncid->allow.f_mru = 1;
3269  ncid->allow.mru = ncis->allow.mru;
3270  }
3271  break;
3272  case 'p':
3273  typadd1_3 = *(u32 *)((char *)&ncis->type + g_options_attach_cnf[i].m_offset);
3274  if ( typadd1_3 )
3275  *(u32 *)((char *)&ncid->type + g_options_attach_cnf[i].m_offset) = typadd1_3;
3276  break;
3277  default:
3278  break;
3279  }
3280  }
3281  for ( i = 0; i < 10; i += 1 )
3282  {
3283  if ( ncis->phone_numbers[i] )
3284  ncid->phone_numbers[i] = ncis->phone_numbers[i];
3285  }
3286 }
3287 
3288 static int do_merge_conf_inner(sceNetCnfEnv_t *e)
3289 {
3290  struct sceNetCnfPair *pair_head;
3291 
3292  if ( !e->root )
3293  {
3294  return -1;
3295  }
3296  for ( pair_head = e->root->pair_head; pair_head; pair_head = pair_head->forw )
3297  {
3298  int type;
3299 
3300  if ( !pair_head->ctl )
3301  {
3302  pair_head->ctl = (sceNetCnfCtl_t *)do_alloc_mem_inner(e, sizeof(sceNetCnfCtl_t), 2);
3303  if ( !pair_head->ctl )
3304  return -2;
3305  }
3306  if ( !pair_head->ctl->dial )
3307  {
3308  pair_head->ctl->dial = (sceNetCnfDial_t *)do_alloc_mem_inner(e, sizeof(sceNetCnfDial_t), 2);
3309  if ( !pair_head->ctl->dial )
3310  return -2;
3311  }
3312  if ( !pair_head->ctl->ifc )
3313  {
3314  pair_head->ctl->ifc = (sceNetCnfInterface_t *)do_alloc_mem_inner(e, sizeof(sceNetCnfInterface_t), 2);
3315  if ( !pair_head->ctl->ifc )
3316  return -2;
3317  }
3318  do_init_ifc_inner(pair_head->ctl->ifc);
3319  pair_head->ctl->ifc->chat_additional = e->root->chat_additional;
3320  pair_head->ctl->ifc->redial_count = e->root->redial_count;
3321  pair_head->ctl->ifc->redial_interval = e->root->redial_interval;
3322  pair_head->ctl->ifc->outside_number = e->root->outside_number;
3323  pair_head->ctl->ifc->outside_delay = e->root->outside_delay;
3324  pair_head->ctl->ifc->dialing_type = e->root->dialing_type;
3325  do_dialauth_related(pair_head->ctl->ifc, pair_head->ifc);
3326  type = pair_head->dev->type;
3327  pair_head->dev->type = -1;
3328  do_dialauth_related(pair_head->ctl->ifc, pair_head->dev);
3329  pair_head->dev->type = type;
3330  }
3331  return 0;
3332 }
3333 
3334 static int do_load_conf_inner(sceNetCnfEnv_t *e)
3335 {
3336  int retres1;
3337  struct sceNetCnfPair *pair_head;
3338 
3339  retres1 = 0;
3340  switch ( e->req )
3341  {
3342  case 1:
3343  {
3344  int ifcres1_1;
3345 
3346  ifcres1_1 = do_netcnf_dial_related(e);
3347  if ( ifcres1_1 )
3348  return ifcres1_1;
3349  if ( !e->root )
3350  return -14;
3351  pair_head = e->root->pair_head;
3352  if ( !pair_head )
3353  return -14;
3354  if ( index(e->arg_fname, ':') )
3355  e->dir_name = e->arg_fname;
3356  for ( ; pair_head; pair_head = pair_head->forw )
3357  {
3358  if ( pair_head->attach_ifc )
3359  {
3360  e->arg_fname = (char *)pair_head->attach_ifc;
3361  ifcres1_1 = do_netcnf_ifc_related(e);
3362  if ( ifcres1_1 )
3363  {
3364  printf("netcnf: load_attach ifc(%d)\n", ifcres1_1);
3365  pair_head->ifc = 0;
3366  if ( (unsigned int)(ifcres1_1 + 15) < 2 )
3367  {
3368  pair_head->dev = 0;
3369  break;
3370  }
3371  retres1 = -21;
3372  }
3373  else
3374  {
3375  pair_head->ifc = e->ifc;
3376  }
3377  }
3378  else
3379  {
3380  pair_head->ifc = 0;
3381  }
3382  if ( pair_head->attach_dev )
3383  {
3384  e->arg_fname = (char *)pair_head->attach_dev;
3385  ifcres1_1 = do_netcnf_ifc_related(e);
3386  if ( ifcres1_1 )
3387  {
3388  printf("netcnf: load_attach dev(%d)\n", ifcres1_1);
3389  pair_head->dev = 0;
3390  if ( (unsigned int)(ifcres1_1 + 15) < 2 )
3391  break;
3392  retres1 = -21;
3393  }
3394  else
3395  {
3396  pair_head->dev = e->ifc;
3397  }
3398  }
3399  else
3400  {
3401  pair_head->dev = 0;
3402  }
3403  }
3404  return (retres1 == -21) ? -21 : ifcres1_1;
3405  }
3406  case 2:
3407  return do_netcnf_ifc_related(e);
3408  default:
3409  return -1;
3410  }
3411 }
3412 
3413 static int do_load_dial_inner(sceNetCnfEnv_t *e, sceNetCnfPair_t *pair)
3414 {
3415  if ( !pair->ctl )
3416  return -1;
3417  pair->ctl->dial = (sceNetCnfDial_t *)do_alloc_mem_inner(e, sizeof(sceNetCnfDial_t), 2);
3418  return pair->ctl->dial ? do_netcnf_read_related(e, e->arg_fname, do_handle_dial_cnf, pair->ctl->dial) : -2;
3419 }
3420 
3421 static int do_netcnf_vsprintf_buffer(sceNetCnfEnv_t *e, const char *fmt, va_list va)
3422 {
3423  char *mem_ptr_03;
3424  void *mem_ptr_rval_04;
3425  int has_negative;
3426  char has_sero;
3427  int strlened;
3428  int fmt_flag_str;
3429  char *mem_ptr_01;
3430  char *strptr1;
3431  int strlenmax;
3432  int strpad1;
3433  int cur_va1;
3434  int strlencalc;
3435  char *mem_ptr_02;
3436  char *mem_ptr_04;
3437  char *mem_ptr_05;
3438  char *i;
3439  char *mem_ptr_0a;
3440  void *mem_ptr_rval_02;
3441  char i_curchr2;
3442  void *mem_ptr_rval_03;
3443  char *mem_ptr_07;
3444  char *mem_ptr_09;
3445  void *mem_ptr_rval_01;
3446  char *mem_ptr_08;
3447  char strptr_curchr1;
3448  char *mem_ptr_06;
3449 
3450  strptr1 = 0;
3451  strlenmax = 0;
3452  while ( *fmt )
3453  {
3454  if ( *fmt == '%' )
3455  {
3456  fmt += 1;
3457  has_negative = 0;
3458  if ( *fmt == '-' )
3459  {
3460  fmt += 1;
3461  has_negative = 1;
3462  }
3463  has_sero = ' ';
3464  if ( *fmt == '0' )
3465  {
3466  has_sero = '0';
3467  fmt += 1;
3468  }
3469  strlened = 0;
3470  for ( ; isdigit(*fmt); fmt += 1 )
3471  {
3472  strlened = 10 * strlened - '0' + *fmt;
3473  }
3474  if ( *fmt == 'l' )
3475  fmt += 1;
3476  fmt_flag_str = -1;
3477  strpad1 = 0;
3478  switch ( *fmt )
3479  {
3480  case 'c':
3481  mem_ptr_01 = (char *)e->mem_ptr;
3482  mem_ptr_rval_04 = mem_ptr_01 + 1;
3483  if ( mem_ptr_01 >= (char *)e->mem_last )
3484  return -2;
3485  *mem_ptr_01 = (char)va_arg(va, int);
3486  e->mem_ptr = mem_ptr_rval_04;
3487  fmt += 1;
3488  continue;
3489  case 'p':
3490  has_sero = '0';
3491  if ( strlened < 8 )
3492  strlened = 8;
3493  strpad1 = 16;
3494  break;
3495  case 'X':
3496  case 'x':
3497  strpad1 = 16;
3498  break;
3499  case 'd':
3500  case 'u':
3501  strpad1 = 10;
3502  break;
3503  case 'o':
3504  strpad1 = 8;
3505  break;
3506  case 'S':
3507  fmt_flag_str = 1;
3508  break;
3509  case 's':
3510  fmt_flag_str = 0;
3511  break;
3512  default:
3513  mem_ptr_03 = (char *)e->mem_ptr;
3514  mem_ptr_rval_04 = mem_ptr_03 + 1;
3515  if ( mem_ptr_03 >= (char *)e->mem_last )
3516  return -2;
3517  *mem_ptr_03 = *fmt;
3518  e->mem_ptr = mem_ptr_rval_04;
3519  fmt += 1;
3520  continue;
3521  }
3522  if ( fmt_flag_str != -1 )
3523  {
3524  strptr1 = va_arg(va, char *);
3525  strlenmax = 0;
3526  if ( !strptr1 )
3527  strpad1 = 0;
3528  }
3529  if ( strpad1 )
3530  {
3531  cur_va1 = va_arg(va, int);
3532  strptr1 = __builtin_alloca(strpad1 + 1);
3533  strptr1[strpad1] = 0;
3534  strptr1 += strpad1;
3535  strlenmax = 0;
3536  if ( *fmt == 'd' && cur_va1 < 0 )
3537  {
3538  cur_va1 = -cur_va1;
3539  strlenmax = 1;
3540  }
3541  while ( 1 )
3542  {
3543  strptr1 -= 1;
3544  *strptr1 = ((*fmt == 'X') ? "0123456789ABCDEF" : "0123456789abcdef")[cur_va1 % strpad1];
3545  cur_va1 /= strpad1;
3546  if ( !cur_va1 )
3547  break;
3548  }
3549  }
3550  if ( strptr1 )
3551  {
3552  strlencalc = strlenmax ? (strlened + 1) : strlened;
3553  strlencalc -= strlen(strptr1);
3554  if ( has_sero == '0' && strlenmax )
3555  {
3556  mem_ptr_02 = (char *)e->mem_ptr;
3557  if ( mem_ptr_02 >= (char *)e->mem_last )
3558  return -2;
3559  *mem_ptr_02 = '-';
3560  e->mem_ptr = mem_ptr_02 + 1;
3561  }
3562  if ( !has_negative )
3563  {
3564  for ( ; strlencalc > 0; strlencalc -= 1 )
3565  {
3566  mem_ptr_04 = (char *)e->mem_ptr;
3567  if ( mem_ptr_04 >= (char *)e->mem_last )
3568  return -2;
3569  *mem_ptr_04 = has_sero;
3570  e->mem_ptr = mem_ptr_04 + 1;
3571  }
3572  }
3573  if ( has_sero != '0' && strlenmax )
3574  {
3575  mem_ptr_05 = (char *)e->mem_ptr;
3576  if ( mem_ptr_05 >= (char *)e->mem_last )
3577  return -2;
3578  *mem_ptr_05 = '-';
3579  e->mem_ptr = mem_ptr_05 + 1;
3580  }
3581  if ( fmt_flag_str != 1 )
3582  {
3583  for ( ; *strptr1; strptr1 += 1 )
3584  {
3585  strptr_curchr1 = *strptr1;
3586  mem_ptr_06 = (char *)e->mem_ptr;
3587  if ( mem_ptr_06 >= (char *)e->mem_last )
3588  return -2;
3589  *mem_ptr_06 = strptr_curchr1;
3590  e->mem_ptr = mem_ptr_06 + 1;
3591  }
3592  }
3593  else
3594  {
3595  for ( i = strptr1; *i; i += 1 )
3596  {
3597  if (
3598  (((u8)*i - 0x81 >= 0x1F) && ((u8)*i - 0xE0 >= 0x1D)) || ((u8)((int)*i - 64) >= 0xBDu) || (u8)*i == 0x7F )
3599  {
3600  if ( (u8)*i == '"' || (u8)*i == '\\' )
3601  {
3602  mem_ptr_07 = (char *)e->mem_ptr;
3603  if ( mem_ptr_07 >= (char *)e->mem_last )
3604  return -2;
3605  *mem_ptr_07 = '\\';
3606  e->mem_ptr = mem_ptr_07 + 1;
3607  mem_ptr_rval_03 = mem_ptr_07 + 2;
3608  if ( mem_ptr_07 + 1 >= (char *)e->mem_last )
3609  return -2;
3610  mem_ptr_07[1] = *i;
3611  }
3612  else if ( (u8)*i - ' ' < '_' )
3613  {
3614  mem_ptr_08 = (char *)e->mem_ptr;
3615  mem_ptr_rval_03 = mem_ptr_08 + 1;
3616  if ( mem_ptr_08 >= (char *)e->mem_last )
3617  return -2;
3618  *mem_ptr_08 = *i;
3619  }
3620  else
3621  {
3622  mem_ptr_09 = (char *)e->mem_ptr;
3623  if ( mem_ptr_09 >= (char *)e->mem_last )
3624  return -2;
3625  *mem_ptr_09 = '\\';
3626  e->mem_ptr = mem_ptr_09 + 1;
3627  if ( mem_ptr_09 + 1 >= (char *)e->mem_last )
3628  return -2;
3629  mem_ptr_09[1] = 'x';
3630  e->mem_ptr = mem_ptr_09 + 2;
3631  mem_ptr_rval_01 = mem_ptr_09 + 3;
3632  if ( mem_ptr_09 + 2 >= (char *)e->mem_last )
3633  return -2;
3634  mem_ptr_09[2] = ("0123456789abcdef")[(u8)*i >> 4];
3635  e->mem_ptr = mem_ptr_rval_01;
3636  mem_ptr_rval_03 = mem_ptr_09 + 4;
3637  if ( (char *)mem_ptr_rval_01 >= (char *)e->mem_last )
3638  return -2;
3639  mem_ptr_09[3] = ("0123456789abcdef")[(u8)*i & 0xF];
3640  }
3641  }
3642  else
3643  {
3644  mem_ptr_0a = (char *)e->mem_ptr;
3645  mem_ptr_rval_02 = mem_ptr_0a + 1;
3646  if ( mem_ptr_0a >= (char *)e->mem_last )
3647  return -2;
3648  *mem_ptr_0a = *i;
3649  e->mem_ptr = mem_ptr_rval_02;
3650  i_curchr2 = *i;
3651  i += 1;
3652  if ( (char *)mem_ptr_rval_02 >= (char *)e->mem_last )
3653  return -2;
3654  mem_ptr_rval_03 = mem_ptr_0a + 2;
3655  mem_ptr_0a[1] = i_curchr2;
3656  }
3657  e->mem_ptr = mem_ptr_rval_03;
3658  }
3659  }
3660  for ( ; has_negative && strlencalc > 0; strlencalc -= 1 )
3661  {
3662  if ( (char *)e->mem_ptr >= (char *)e->mem_last )
3663  return -2;
3664  *((char *)e->mem_ptr) = ' ';
3665  e->mem_ptr = ((char *)e->mem_ptr) + 1;
3666  }
3667  }
3668  }
3669  else
3670  {
3671  mem_ptr_03 = (char *)e->mem_ptr;
3672  mem_ptr_rval_04 = mem_ptr_03 + 1;
3673  if ( mem_ptr_03 >= (char *)e->mem_last )
3674  return -2;
3675  *mem_ptr_03 = *fmt;
3676  e->mem_ptr = mem_ptr_rval_04;
3677  }
3678  fmt += 1;
3679  }
3680  return 0;
3681 }
3682 
3683 static int do_netcnf_sprintf_buffer(sceNetCnfEnv_t *e, const char *fmt, ...)
3684 {
3685  va_list va;
3686  int retval;
3687 
3688  va_start(va, fmt);
3689  retval = do_netcnf_vsprintf_buffer(e, fmt, va);
3690  va_end(va);
3691  return retval;
3692 }
3693 
3694 static int do_netcnf_other_write(sceNetCnfEnv_t *e, const struct netcnf_option *options, void *cnfdata)
3695 {
3696  char *offsptr1;
3697  unsigned int offsptr6;
3698  unsigned int offsptr4;
3699  int i;
3700 
3701  for ( ; options->m_key; options += 1 )
3702  {
3703  unsigned int offsptr3;
3704  int result;
3705  const char *lbuf;
3706 
3707  offsptr3 = 0;
3708  result = 0;
3709  lbuf = (const char *)e->lbuf;
3710  switch ( options->m_type )
3711  {
3712  case '1':
3713  if ( *((u8 *)cnfdata + options->m_offset) == 255 )
3714  {
3715  lbuf = 0;
3716  break;
3717  }
3718  result = do_netcnf_sprintf_buffer(e, "%s %d\n", options->m_key, *((u8 *)cnfdata + options->m_offset));
3719  lbuf = 0;
3720  break;
3721  case '4':
3722  offsptr1 = (char *)cnfdata + options->m_offset;
3723  if ( *(int *)offsptr1 < 0 )
3724  {
3725  lbuf = 0;
3726  break;
3727  }
3728  result = do_netcnf_sprintf_buffer(e, "%s %d\n", options->m_key, *(u32 *)offsptr1);
3729  lbuf = 0;
3730  break;
3731  case 'A':
3732  if ( !strcmp("want.auth", options->m_key) ? !*((u8 *)cnfdata + 171) : !*((u8 *)cnfdata + 247) )
3733  {
3734  lbuf = 0;
3735  break;
3736  }
3737  offsptr3 = (u32)(s32) * ((char *)cnfdata + options->m_offset);
3738  switch ( offsptr3 )
3739  {
3740  case 0:
3741  lbuf = "any";
3742  break;
3743  case 1:
3744  lbuf = "pap";
3745  break;
3746  case 2:
3747  lbuf = "chap";
3748  break;
3749  case 3:
3750  lbuf = "pap/chap";
3751  break;
3752  case 4:
3753  lbuf = "chap/pap";
3754  break;
3755  default:
3756  break;
3757  }
3758  break;
3759  case 'C':
3760  if ( !strcmp("want.accm", options->m_key) ? !*((u8 *)cnfdata + 170) : !*((u8 *)cnfdata + 246) )
3761  {
3762  lbuf = 0;
3763  break;
3764  }
3765  result =
3766  do_netcnf_sprintf_buffer(e, "%s 0x%08x\n", options->m_key, *(u32 *)((char *)cnfdata + options->m_offset));
3767  lbuf = 0;
3768  break;
3769  case 'D':
3770  offsptr3 = *(u32 *)((char *)cnfdata + options->m_offset);
3771  switch ( offsptr3 )
3772  {
3773  case 0xFFFFFFFF:
3774  lbuf = 0;
3775  break;
3776  case 0:
3777  lbuf = "tone";
3778  break;
3779  case 1:
3780  lbuf = "pulse";
3781  break;
3782  case 2:
3783  lbuf = "any";
3784  break;
3785  default:
3786  break;
3787  }
3788  break;
3789  case 'L':
3790  offsptr4 = *(u32 *)((char *)cnfdata + options->m_offset);
3791  if ( offsptr4 == 0xFFFFFFFF )
3792  {
3793  lbuf = 0;
3794  break;
3795  }
3796  result = do_netcnf_sprintf_buffer(e, "%s", options->m_key);
3797  if ( result < 0 )
3798  return result;
3799  for ( i = 0; i < 32; i += 1 )
3800  {
3801  lbuf = 0;
3802  switch ( ((u32)1 << i) & offsptr4 )
3803  {
3804  case 1u:
3805  lbuf = "phase";
3806  break;
3807  case 2u:
3808  lbuf = "cp";
3809  break;
3810  case 4u:
3811  lbuf = "auth";
3812  break;
3813  case 8u:
3814  lbuf = "chat";
3815  break;
3816  case 0x10u:
3817  lbuf = "private";
3818  break;
3819  case 0x20u:
3820  lbuf = "dll";
3821  break;
3822  case 0x40u:
3823  lbuf = "dump";
3824  break;
3825  case 0x10000:
3826  lbuf = "timer";
3827  break;
3828  case 0x20000:
3829  lbuf = "event";
3830  break;
3831  default:
3832  break;
3833  }
3834  if ( lbuf )
3835  {
3836  offsptr4 &= ~((u32)1 << i);
3837  result = do_netcnf_sprintf_buffer(e, " %s", lbuf);
3838  if ( result < 0 )
3839  return result;
3840  }
3841  }
3842  if ( offsptr4 )
3843  {
3844  result = do_netcnf_sprintf_buffer(e, " 0x%x", offsptr4);
3845  if ( result < 0 )
3846  return result;
3847  }
3848  result = do_netcnf_sprintf_buffer(e, "\n");
3849  lbuf = 0;
3850  break;
3851  case 'M':
3852  if ( !strcmp("want.mru", options->m_key) ? !*((u8 *)cnfdata + 169) : !*((u8 *)cnfdata + 245) )
3853  {
3854  lbuf = 0;
3855  break;
3856  }
3857  result = do_netcnf_sprintf_buffer(e, "%s %d\n", options->m_key, *(u16 *)((char *)cnfdata + options->m_offset));
3858  lbuf = 0;
3859  break;
3860  case 'P':
3861  offsptr3 = *(u32 *)((char *)cnfdata + options->m_offset);
3862  switch ( offsptr3 )
3863  {
3864  case 0xFFFFFFFF:
3865  lbuf = 0;
3866  break;
3867  case 1:
3868  lbuf = "auto";
3869  break;
3870  case 2:
3871  lbuf = "10";
3872  break;
3873  case 3:
3874  lbuf = "10_fd";
3875  break;
3876  case 4:
3877  lbuf = "10_fd_pause";
3878  break;
3879  case 5:
3880  lbuf = "tx";
3881  break;
3882  case 6:
3883  lbuf = "tx_fd";
3884  break;
3885  case 7:
3886  lbuf = "tx_fd_pause";
3887  break;
3888  default:
3889  break;
3890  }
3891  break;
3892  case 'T':
3893  offsptr3 = *(u32 *)((char *)cnfdata + options->m_offset);
3894  switch ( offsptr3 )
3895  {
3896  case 0xFFFFFFFF:
3897  lbuf = 0;
3898  break;
3899  case 0:
3900  lbuf = "any";
3901  break;
3902  case 1:
3903  lbuf = "eth";
3904  break;
3905  case 2:
3906  lbuf = "ppp";
3907  break;
3908  case 3:
3909  lbuf = "nic";
3910  break;
3911  default:
3912  break;
3913  }
3914  break;
3915  case 'b':
3916  if ( *((u8 *)cnfdata + options->m_offset) == 255 )
3917  {
3918  lbuf = 0;
3919  break;
3920  }
3921  result = do_netcnf_sprintf_buffer(e, "%s%s\n", *((u8 *)cnfdata + options->m_offset) ? "" : "-", options->m_key);
3922  lbuf = 0;
3923  break;
3924  case 'c':
3925  offsptr3 = (u32)(s32) * ((char *)cnfdata + options->m_offset);
3926  switch ( offsptr3 )
3927  {
3928  case 0xFFFFFFFF:
3929  lbuf = 0;
3930  break;
3931  case 0:
3932  lbuf = "no";
3933  break;
3934  case 5:
3935  lbuf = "md5";
3936  break;
3937  case 128:
3938  lbuf = "ms-v1";
3939  break;
3940  case 129:
3941  lbuf = "ms-v2";
3942  break;
3943  default:
3944  break;
3945  }
3946  break;
3947  case 'p':
3948  offsptr6 = *(u32 *)((char *)cnfdata + options->m_offset);
3949  if ( !offsptr6 )
3950  {
3951  lbuf = 0;
3952  break;
3953  }
3954  result = do_netcnf_sprintf_buffer(e, "%s \"%S\"\n", options->m_key, offsptr6);
3955  lbuf = 0;
3956  break;
3957  default:
3958  return printf("netcnf: internal save error (%d, type=%c)\n", 302, options->m_type);
3959  }
3960  if ( lbuf )
3961  {
3962  if ( (const char *)e->lbuf == (const char *)lbuf )
3963  {
3964  sprintf((char *)e->lbuf, "0x%x", offsptr3);
3965  }
3966  result = do_netcnf_sprintf_buffer(e, "%s %s\n", options->m_key, lbuf);
3967  }
3968  if ( result < 0 )
3969  return result;
3970  }
3971  return 0;
3972 }
3973 
3974 static int do_netcnf_net_write(sceNetCnfEnv_t *e, struct sceNetCnfInterface *ifc)
3975 {
3976  struct sceNetCnfCommand *cmd_head;
3977  int result;
3978 
3979  for ( cmd_head = ifc->cmd_head; cmd_head; cmd_head = cmd_head->forw )
3980  {
3981  int nameserverflag;
3982 
3983  nameserverflag = -1;
3984  switch ( cmd_head->code )
3985  {
3986  case 1:
3987  nameserverflag = 1;
3988  break;
3989  case 2:
3990  nameserverflag = 0;
3991  break;
3992  case 3:
3993  {
3994  result = do_netcnf_sprintf_buffer(e, "route add -%s", (((route_t *)cmd_head)->re.flags & 2) ? "host" : "net");
3995  if ( result < 0 )
3996  return result;
3997  if ( sceNetCnfAddress2String((char *)e->lbuf, sizeof(e->lbuf), &((route_t *)cmd_head)->re.dstaddr) )
3998  return -1;
3999  result = do_netcnf_sprintf_buffer(e, " %s", (const char *)e->lbuf);
4000  if ( result < 0 )
4001  return result;
4002  if ( (((route_t *)cmd_head)->re.flags & 4) )
4003  {
4004  if ( sceNetCnfAddress2String((char *)e->lbuf, sizeof(e->lbuf), &((route_t *)cmd_head)->re.gateway) )
4005  return -1;
4006  result = do_netcnf_sprintf_buffer(e, " gw %s", (const char *)e->lbuf);
4007  if ( result < 0 )
4008  return result;
4009  }
4010  if ( sceNetCnfAddress2String((char *)e->lbuf, sizeof(e->lbuf), &((route_t *)cmd_head)->re.genmask) )
4011  return -1;
4012  result = do_netcnf_sprintf_buffer(e, " netmask %s", (const char *)e->lbuf);
4013  if ( result < 0 )
4014  return result;
4015  result = do_netcnf_sprintf_buffer(e, "\n");
4016  if ( result < 0 )
4017  return result;
4018  break;
4019  }
4020  case 4:
4021  {
4022  if ( sceNetCnfAddress2String((char *)e->lbuf, sizeof(e->lbuf), &((route_t *)cmd_head)->re.dstaddr) )
4023  return -1;
4024  result = do_netcnf_sprintf_buffer(e, "route del %s\n", (const char *)e->lbuf);
4025  if ( result < 0 )
4026  return result;
4027  break;
4028  }
4029  default:
4030  return -1;
4031  }
4032  if ( nameserverflag != -1 )
4033  {
4034  if ( sceNetCnfAddress2String((char *)e->lbuf, sizeof(e->lbuf), &((nameserver_t *)cmd_head)->address) )
4035  return -1;
4036  result = do_netcnf_sprintf_buffer(e, "nameserver %s %s\n", nameserverflag ? "add" : "del", (const char *)e->lbuf);
4037  if ( result < 0 )
4038  return result;
4039  }
4040  }
4041  return 0;
4042 }
4043 
4044 static int do_netcnf_phone_write(sceNetCnfEnv_t *e, struct sceNetCnfInterface *ifc)
4045 {
4046  int i;
4047  int result;
4048 
4049  for ( i = 0; i < (int)(sizeof(ifc->phone_numbers) / sizeof(ifc->phone_numbers[0])); i += 1 )
4050  {
4051  if ( ifc->phone_numbers[i] )
4052  {
4053  result = do_netcnf_sprintf_buffer(e, "phone_number%d \"%S\"\n", i, ifc->phone_numbers[i]);
4054  if ( result < 0 )
4055  return result;
4056  }
4057  }
4058  return 0;
4059 }
4060 
4061 static int do_netcnf_unknown_write(sceNetCnfEnv_t *e, struct sceNetCnfUnknownList *unknown_list)
4062 {
4063  struct sceNetCnfUnknown *head;
4064 
4065  for ( head = unknown_list->head; head; head = head->forw )
4066  {
4067  int result;
4068 
4069  result = do_netcnf_sprintf_buffer(e, "%s\n", (const char *)&head[1]);
4070  if ( result < 0 )
4071  return result;
4072  }
4073  return 0;
4074 }
4075 
4076 static int do_write_netcnf(sceNetCnfEnv_t *e, const char *path, int is_attach_cnf)
4077 {
4078  int memsize;
4079  const char *fullpath;
4080 
4081  memsize = (int)((char *)e->mem_ptr - (char *)e->mem_base);
4082  if ( e->f_verbose )
4083  printf("netcnf: dir=%s path=%s\n", e->dir_name ? e->dir_name : "NULL", path ? path : "NULL");
4084  fullpath = do_handle_netcnf_prerw(e, path);
4085  if ( !fullpath )
4086  return -1;
4087  if ( e->f_verbose )
4088  {
4089  printf("netcnf: writing \"%s\" as ", fullpath);
4090  if ( is_attach_cnf )
4091  printf("ATTACH_CNF");
4092  else
4093  printf("NET_CNF");
4094  printf("\n");
4095  }
4096  if ( !is_attach_cnf || e->f_no_decode )
4097  {
4098  int fd;
4099  int writeres;
4100 
4101  fd = do_open_netcnf(fullpath, 1538, 511);
4102  if ( fd < 0 )
4103  {
4104  e->file_err += 1;
4105  return (fd == -EIO) ? -18 : -3;
4106  }
4107  writeres = do_write_netcnf_no_encode(fd, e->mem_base, memsize);
4108  if ( memsize != writeres )
4109  {
4110  e->file_err += 1;
4111  do_close_netcnf(fd);
4112  return (writeres == -EIO) ? -18 : -5;
4113  }
4114  do_close_netcnf(fd);
4115  }
4116  else
4117  {
4118  if ( do_write_netcnf_encode(fullpath, e->mem_base, memsize) < 0 )
4119  {
4120  e->file_err += 1;
4121  return -1;
4122  }
4123  }
4124  return 0;
4125 }
4126 
4127 static int do_export_netcnf_inner(sceNetCnfEnv_t *e, const char *arg_fname, struct sceNetCnfInterface *ifc)
4128 {
4129  void *memalign;
4130  int result;
4131  struct sceNetCnfPair *pair_head;
4132 
4133  memalign = (void *)(((uiptr)e->mem_base + 3) & (uiptr)~3);
4134  e->mem_base = memalign;
4135  e->mem_ptr = memalign;
4136  result = do_netcnf_sprintf_buffer(e, "%s\n\n", "# <Sony Computer Entertainment Inc.>");
4137  if ( result < 0 )
4138  return result;
4139  if ( ifc )
4140  {
4141  result = do_netcnf_other_write(e, g_options_attach_cnf, ifc);
4142  if ( result < 0 )
4143  return result;
4144  result = do_netcnf_phone_write(e, ifc);
4145  if ( result < 0 )
4146  return result;
4147  result = do_netcnf_net_write(e, ifc);
4148  if ( result < 0 )
4149  return result;
4150  result = do_netcnf_unknown_write(e, &ifc->unknown_list);
4151  if ( result < 0 )
4152  return result;
4153  return do_write_netcnf(e, arg_fname, 1);
4154  }
4155  for ( pair_head = e->root->pair_head; pair_head; pair_head = pair_head->forw )
4156  {
4157  result = do_netcnf_sprintf_buffer(
4158  e, "interface \"%S\" \"%S\" \"%S\"\n", pair_head->display_name, pair_head->attach_ifc, pair_head->attach_dev);
4159  if ( result < 0 )
4160  return result;
4161  }
4162  result = do_netcnf_other_write(e, g_options_net_cnf, e->root);
4163  if ( result < 0 )
4164  return result;
4165  result = do_netcnf_unknown_write(e, &e->root->unknown_list);
4166  if ( result < 0 )
4167  return result;
4168  return do_write_netcnf(e, arg_fname, 0);
4169 }
4170 
4171 static int do_export_netcnf(sceNetCnfEnv_t *e)
4172 {
4173  return ((e->req != 1 && e->req != 2) || do_export_netcnf_inner(e, e->arg_fname, (e->req == 1) ? 0 : e->ifc)) ? -1 : 0;
4174 }
4175 
4176 static char *do_address_to_string_inner_element(char *dst, int srcbyte)
4177 {
4178  char *tmpstk_ptr;
4179  char tmpstk[16];
4180 
4181  tmpstk_ptr = tmpstk;
4182  if ( srcbyte < 0 )
4183  {
4184  *dst = '-';
4185  dst += 1;
4186  srcbyte = -srcbyte;
4187  }
4188  for ( ; srcbyte > 0; srcbyte /= 10 )
4189  {
4190  *tmpstk_ptr = srcbyte % 10 + '0';
4191  tmpstk_ptr += 1;
4192  }
4193  for ( ; tmpstk < tmpstk_ptr; tmpstk_ptr -= 1 )
4194  {
4195  *dst = tmpstk_ptr[-1];
4196  dst += 1;
4197  }
4198  return dst;
4199 }
4200 
4201 static void do_address_to_string_inner(char *dst, unsigned int srcint)
4202 {
4203  char *elm1;
4204 
4205  elm1 = do_address_to_string_inner_element(dst, (srcint >> 24) & 0xFF);
4206  *elm1 = '.';
4207  elm1 = do_address_to_string_inner_element(elm1 + 1, (srcint >> 16) & 0xFF);
4208  *elm1 = '.';
4209  elm1 = do_address_to_string_inner_element(elm1 + 1, (srcint >> 8) & 0xFF);
4210  *elm1 = '.';
4211  elm1 = do_address_to_string_inner_element(elm1 + 1, srcint & 0xFF);
4212  *elm1 = 0;
4213 }
4214 
4215 static int do_name_2_address_inner(unsigned int *dst, const char *buf)
4216 {
4217  int prefixchkn;
4218  unsigned int i;
4219  int offsbase1;
4220  unsigned int tmpstk1[4];
4221 
4222  i = 0;
4223  for ( prefixchkn = 0; prefixchkn < (int)(sizeof(tmpstk1) / sizeof(tmpstk1[0])); prefixchkn += 1 )
4224  {
4225  unsigned int base;
4226 
4227  base = 10;
4228  if ( *buf == '0' )
4229  {
4230  base = 8;
4231  buf += 1;
4232  if ( *buf == 'x' || *buf == 'X' )
4233  {
4234  buf += 1;
4235  base = 16;
4236  }
4237  }
4238  for ( i = 0; isxdigit(*buf); i = i * base + (unsigned int)offsbase1 )
4239  {
4240  offsbase1 = *buf - '0';
4241  if ( !isdigit(*buf) )
4242  {
4243  offsbase1 = *buf - '7';
4244  if ( !isupper(*buf) )
4245  offsbase1 = *buf - 'W';
4246  }
4247  if ( offsbase1 >= (int)base )
4248  break;
4249  buf += 1;
4250  }
4251  if ( prefixchkn > 0 && (unsigned int)tmpstk1[prefixchkn - 1] >= 0x100 )
4252  return 0;
4253  tmpstk1[prefixchkn] = i;
4254  if ( *buf != '.' )
4255  break;
4256  buf += 1;
4257  }
4258  if ( *buf && *buf != ' ' )
4259  return 0;
4260  switch ( prefixchkn )
4261  {
4262  case 0:
4263  break;
4264  case 1:
4265  if ( (i >> 24) )
4266  return 0;
4267  i |= tmpstk1[0] << 24;
4268  break;
4269  case 2:
4270  if ( (i >> 16) )
4271  return 0;
4272  i |= (tmpstk1[0] << 24) | (tmpstk1[1] << 16);
4273  break;
4274  case 3:
4275  if ( (i >> 8) )
4276  return 0;
4277  i |= (tmpstk1[0] << 24) | (tmpstk1[1] << 16) | (tmpstk1[2] << 8);
4278  break;
4279  default:
4280  return 0;
4281  }
4282  *dst = i;
4283  return 1;
4284 }
4285 
4286 static int do_conv_a2s_inner(char *sp_, char *dp_, int len)
4287 {
4288  int len_minus_three;
4289  int curindx1;
4290  char *dp_ptroffs1;
4291  char *dp_ptroffs2;
4292  char *dp_ptroffs3;
4293 
4294  len_minus_three = len - 3;
4295  curindx1 = 0;
4296  if ( len_minus_three <= 0 )
4297  return -19;
4298  *dp_ = '"';
4299  dp_ptroffs1 = dp_ + 1;
4300  *dp_ptroffs1 = '"';
4301  dp_ptroffs1 += 1;
4302  *dp_ptroffs1 = ' ';
4303  dp_ptroffs2 = dp_ptroffs1 + 1;
4304  while ( 1 )
4305  {
4306  for ( ; *sp_ == ' ' || *sp_ == '\t'; sp_ += 1 )
4307  ;
4308  if ( !*sp_ )
4309  break;
4310  if ( (*sp_ != 'A' && *sp_ != 'a') || (sp_[1] != 'T' && sp_[1] != 't') )
4311  return 0;
4312  for ( ; *sp_ && *sp_ != ' ' && *sp_ != '\t'; sp_ += 1 )
4313  {
4314  len_minus_three -= 1;
4315  if ( len_minus_three <= 0 )
4316  return -19;
4317  if ( *sp_ == '-' || *sp_ == '\\' || *sp_ == '"' || *sp_ == '^' )
4318  {
4319  len_minus_three -= 1;
4320  if ( len_minus_three <= 0 )
4321  return -19;
4322  *dp_ptroffs2 = '\\';
4323  dp_ptroffs2 += 1;
4324  }
4325  *dp_ptroffs2 = *sp_;
4326  dp_ptroffs2 += 1;
4327  }
4328  len_minus_three -= 4;
4329  if ( len_minus_three <= 0 )
4330  return -19;
4331  *dp_ptroffs2 = ' ';
4332  dp_ptroffs3 = dp_ptroffs2 + 1;
4333  *dp_ptroffs3 = 'O';
4334  dp_ptroffs3 += 1;
4335  *dp_ptroffs3 = 'K';
4336  dp_ptroffs3 += 1;
4337  *dp_ptroffs3 = ' ';
4338  dp_ptroffs2 = dp_ptroffs3 + 1;
4339  curindx1 += 1;
4340  }
4341  if ( curindx1 <= 0 )
4342  return 0;
4343  if ( (len_minus_three - 2) <= 0 )
4344  return -19;
4345  strcpy(dp_ptroffs2, "\\c");
4346  return 1;
4347 }
4348 
4349 static int do_conv_s2a_inner(char *sp_, char *dp_, int len)
4350 {
4351  int curindx1;
4352  char *sp_minus_one1;
4353  char *sp_ptroffs1;
4354  char *sp_ptroffs2;
4355  char *sp_ptroffs3;
4356  char *sp_ptroffs4;
4357 
4358  curindx1 = 0;
4359  for ( ; *sp_ == ' ' || *sp_ == '\t'; sp_ += 1 )
4360  ;
4361  sp_minus_one1 = sp_;
4362  if ( *sp_minus_one1 != '"' || sp_minus_one1[1] != '"' || (sp_minus_one1[2] != ' ' && sp_minus_one1[2] != '\t') )
4363  return 0;
4364  sp_ptroffs1 = sp_minus_one1 + 3;
4365  while ( 1 )
4366  {
4367  for ( ; *sp_ptroffs1 == ' ' || *sp_ptroffs1 == '\t'; sp_ptroffs1 += 1 )
4368  ;
4369  sp_ptroffs2 = sp_ptroffs1;
4370  if ( !*sp_ptroffs2 || *sp_ptroffs2 == '\\' )
4371  {
4372  if ( *sp_ptroffs2 != '\\' || sp_ptroffs2[1] != 'c' )
4373  return 0;
4374  sp_ptroffs4 = sp_ptroffs2 + 2;
4375  for ( ; *sp_ptroffs4 == ' ' || *sp_ptroffs4 == '\t'; sp_ptroffs4 += 1 )
4376  ;
4377  if ( *sp_ptroffs4 )
4378  return -19;
4379  if ( curindx1 <= 0 )
4380  return 0;
4381  if ( (int)(len - 1) < 0 )
4382  return -19;
4383  *dp_ = 0;
4384  return 1;
4385  }
4386  if ( (*sp_ptroffs2 != 'A' && *sp_ptroffs2 != 'a') || (sp_ptroffs2[1] != 'T' && sp_ptroffs2[1] != 't') )
4387  return 0;
4388  if ( curindx1 > 0 )
4389  {
4390  len -= 1;
4391  if ( len <= 0 )
4392  return -19;
4393  *dp_ = ' ';
4394  dp_ += 1;
4395  }
4396  sp_ptroffs2 += 1;
4397  if ( (sp_ptroffs2[-1]) != ' ' )
4398  {
4399  sp_ptroffs2 -= 1;
4400  while ( *sp_ptroffs2 != '\t' )
4401  {
4402  len -= 1;
4403  if ( len <= 0 )
4404  return -19;
4405  if ( *sp_ptroffs2 == '\\' )
4406  {
4407  if ( sp_ptroffs2[1] != '-' && sp_ptroffs2[1] != '\\' && sp_ptroffs2[1] != '"' && sp_ptroffs2[1] != '^' )
4408  return 0;
4409  sp_ptroffs2 += 1;
4410  }
4411  *dp_ = *sp_ptroffs2;
4412  dp_ += 1;
4413  sp_ptroffs2 += 1;
4414  if ( !*sp_ptroffs2 || *sp_ptroffs2 == ' ' )
4415  break;
4416  }
4417  }
4418  for ( ; *sp_ptroffs2 == ' ' || *sp_ptroffs2 == '\t'; sp_ptroffs2 += 1 )
4419  ;
4420  sp_ptroffs3 = sp_ptroffs2;
4421  if ( *sp_ptroffs3 != 'O' || sp_ptroffs3[1] != 'K' || (sp_ptroffs3[2] != ' ' && sp_ptroffs3[2] != '\t') )
4422  return 0;
4423  sp_ptroffs1 = sp_ptroffs3 + 3;
4424  curindx1 += 1;
4425  }
4426 }
4427 
4428 static int do_check_aolnet(const char *auth_name)
4429 {
4430  int i;
4431  const char *periodpos;
4432 
4433  if ( strncmp(auth_name, "aolnet/", 7) )
4434  return 0;
4435  periodpos = auth_name;
4436  for ( i = 0; periodpos; i += 1 )
4437  {
4438  periodpos = strchr(periodpos, '.');
4439  if ( periodpos )
4440  periodpos += 1;
4441  }
4442  return (i != 5) ? 0 : -20;
4443 }
4444 
4445 static int do_check_authnet(char *argst, char *arged)
4446 {
4447  char *i;
4448  char *j;
4449 
4450  for ( i = arged; argst < i && i[-1] < '!'; i -= 1 )
4451  ;
4452  *i = 0;
4453  for ( j = argst; *j && isspace(*j); j += 1 )
4454  ;
4455  if ( !strncmp(j, "auth_name", 9) )
4456  {
4457  int result;
4458 
4459  for ( ; *j && !isspace(*j); j += 1 )
4460  ;
4461  for ( ; *j && isspace(*j); j += 1 )
4462  ;
4463  if ( *j == '"' )
4464  j += 1;
4465  result = do_check_aolnet(j);
4466  if ( result < 0 )
4467  return result;
4468  }
4469  return 0;
4470 }
4471 
4472 static int do_read_check_netcnf(const char *netcnf_path, int type, int no_check_magic, int no_decode)
4473 {
4474  int read_res2;
4475  char *heapmem;
4476  int errretres;
4477  char *curheapptr1;
4478  char *heapmem_2;
4479 
4480  switch ( type )
4481  {
4482  case 0:
4483  case 2:
4484  return 0;
4485  default:
4486  return -10;
4487  case 1:
4488  break;
4489  }
4490  read_res2 = no_decode ? do_read_netcnf_no_decode(netcnf_path, &g_read_check_netcnf_heapptr) :
4491  do_read_netcnf_decode(netcnf_path, &g_read_check_netcnf_heapptr);
4492  if ( read_res2 < 0 )
4493  return read_res2;
4494  heapmem = (char *)do_alloc_heapmem(1024);
4495  errretres = 0;
4496  if ( !heapmem )
4497  {
4498  do_free_heapmem(g_read_check_netcnf_heapptr);
4499  return -2;
4500  }
4501  curheapptr1 = g_read_check_netcnf_heapptr;
4502  heapmem_2 = heapmem;
4503  if (
4504  no_check_magic
4505  && (read_res2 < 36 || strncmp(g_read_check_netcnf_heapptr, "# <Sony Computer Entertainment Inc.>", 36)) )
4506  {
4507  int i;
4508 
4509  printf("netcnf: decoding error (magic=\"");
4510  for ( i = 0; i < read_res2 && i < 36; i += 1 )
4511  {
4512  printf("%c", (unsigned int)((u8)curheapptr1[i] - 32) >= 0x5F ? '?' : (char)(u8)curheapptr1[i]);
4513  }
4514  errretres = -15;
4515  printf("\")\n");
4516  }
4517  if ( !errretres && read_res2 > 0 )
4518  {
4519  read_res2 -= 1;
4520  for ( ; read_res2 > 0; read_res2 -= 1 )
4521  {
4522  if ( *curheapptr1 == '\n' )
4523  {
4524  if ( heapmem < heapmem_2 && heapmem_2[-1] == '\\' )
4525  {
4526  heapmem_2 -= 1;
4527  }
4528  else
4529  {
4530  *heapmem_2 = 0;
4531  errretres = do_check_authnet(heapmem, heapmem_2);
4532  heapmem_2 = heapmem;
4533  if ( errretres < 0 )
4534  break;
4535  }
4536  }
4537  else
4538  {
4539  if ( heapmem_2 < &heapmem[1023] && *curheapptr1 != '\r' )
4540  {
4541  *heapmem_2 = *curheapptr1;
4542  heapmem_2 += 1;
4543  }
4544  }
4545  curheapptr1 += 1;
4546  }
4547  }
4548  if ( !errretres && heapmem < heapmem_2 )
4549  errretres = do_check_authnet(heapmem, heapmem_2);
4550  do_free_heapmem(g_read_check_netcnf_heapptr);
4551  do_free_heapmem(heapmem);
4552  return errretres;
4553 }
4554 
4555 static int do_check_provider_inner(const sceNetCnfEnv_t *e, int type)
4556 {
4557  switch ( type )
4558  {
4559  case 0:
4560  case 2:
4561  return 0;
4562  case 1:
4563  {
4564  if ( !e || !e->ifc )
4565  return -14;
4566  if ( e->ifc->auth_name )
4567  {
4568  int result;
4569 
4570  result = do_check_aolnet((const char *)e->ifc->auth_name);
4571  if ( result < 0 )
4572  return result;
4573  }
4574  return 0;
4575  }
4576  default:
4577  return -10;
4578  }
4579 }
4580 
4581 static const char *do_handle_netcnf_dirname(const char *fpath, const char *entry_buffer, char *netcnf_file_path)
4582 {
4583  const char *entry_buffer_1;
4584  const char *fpath_1;
4585  const char *fpath_1_minus_1;
4586  const char *fpath_2;
4587  char *i;
4588  const char *entry_buffer_2;
4589 
4590  if ( !entry_buffer || !*entry_buffer )
4591  return 0;
4592  for ( entry_buffer_1 = entry_buffer; *entry_buffer_1; entry_buffer_1 += 1 )
4593  {
4594  if ( *entry_buffer_1 == ':' )
4595  return entry_buffer;
4596  }
4597  if ( !fpath || !*fpath )
4598  return entry_buffer;
4599  for ( fpath_1 = fpath; fpath_1[1]; fpath_1 += 1 )
4600  ;
4601  fpath_1_minus_1 = fpath_1 - 1;
4602  if ( fpath < fpath_1_minus_1 || *entry_buffer == '/' || *entry_buffer == '\\' )
4603  {
4604  for ( ; fpath < fpath_1_minus_1 && *fpath_1_minus_1 != ':'; fpath_1_minus_1 -= 1 )
4605  ;
4606  if ( fpath <= fpath_1_minus_1 && (*fpath_1_minus_1 == ':' || *fpath_1_minus_1 == '/' || *fpath_1_minus_1 == '\\') )
4607  {
4608  fpath_1_minus_1 += 1;
4609  }
4610  }
4611  else if ( fpath <= fpath_1_minus_1 && *fpath_1_minus_1 != ':' )
4612  {
4613  for ( ; fpath < fpath_1_minus_1 && *fpath_1_minus_1 != ':' && *fpath_1_minus_1 != '/' && *fpath_1_minus_1 != '\\';
4614  fpath_1_minus_1 -= 1 )
4615  ;
4616  if ( *fpath_1_minus_1 == ':' || *fpath_1_minus_1 == '/' || *fpath_1_minus_1 == '\\' )
4617  {
4618  fpath_1_minus_1 += 1;
4619  }
4620  }
4621  fpath_2 = fpath;
4622  for ( i = netcnf_file_path; fpath_2 < fpath_1_minus_1; i += 1 )
4623  {
4624  *i = *fpath_2;
4625  fpath_2 += 1;
4626  }
4627  for ( entry_buffer_2 = entry_buffer; *entry_buffer_2; entry_buffer_2 += 1 )
4628  {
4629  *i = *entry_buffer_2;
4630  i += 1;
4631  }
4632  *i = 0;
4633  return netcnf_file_path;
4634 }
4635 
4636 static int do_get_filesize_inner(int fd)
4637 {
4638  int lseek_end_res;
4639  int lseek_start_res;
4640 
4641  lseek_end_res = lseek(fd, 0, 2);
4642  if ( lseek_end_res < 0 )
4643  return (lseek_end_res != -EIO) ? -6 : -18;
4644  lseek_start_res = lseek(fd, 0, 0);
4645  return (lseek_start_res < 0) ? ((lseek_start_res != -EIO) ? -6 : -18) : lseek_end_res;
4646 }
4647 
4648 static int is_special_file_path(const char *netcnf_path)
4649 {
4650  switch ( g_callbacks.type )
4651  {
4652  case 1:
4653  return !strncmp(netcnf_path, "mc", 2) ? 1 : 0;
4654  case 2:
4655  return !strncmp(netcnf_path, "ext", 3) ? 1 : 0;
4656  default:
4657  return 1;
4658  }
4659 }
4660 
4661 static void do_init_callback_handles(void)
4662 {
4663  int i;
4664 
4665  for ( i = 0; i < (int)(sizeof(g_callback_handle_infos) / sizeof(g_callback_handle_infos[0])); i += 1 )
4666  {
4667  g_callback_handle_infos[i].m_fd = -1;
4668  g_callback_handle_infos[i].m_filesize = 0;
4669  g_callback_handle_infos[i].m_allocstate = 0;
4670  }
4671 }
4672 
4673 static int do_get_empty_callback_handle(int in_fd, int in_allocstate)
4674 {
4675  int i;
4676 
4677  for ( i = 0; i < (int)(sizeof(g_callback_handle_infos) / sizeof(g_callback_handle_infos[0])); i += 1 )
4678  {
4679  if ( g_callback_handle_infos[i].m_fd == -1 )
4680  {
4681  g_callback_handle_infos[i].m_fd = in_fd;
4682  g_callback_handle_infos[i].m_allocstate = in_allocstate;
4683  g_open_callback_handle_count += 1;
4684  return i;
4685  }
4686  }
4687  return -1;
4688 }
4689 
4690 static int do_filesize_callback_handles(int in_fd, int in_allocstate)
4691 {
4692  int i;
4693 
4694  for ( i = 0; i < (int)(sizeof(g_callback_handle_infos) / sizeof(g_callback_handle_infos[0])); i += 1 )
4695  {
4696  if (
4697  g_callback_handle_infos[i].m_fd == in_fd
4698  && (g_callback_handle_infos[i].m_allocstate == in_allocstate || !in_allocstate) )
4699  {
4700  return i;
4701  }
4702  }
4703  return -1;
4704 }
4705 
4706 static void do_clear_callback_handles(int fd, int allocmatch)
4707 {
4708  int i;
4709 
4710  for ( i = 0; i < (int)(sizeof(g_callback_handle_infos) / sizeof(g_callback_handle_infos[0])); i += 1 )
4711  {
4712  if ( g_callback_handle_infos[i].m_fd == fd && g_callback_handle_infos[i].m_allocstate == allocmatch )
4713  {
4714  g_callback_handle_infos[i].m_fd = -1;
4715  g_callback_handle_infos[i].m_allocstate = 0;
4716  g_open_callback_handle_count -= 1;
4717  break;
4718  }
4719  }
4720 }
4721 
4722 static const char *do_colon_callback_handles(const char *netcnf_path, char *device)
4723 {
4724  char *index_res;
4725  u32 devnameend;
4726 
4727  index_res = index(netcnf_path, ':');
4728  if ( !index_res )
4729  return 0;
4730  devnameend = (u32)(int)(index_res - netcnf_path) + 1;
4731  if ( devnameend >= 17 )
4732  return 0;
4733  memcpy(device, netcnf_path, (u32)devnameend);
4734  device[devnameend] = 0;
4735  return (strlen(index_res + 1) + 1 < 257) ? (index_res + 1) : 0;
4736 }
4737 
4738 static int do_open_netcnf(const char *netcnf_path, int file_flags, int file_mode)
4739 {
4740  const char *cbind;
4741  int openret1;
4742  int empty_callback_handle;
4743  char pathconcat[16];
4744  int filesz1;
4745 
4746  if ( !g_callbacks.open || !is_special_file_path(netcnf_path) )
4747  return open(netcnf_path, file_flags, file_mode);
4748  if ( g_open_callback_handle_count >= (int)(sizeof(g_callback_handle_infos) / sizeof(g_callback_handle_infos[0])) )
4749  return -EPERM;
4750  cbind = do_colon_callback_handles(netcnf_path, pathconcat);
4751  if ( !cbind )
4752  return -EPERM;
4753  openret1 = g_callbacks.open(pathconcat, cbind, file_flags, file_mode, &filesz1);
4754  if ( openret1 < 0 )
4755  return openret1;
4756  empty_callback_handle = do_get_empty_callback_handle(openret1, 1);
4757  strcpy(g_callback_handle_infos[empty_callback_handle].m_device, pathconcat);
4758  strcpy(g_callback_handle_infos[empty_callback_handle].m_pathname, cbind);
4759  g_callback_handle_infos[empty_callback_handle].m_buf = 0;
4760  g_callback_handle_infos[empty_callback_handle].m_bufpos = 0;
4761  g_callback_handle_infos[empty_callback_handle].m_filesize = filesz1;
4762  return openret1;
4763 }
4764 
4765 static int do_read_callback_handles(int handlefd, int fd, void *ptr, int size)
4766 {
4767  struct netcnf_callback_handle_info *cbh;
4768 
4769  cbh = &g_callback_handle_infos[handlefd];
4770  if ( !cbh->m_bufpos )
4771  {
4772  cbh->m_buf = do_alloc_heapmem(cbh->m_filesize);
4773  if ( !cbh->m_buf )
4774  return -EPERM;
4775  if ( g_callbacks.read(fd, cbh->m_device, cbh->m_pathname, cbh->m_buf, 0, cbh->m_filesize) != cbh->m_filesize )
4776  {
4777  do_free_heapmem(cbh->m_buf);
4778  cbh->m_buf = 0;
4779  return -EPERM;
4780  }
4781  }
4782  memcpy(ptr, (char *)cbh->m_buf + cbh->m_bufpos, (u32)size);
4783  cbh->m_bufpos += size;
4784  return size;
4785 }
4786 
4787 static int do_readfile_netcnf(int fd, void *ptr, int size)
4788 {
4789  int cbind;
4790 
4791  if ( !g_callbacks.read )
4792  return read(fd, ptr, size);
4793  cbind = do_filesize_callback_handles(fd, 1);
4794  return (cbind == -1) ? read(fd, ptr, size) : do_read_callback_handles(cbind, fd, ptr, size);
4795 }
4796 
4797 static int do_write_netcnf_no_encode(int fd, void *ptr, int size)
4798 {
4799  if ( !g_callbacks_set || g_callbacks.type == 2 )
4800  return write(fd, ptr, size);
4801  printf("[err] netcnf write()\n");
4802  return -EPERM;
4803 }
4804 
4805 static int do_dopen_wrap(const char *fn)
4806 {
4807  if ( !g_callbacks_set || g_callbacks.type == 2 )
4808  {
4809 #ifdef _IOP
4810  return dopen(fn);
4811 #else
4812  (void)fn;
4813  return -EPERM;
4814 #endif
4815  }
4816  printf("[err] netcnf dopen()\n");
4817  return -EPERM;
4818 }
4819 
4820 static int do_dread_wrap(int fn, iox_dirent_t *buf)
4821 {
4822  if ( !g_callbacks_set || g_callbacks.type == 2 )
4823  {
4824 #ifdef _IOP
4825  return dread(fn, buf);
4826 #else
4827  (void)fn;
4828  (void)buf;
4829  return -EPERM;
4830 #endif
4831  }
4832  printf("[err] netcnf dread()\n");
4833  return -EPERM;
4834 }
4835 
4836 static int do_remove_wrap(const char *fn)
4837 {
4838  if ( !g_callbacks_set || g_callbacks.type == 2 )
4839  return remove(fn);
4840  printf("[err] netcnf remove()\n");
4841  return -EPERM;
4842 }
4843 
4844 static void do_close_netcnf(int fd)
4845 {
4846  int cbind;
4847 
4848  if ( !g_callbacks.close )
4849  {
4850  close(fd);
4851  return;
4852  }
4853  cbind = do_filesize_callback_handles(fd, 1);
4854  if ( cbind == -1 )
4855  {
4856  close(fd);
4857  return;
4858  }
4859  g_callbacks.close(fd);
4860  do_free_heapmem(g_callback_handle_infos[cbind].m_buf);
4861  g_callback_handle_infos[cbind].m_buf = 0;
4862  do_clear_callback_handles(fd, 1);
4863 }
4864 
4865 static void do_dclose_wrap(int fd)
4866 {
4867  if ( !g_callbacks_set || g_callbacks.type == 2 )
4868  {
4869 #ifdef _IOP
4870  dclose(fd);
4871 #else
4872  (void)fd;
4873 #endif
4874  return;
4875  }
4876  printf("[err] netcnf dclose()\n");
4877 }
4878 
4879 static int do_filesize_netcnf(int fd)
4880 {
4881  int cbind;
4882 
4883  cbind = do_filesize_callback_handles(fd, 0);
4884  return (cbind == -1) ? do_get_filesize_inner(fd) : g_callback_handle_infos[cbind].m_filesize;
4885 }
4886 
4887 static void do_getstat_wrap(const char *fn, iox_stat_t *stx)
4888 {
4889  if ( !g_callbacks_set || g_callbacks.type == 2 )
4890  {
4891 #ifdef _IOP
4892  getstat(fn, stx);
4893 #else
4894  {
4895  struct stat st;
4896 
4897  stat(fn, &st);
4898  stx->size = (unsigned int)(int)st.st_size;
4899  }
4900 #endif
4901  return;
4902  }
4903  printf("[err] netcnf getstat()\n");
4904 }
4905 
4906 static void do_chstat_mode_copyprotect_wrap(const char *fn)
4907 {
4908 #ifdef _IOP
4909  iox_stat_t statmode;
4910 #endif
4911 
4912  if ( !g_callbacks_set || g_callbacks.type == 2 )
4913  {
4914 #ifdef _IOP
4915  do_getstat_wrap(fn, &statmode);
4916  statmode.mode |= 8u;
4917  chstat(fn, &statmode, 1u);
4918 #else
4919  (void)fn;
4920 #endif
4921  return;
4922  }
4923  printf("[err] netcnf chstat()\n");
4924 }
4925 
4926 static void do_set_callback_inner(sceNetCnfCallback_t *pcallback)
4927 {
4928  if ( pcallback )
4929  {
4930  g_callbacks.type = pcallback->type;
4931  g_callbacks.open = pcallback->open;
4932  g_callbacks.read = pcallback->read;
4933  g_callbacks.close = pcallback->close;
4934  g_callbacks_set = 1;
4935  }
4936  else
4937  {
4938  memset(&g_callbacks, 0, sizeof(g_callbacks));
4939  g_callbacks_set = 0;
4940  }
4941  do_init_callback_handles();
4942 }
4943 
4944 #ifdef _IOP
4945 static int do_init_heap(void)
4946 {
4947  if ( g_netcnf_heap )
4948  return -2;
4949  g_netcnf_heap = CreateHeap(1024, 1);
4950  return g_netcnf_heap ? 0 : -1;
4951 }
4952 #endif
4953 
4954 static void *do_alloc_heapmem(int nbytes)
4955 {
4956 #ifdef _IOP
4957  return AllocHeapMemory(g_netcnf_heap, nbytes);
4958 #else
4959  return malloc((size_t)nbytes);
4960 #endif
4961 }
4962 
4963 static void do_free_heapmem(void *ptr)
4964 {
4965 #ifdef _IOP
4966  if ( ptr )
4967  FreeHeapMemory(g_netcnf_heap, ptr);
4968 #else
4969  if ( ptr )
4970  free(ptr);
4971 #endif
4972 }
4973 
4974 #ifdef _IOP
4975 static void do_delete_heap(void)
4976 {
4977  DeleteHeap(g_netcnf_heap);
4978  g_netcnf_heap = 0;
4979 }
4980 #endif
sceNetCnfEnv
Definition: netcnf.h:187
sceNetCnfDial
Definition: netcnf.h:138
_ModuleInfo::newflags
u16 newflags
Definition: loadcore.h:36
iox_stat_t
Definition: iox_stat.h:92
sceNetCnfPair
Definition: netcnf.h:160
sceNetCnfCommand
Definition: netcnf.h:28
sceNetCnfUnknown
Definition: netcnf.h:35
sceNetCnfRoot
Definition: netcnf.h:173
iop_sema_t
Definition: thsemap.h:38
EPERM
#define EPERM
Definition: errno.h:21
sceNetCnfCallback
Definition: netcnf.h:51
EIO
#define EIO
Definition: errno.h:29
ctype.h
nameserver
Definition: netcnf.h:228
sceNetCnfCtl
Definition: netcnf.h:150
sceNetCnfInterface
Definition: netcnf.h:84
route
Definition: netcnf.h:222
irx_export_table
Definition: irx.h:90
stdio.h
netcnf_callback_handle_info
Definition: netcnf.c:65
iox_dirent_t
Definition: iox_stat.h:111
sceNetCnfAddress
Definition: netcnf.h:22
netcnf_option
Definition: netcnf.c:76
sceNetCnfList
Definition: netcnf.h:14
stdlib.h
_ModuleInfo
Definition: loadcore.h:31
errno.h
sceCdRI
int sceCdRI(u8 *buffer, u32 *result)
Definition: cdvdman.c:7268
sceNetCnfUnknownList
Definition: netcnf.h:41