protoutils.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <strings.h>
  5. #include <math.h>
  6. #include <inttypes.h>
  7. #include <ctype.h>
  8. #include "multiaddr/base58.h"
  9. #include "multiaddr/varhexutils.h"
  10. #include "multiaddr/protocols.h"
  11. #include "multiaddr/protoutils.h"
  12. extern char *strtok_r(char *, const char *, char **);
  13. //////////////////////////////////////////////////////////
  14. char ASCII2bits(char ch) {
  15. if (ch >= '0' && ch <= '9') {
  16. return (ch - '0');
  17. } else if (ch >= 'a' && ch <= 'z') {
  18. return (ch - 'a') + 10;
  19. } else if (ch >= 'A' && ch <= 'Z') {
  20. return (ch - 'A') + 10;
  21. }
  22. return 0; // fail
  23. }
  24. void hex2bin (char *dst, char *src, int len)
  25. {
  26. while (len--) {
  27. *dst = ASCII2bits(*src++) << 4; // higher bits
  28. *dst++ |= ASCII2bits(*src++); // lower bits
  29. }
  30. }
  31. char bits2ASCII(char b) {
  32. if (b >= 0 && b < 10) {
  33. return (b + '0');
  34. } else if (b >= 10 && b <= 15) {
  35. return (b - 10 + 'a');
  36. }
  37. return 0; // fail
  38. }
  39. void bin2hex (char *dst, char *src, int len)
  40. {
  41. while (len--) {
  42. *dst++ = bits2ASCII((*src >> 4) & 0xf); // higher bits
  43. *dst++ = bits2ASCII(*src++ & 0xf); // lower bits
  44. }
  45. *dst = '\0';
  46. }
  47. //////////////////////////////////////////////////////////
  48. //IPv4 VALIDATOR
  49. #define DELIM "."
  50. /* return 1 if string contain only digits, else return 0 */
  51. int valid_digit(char *ip_str)
  52. {
  53. int err = 0;
  54. while (*ip_str) {
  55. if (*ip_str >= '0' && *ip_str <= '9')
  56. ++ip_str;
  57. else
  58. return 0;
  59. }
  60. return 1;
  61. }
  62. /* return 1 if IP string is valid, else return 0 */
  63. int is_valid_ipv4(char *ip_str)
  64. {
  65. int i, num, dots = 0;
  66. char *ptr;
  67. int err=0;
  68. if (ip_str == NULL)
  69. err = 1;
  70. // See following link for strtok()
  71. // http://pubs.opengroup.org/onlinepubs/009695399/functions/strtok_r.html
  72. ptr = strtok(ip_str, DELIM);
  73. if (ptr == NULL)
  74. err = 1;
  75. while (ptr)
  76. {
  77. /* after parsing string, it must contain only digits */
  78. if (!valid_digit(ptr))
  79. err = 1;
  80. num = atoi(ptr);
  81. /* check for valid IP */
  82. if (num >= 0 && num <= 255) {
  83. /* parse remaining string */
  84. ptr = strtok(NULL, DELIM);
  85. if (ptr != NULL)
  86. ++dots;
  87. } else
  88. err = 1;
  89. }
  90. /* valid IP string must contain 3 dots */
  91. if (dots != 3)
  92. {
  93. err = 1;
  94. }
  95. if(err == 0)
  96. {
  97. return 1;
  98. }
  99. else
  100. {
  101. return 0;
  102. }
  103. }
  104. //////////////IPv6 Validator
  105. #define MAX_HEX_NUMBER_COUNT 8
  106. int ishexdigit(char ch)
  107. {
  108. if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='f')||(ch>='A'&&ch<='F'))
  109. return(1);
  110. return(0);
  111. }
  112. int is_valid_ipv6(char *str)
  113. {
  114. int hdcount=0;
  115. int hncount=0;
  116. int err=0;
  117. int packed=0;
  118. if(*str==':')
  119. {
  120. str++;
  121. if(*str!=':')
  122. return(0);
  123. else
  124. {
  125. packed=1;
  126. hncount=1;
  127. str++;
  128. if(*str==0)
  129. return(1);
  130. }
  131. }
  132. if(ishexdigit(*str)==0)
  133. {
  134. return(0);
  135. }
  136. hdcount=1;
  137. hncount=1;
  138. str++;
  139. while(err==0&&*str!=0)
  140. {
  141. if(*str==':')
  142. {
  143. str++;
  144. if(*str==':')
  145. {
  146. if(packed==1)
  147. err=1;
  148. else
  149. {
  150. str++;
  151. if(ishexdigit(*str) || (*str==0 && hncount < MAX_HEX_NUMBER_COUNT ))
  152. {
  153. packed=1;
  154. hncount++;
  155. if(ishexdigit(*str))
  156. {
  157. if(hncount==MAX_HEX_NUMBER_COUNT)
  158. {
  159. err=1;
  160. } else
  161. {
  162. hdcount=1;
  163. hncount++;
  164. str++;
  165. }
  166. }
  167. } else
  168. {
  169. err=1;
  170. }
  171. }
  172. }
  173. else
  174. {
  175. if(!ishexdigit(*str))
  176. {
  177. err=1;
  178. } else
  179. {
  180. if(hncount==MAX_HEX_NUMBER_COUNT)
  181. {
  182. err=1;
  183. } else
  184. {
  185. hdcount=1;
  186. hncount++;
  187. str++;
  188. }
  189. }
  190. }
  191. }
  192. else
  193. {
  194. if(ishexdigit(*str))
  195. {
  196. if(hdcount==4)
  197. err=1;
  198. else
  199. {
  200. hdcount++;
  201. str++;
  202. }
  203. } else
  204. err=1;
  205. }
  206. }
  207. if(hncount<MAX_HEX_NUMBER_COUNT&&packed==0)
  208. err=1;
  209. return(err==0);
  210. }
  211. uint64_t ip2int(const char * ipconvertint)
  212. {
  213. uint64_t final_result =0;
  214. char * iproc;
  215. int ipat1=0;
  216. int ipat2=0;
  217. int ipat3=0;
  218. int ipat4=0;
  219. char ip[16];
  220. strcpy(ip, ipconvertint);
  221. iproc = strtok (ip,".");
  222. for(int i=0; i<4;i++)
  223. {
  224. switch(i)
  225. {
  226. case 0:
  227. {
  228. ipat1 = atoi(iproc);
  229. break;
  230. }
  231. case 1:
  232. {
  233. ipat2 = atoi(iproc);
  234. break;
  235. }
  236. case 2:
  237. {
  238. ipat3 = atoi(iproc);
  239. break;
  240. }
  241. case 3:
  242. {
  243. ipat4 = atoi(iproc);
  244. break;
  245. }
  246. default:
  247. {
  248. printf("Somebody misplaced an int\n");
  249. break;
  250. }
  251. }
  252. iproc = strtok (NULL,".");
  253. }
  254. final_result = ((ipat1*pow(2,24))+(ipat2*pow(2,16))+(ipat3*pow(2,8))+ipat4*1);
  255. return final_result;
  256. }
  257. char * int2ip(int inputintip)
  258. {
  259. uint32_t ipint = inputintip;
  260. static char xxx_int2ip_result[16] = "\0";
  261. bzero(xxx_int2ip_result,16);
  262. uint32_t ipint0 = (ipint >> 8*3) % 256;
  263. uint32_t ipint1 = (ipint >> 8*2) % 256;
  264. uint32_t ipint2 = (ipint >> 8*1) % 256;
  265. uint32_t ipint3 = (ipint >> 8*0) % 256;
  266. sprintf(xxx_int2ip_result, "%d.%d.%d.%d", ipint0,ipint1,ipint2,ipint3);
  267. return xxx_int2ip_result;
  268. }
  269. /**
  270. * Unserialize the bytes into a string
  271. * @param results where to put the resultant string
  272. * @param in_bytes the bytes to unserialize
  273. * @param in_bytes_size the length of the bytes array
  274. * @returns 0 on error, otherwise 1
  275. */
  276. int bytes_to_string(char** buffer, const uint8_t* in_bytes, int in_bytes_size)
  277. {
  278. uint8_t * bytes = NULL;
  279. char *results = NULL;
  280. int size = in_bytes_size;
  281. struct ProtocolListItem* head = NULL;
  282. char hex[(in_bytes_size*2)+1];
  283. //Positioning for memory jump:
  284. int lastpos = 0;
  285. char pid[3];
  286. // set up variables
  287. load_protocols(&head);
  288. memset(hex, 0, (in_bytes_size * 2) + 1);
  289. char* tmp = (char*)Var_To_Hex((char*)in_bytes, size);
  290. memcpy(hex, tmp, in_bytes_size * 2);
  291. free(tmp);
  292. pid[2] = 0;
  293. // allocate memory for results
  294. *buffer = malloc(800);
  295. results = *buffer;
  296. memset(results, 0, 800);
  297. //Process Hex String
  298. NAX:
  299. //Stage 1 ID:
  300. pid[0] = hex[lastpos];
  301. pid[1] = hex[lastpos+1];
  302. int protocol_int = Hex_To_Int(pid);
  303. struct Protocol* protocol = proto_with_deccode(head, protocol_int);
  304. if(protocol != NULL)
  305. {
  306. //////////Stage 2: Address
  307. if(strcmp(protocol->name,"ipfs")!=0)
  308. {
  309. lastpos = lastpos+2;
  310. char address[(protocol->size/4)+1];
  311. memset(address, 0, (protocol->size / 4) + 1);
  312. memcpy(address, &hex[lastpos], protocol->size / 4);
  313. //////////Stage 3 Process it back to string
  314. lastpos= lastpos+(protocol->size/4);
  315. //////////Address:
  316. //Keeping Valgrind happy
  317. char name[30];
  318. bzero(name,30);
  319. strcpy(name, protocol->name);
  320. //
  321. strcat(results, "/");
  322. strcat(results, name);
  323. strcat(results, "/");
  324. if(strcmp(name, "ip4")==0)
  325. {
  326. strcat(results,int2ip(Hex_To_Int(address)));
  327. }
  328. else if(strcmp(name, "tcp")==0)
  329. {
  330. char a[5];
  331. sprintf(a,"%lu",Hex_To_Int(address));
  332. strcat(results,a);
  333. }
  334. else if(strcmp(name, "udp")==0)
  335. {
  336. char a[5];
  337. sprintf(a,"%lu",Hex_To_Int(address));
  338. strcat(results,a);
  339. }
  340. /////////////Done processing this, move to next if there is more.
  341. if(lastpos<size*2)
  342. {
  343. goto NAX;
  344. }
  345. }
  346. else//IPFS CASE
  347. {
  348. lastpos = lastpos + 4;
  349. //fetch the size of the address based on the varint prefix
  350. char prefixedvarint[3];
  351. memset(prefixedvarint, 0, 3);
  352. memcpy(prefixedvarint, &hex[lastpos-2], 2);
  353. int addrsize = HexVar_To_Num_32(prefixedvarint);
  354. // get the ipfs address as hex values
  355. unsigned char IPFS_ADDR[addrsize+1];
  356. memset(IPFS_ADDR, 0, addrsize + 1);
  357. memcpy(IPFS_ADDR, &hex[lastpos], addrsize);
  358. // convert the address from hex values to a binary array
  359. size_t num_bytes = 0;
  360. unsigned char* addrbuf = Hex_To_Var((char*)IPFS_ADDR, &num_bytes);
  361. size_t b58_size = strlen((char*)IPFS_ADDR);
  362. unsigned char b58[b58_size];
  363. memset(b58, 0, b58_size);
  364. unsigned char *ptr_b58 = b58;
  365. int returnstatus = multiaddr_encoding_base58_encode(addrbuf, num_bytes, &ptr_b58, &b58_size);
  366. free(addrbuf);
  367. if(returnstatus == 0)
  368. {
  369. fprintf(stderr, "Unable to base58 encode MultiAddress %s\n", IPFS_ADDR);
  370. unload_protocols(head);
  371. return 0;
  372. }
  373. strcat(results, "/");
  374. strcat(results, protocol->name);
  375. strcat(results, "/");
  376. strcat(results, (char*)b58);
  377. }
  378. }
  379. strcat(results, "/");
  380. unload_protocols(head);
  381. return 1;
  382. }
  383. //
  384. /**
  385. * Convert an address string to a byte representation
  386. * @param protocol the protocol to use
  387. * @param incoming the byte array
  388. * @param incoming_size the size of the byte array
  389. * @param results the results
  390. * @param results_size the size of the results
  391. * @returns the results array
  392. */
  393. char* address_string_to_bytes(struct Protocol * protocol, const char *incoming, size_t incoming_size, char** results, int* results_size)
  394. {
  395. static char astb__stringy[800] = "\0";
  396. memset(astb__stringy, 0, 800);
  397. int code = 0;
  398. code = protocol->deccode;
  399. switch(code)
  400. {
  401. case 4://IPv4
  402. {
  403. char testip[16] = "\0";
  404. bzero(testip,16);
  405. strcpy(testip,incoming);
  406. if(is_valid_ipv4(testip)==1)
  407. {
  408. uint64_t iip = ip2int(incoming);
  409. strcpy(astb__stringy,Int_To_Hex(iip));
  410. protocol = NULL;
  411. *results = malloc(strlen(astb__stringy));
  412. memcpy(*results, astb__stringy, strlen(astb__stringy));
  413. *results_size = strlen(astb__stringy);
  414. return *results;
  415. }
  416. else
  417. {
  418. return "ERR";
  419. }
  420. break;
  421. }
  422. case 41://IPv6 Must be done
  423. {
  424. return "ERR";
  425. break;
  426. }
  427. case 6: //Tcp
  428. {
  429. if(atoi(incoming)<65536&&atoi(incoming)>0)
  430. {
  431. static char himm_woot[5] = "\0";
  432. bzero(himm_woot, 5);
  433. strcpy(himm_woot, Int_To_Hex(atoi(incoming)));
  434. if(himm_woot[2] == '\0')
  435. {//manual switch
  436. char swap0='0';
  437. char swap1='0';
  438. char swap2=himm_woot[0];
  439. char swap3=himm_woot[1];
  440. himm_woot[0] = swap0;
  441. himm_woot[1] = swap1;
  442. himm_woot[2] = swap2;
  443. himm_woot[3] = swap3;
  444. }
  445. else if(himm_woot[3] == '\0')
  446. {
  447. char swap0='0';
  448. char swap1=himm_woot[0];
  449. char swap2=himm_woot[1];
  450. char swap3=himm_woot[2];
  451. himm_woot[0] = swap0;
  452. himm_woot[1] = swap1;
  453. himm_woot[2] = swap2;
  454. himm_woot[3] = swap3;
  455. }
  456. himm_woot[4]='\0';
  457. *results = malloc(5);
  458. *results_size = 5;
  459. memcpy(*results, himm_woot, 5);
  460. return *results;
  461. }
  462. else
  463. {
  464. return "ERR";
  465. }
  466. break;
  467. }
  468. case 17: //Udp
  469. {
  470. if(atoi(incoming)<65536&&atoi(incoming)>0)
  471. {
  472. static char himm_woot2[5] = "\0";
  473. bzero(himm_woot2, 5);
  474. strcpy(himm_woot2, Int_To_Hex(atoi(incoming)));
  475. if(himm_woot2[2] == '\0')
  476. {//Manual Switch2be
  477. char swap0='0';
  478. char swap1='0';
  479. char swap2=himm_woot2[0];
  480. char swap3=himm_woot2[1];
  481. himm_woot2[0] = swap0;
  482. himm_woot2[1] = swap1;
  483. himm_woot2[2] = swap2;
  484. himm_woot2[3] = swap3;
  485. }
  486. else if(himm_woot2[3] == '\0')
  487. {//Manual switch
  488. char swap0='0';
  489. char swap1=himm_woot2[0];
  490. char swap2=himm_woot2[1];
  491. char swap3=himm_woot2[2];
  492. himm_woot2[0] = swap0;
  493. himm_woot2[1] = swap1;
  494. himm_woot2[2] = swap2;
  495. himm_woot2[3] = swap3;
  496. }
  497. himm_woot2[4]='\0';
  498. *results = malloc(5);
  499. *results_size = 5;
  500. memcpy(*results, himm_woot2, 5);
  501. return *results;
  502. }
  503. else
  504. {
  505. return "ERR";
  506. }
  507. break;
  508. }
  509. case 33://dccp
  510. {
  511. return "ERR";
  512. }
  513. case 132://sctp
  514. {
  515. return "ERR";
  516. }
  517. case 301://udt
  518. {
  519. return "ERR";
  520. }
  521. case 302://utp
  522. {
  523. return "ERR";
  524. }
  525. case 42://IPFS - !!!
  526. {
  527. // decode the base58 to bytes
  528. char * incoming_copy = NULL;
  529. incoming_copy = (char*)incoming;
  530. size_t incoming_copy_size = strlen(incoming_copy);
  531. size_t result_buffer_length = multiaddr_encoding_base58_decode_max_size((unsigned char*)incoming_copy);
  532. unsigned char result_buffer[result_buffer_length];
  533. unsigned char* ptr_to_result = result_buffer;
  534. memset(result_buffer, 0, result_buffer_length);
  535. // now get the decoded address
  536. int return_value = multiaddr_encoding_base58_decode(incoming_copy, incoming_copy_size, &ptr_to_result, &result_buffer_length);
  537. if (return_value == 0)
  538. {
  539. return "ERR";
  540. }
  541. // throw everything in a hex string so we can debug the results
  542. char addr_encoded[300];
  543. memset(addr_encoded, 0, 300);
  544. int ilen = 0;
  545. for(int i = 0; i < result_buffer_length; i++)
  546. {
  547. // get the char so we can see it in the debugger
  548. char miu[3];
  549. sprintf(miu,"%02x", ptr_to_result[i]);
  550. strcat(addr_encoded, miu);
  551. }
  552. ilen = strlen(addr_encoded);
  553. char prefixed[3];
  554. memset(prefixed, 0, 3);
  555. strcpy(prefixed,Num_To_HexVar_32(ilen));
  556. *results_size = ilen + 3;
  557. *results = malloc(*results_size);
  558. memset(*results, 0, *results_size);
  559. strcat(*results, prefixed); // 2 bytes
  560. strcat(*results, addr_encoded); // ilen bytes + null terminator
  561. return *results;
  562. }
  563. case 480://http
  564. {
  565. return "ERR";
  566. }
  567. case 443://https
  568. {
  569. return "ERR";
  570. }
  571. case 477://ws
  572. {
  573. return "ERR";
  574. }
  575. case 444://onion
  576. {
  577. return "ERR";
  578. }
  579. case 275://libp2p-webrtc-star
  580. {
  581. return "ERR";
  582. }
  583. default:
  584. {
  585. printf("NO SUCH PROTOCOL!\n");
  586. return "ERR";
  587. }
  588. }
  589. }
  590. /**
  591. * convert a string address into bytes
  592. * @param finalbytes the destination
  593. * @param realbbsize the ultimate size of the destination
  594. * @param strx the incoming string
  595. * @param strsize the string length
  596. */
  597. int string_to_bytes(uint8_t** finalbytes, size_t* realbbsize, const char* strx, size_t strsize)
  598. {
  599. if(strx[0] != '/')
  600. {
  601. fprintf(stderr, "multiaddr:string_to_bytes: Error, must start with '/' : [%s].\n", strx);
  602. return 0;
  603. }
  604. //Initializing variables to store our processed HEX in:
  605. int malf=0; //In case something goes wrong this will be 1.
  606. char processed[800];//HEX CONTAINER
  607. bzero(processed,800);
  608. //Now Setting up variables for calculating which is the first
  609. //and second word:
  610. int firstorsecond = 1; //1=Protocol && 2 = Address
  611. // copy input so as to not harm it
  612. char pstring[strsize + 1];
  613. strcpy(pstring,strx);
  614. // load up the list of protocols
  615. struct ProtocolListItem* head = NULL;
  616. load_protocols(&head);
  617. //Starting to extract words and process them:
  618. char * wp;
  619. char * end;
  620. wp=strtok_r(pstring,"/",&end);
  621. struct Protocol * protx;
  622. while(wp)
  623. {
  624. if(firstorsecond==1)//This is the Protocol
  625. {
  626. protx = proto_with_name(head, wp);
  627. if(protx != NULL)
  628. {
  629. strcat(processed, Int_To_Hex(protx->deccode));
  630. firstorsecond=2;//Since the next word will be an address
  631. }
  632. else
  633. {
  634. printf("\nNo such protocol!\n\n");
  635. malf=1;
  636. break;
  637. }
  638. }
  639. else//This is the address
  640. {
  641. char* s_to_b = NULL;
  642. int s_to_b_size = 0;
  643. if( strcmp(address_string_to_bytes(protx, wp,strlen(wp), &s_to_b, &s_to_b_size), "ERR") == 0)
  644. {
  645. malf = 1;
  646. }
  647. else
  648. {
  649. int temp_size = strlen(processed);
  650. strncat(processed, s_to_b, s_to_b_size);
  651. processed[temp_size + s_to_b_size] = 0;
  652. free(s_to_b);
  653. }
  654. protx=NULL;//Since right now it doesn't need that assignment anymore.
  655. firstorsecond=1;//Since the next word will be an protocol
  656. }
  657. wp=strtok_r(NULL,"/",&end);
  658. }
  659. protx=NULL;
  660. unload_protocols(head);
  661. if(malf==1)
  662. {
  663. return 0;
  664. }
  665. else
  666. {
  667. *finalbytes = Hex_To_Var(processed, realbbsize);
  668. return 1;
  669. }
  670. }