123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <strings.h>
- #include <math.h>
- #include <inttypes.h>
- #include <ctype.h>
- #include "multiaddr/base58.h"
- #include "multiaddr/varhexutils.h"
- #include "multiaddr/protocols.h"
- #include "multiaddr/protoutils.h"
- extern char *strtok_r(char *, const char *, char **);
- //////////////////////////////////////////////////////////
- char ASCII2bits(char ch) {
- if (ch >= '0' && ch <= '9') {
- return (ch - '0');
- } else if (ch >= 'a' && ch <= 'z') {
- return (ch - 'a') + 10;
- } else if (ch >= 'A' && ch <= 'Z') {
- return (ch - 'A') + 10;
- }
- return 0; // fail
- }
- void hex2bin (char *dst, char *src, int len)
- {
- while (len--) {
- *dst = ASCII2bits(*src++) << 4; // higher bits
- *dst++ |= ASCII2bits(*src++); // lower bits
- }
- }
- char bits2ASCII(char b) {
- if (b >= 0 && b < 10) {
- return (b + '0');
- } else if (b >= 10 && b <= 15) {
- return (b - 10 + 'a');
- }
- return 0; // fail
- }
- void bin2hex (char *dst, char *src, int len)
- {
- while (len--) {
- *dst++ = bits2ASCII((*src >> 4) & 0xf); // higher bits
- *dst++ = bits2ASCII(*src++ & 0xf); // lower bits
- }
- *dst = '\0';
- }
- //////////////////////////////////////////////////////////
- //IPv4 VALIDATOR
- #define DELIM "."
- /* return 1 if string contain only digits, else return 0 */
- int valid_digit(char *ip_str)
- {
- int err = 0;
- while (*ip_str) {
- if (*ip_str >= '0' && *ip_str <= '9')
- ++ip_str;
- else
- return 0;
- }
- return 1;
- }
- /* return 1 if IP string is valid, else return 0 */
- int is_valid_ipv4(char *ip_str)
- {
- int i, num, dots = 0;
- char *ptr;
- int err=0;
- if (ip_str == NULL)
- err = 1;
- // See following link for strtok()
- // http://pubs.opengroup.org/onlinepubs/009695399/functions/strtok_r.html
- ptr = strtok(ip_str, DELIM);
- if (ptr == NULL)
- err = 1;
- while (ptr)
- {
- /* after parsing string, it must contain only digits */
- if (!valid_digit(ptr))
- err = 1;
- num = atoi(ptr);
- /* check for valid IP */
- if (num >= 0 && num <= 255) {
- /* parse remaining string */
- ptr = strtok(NULL, DELIM);
- if (ptr != NULL)
- ++dots;
- } else
- err = 1;
- }
- /* valid IP string must contain 3 dots */
- if (dots != 3)
- {
- err = 1;
- }
- if(err == 0)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- //////////////IPv6 Validator
- #define MAX_HEX_NUMBER_COUNT 8
- int ishexdigit(char ch)
- {
- if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='f')||(ch>='A'&&ch<='F'))
- return(1);
- return(0);
- }
- int is_valid_ipv6(char *str)
- {
- int hdcount=0;
- int hncount=0;
- int err=0;
- int packed=0;
- if(*str==':')
- {
- str++;
- if(*str!=':')
- return(0);
- else
- {
- packed=1;
- hncount=1;
- str++;
- if(*str==0)
- return(1);
- }
- }
- if(ishexdigit(*str)==0)
- {
- return(0);
- }
- hdcount=1;
- hncount=1;
- str++;
- while(err==0&&*str!=0)
- {
- if(*str==':')
- {
- str++;
- if(*str==':')
- {
- if(packed==1)
- err=1;
- else
- {
- str++;
- if(ishexdigit(*str) || (*str==0 && hncount < MAX_HEX_NUMBER_COUNT ))
- {
- packed=1;
- hncount++;
- if(ishexdigit(*str))
- {
- if(hncount==MAX_HEX_NUMBER_COUNT)
- {
- err=1;
- } else
- {
- hdcount=1;
- hncount++;
- str++;
- }
- }
- } else
- {
- err=1;
- }
- }
- }
- else
- {
- if(!ishexdigit(*str))
- {
- err=1;
- } else
- {
- if(hncount==MAX_HEX_NUMBER_COUNT)
- {
- err=1;
- } else
- {
- hdcount=1;
- hncount++;
- str++;
- }
- }
- }
- }
- else
- {
- if(ishexdigit(*str))
- {
- if(hdcount==4)
- err=1;
- else
- {
- hdcount++;
- str++;
- }
- } else
- err=1;
- }
- }
- if(hncount<MAX_HEX_NUMBER_COUNT&&packed==0)
- err=1;
- return(err==0);
- }
- uint64_t ip2int(const char * ipconvertint)
- {
- uint64_t final_result =0;
- char * iproc;
- int ipat1=0;
- int ipat2=0;
- int ipat3=0;
- int ipat4=0;
- char ip[16];
- strcpy(ip, ipconvertint);
- iproc = strtok (ip,".");
- for(int i=0; i<4;i++)
- {
- switch(i)
- {
- case 0:
- {
- ipat1 = atoi(iproc);
- break;
- }
- case 1:
- {
- ipat2 = atoi(iproc);
- break;
- }
- case 2:
- {
- ipat3 = atoi(iproc);
- break;
- }
- case 3:
- {
- ipat4 = atoi(iproc);
- break;
- }
- default:
- {
- printf("Somebody misplaced an int\n");
- break;
- }
- }
- iproc = strtok (NULL,".");
- }
- final_result = ((ipat1*pow(2,24))+(ipat2*pow(2,16))+(ipat3*pow(2,8))+ipat4*1);
- return final_result;
- }
- char * int2ip(int inputintip)
- {
- uint32_t ipint = inputintip;
- static char xxx_int2ip_result[16] = "\0";
- bzero(xxx_int2ip_result,16);
- uint32_t ipint0 = (ipint >> 8*3) % 256;
- uint32_t ipint1 = (ipint >> 8*2) % 256;
- uint32_t ipint2 = (ipint >> 8*1) % 256;
- uint32_t ipint3 = (ipint >> 8*0) % 256;
- sprintf(xxx_int2ip_result, "%d.%d.%d.%d", ipint0,ipint1,ipint2,ipint3);
- return xxx_int2ip_result;
- }
- /**
- * Unserialize the bytes into a string
- * @param results where to put the resultant string
- * @param in_bytes the bytes to unserialize
- * @param in_bytes_size the length of the bytes array
- * @returns 0 on error, otherwise 1
- */
- int bytes_to_string(char** buffer, const uint8_t* in_bytes, int in_bytes_size)
- {
- uint8_t * bytes = NULL;
- char *results = NULL;
- int size = in_bytes_size;
- struct ProtocolListItem* head = NULL;
- char hex[(in_bytes_size*2)+1];
- //Positioning for memory jump:
- int lastpos = 0;
- char pid[3];
- // set up variables
- load_protocols(&head);
- memset(hex, 0, (in_bytes_size * 2) + 1);
- char* tmp = (char*)Var_To_Hex((char*)in_bytes, size);
- memcpy(hex, tmp, in_bytes_size * 2);
- free(tmp);
- pid[2] = 0;
- // allocate memory for results
- *buffer = malloc(800);
- results = *buffer;
- memset(results, 0, 800);
- //Process Hex String
- NAX:
- //Stage 1 ID:
- pid[0] = hex[lastpos];
- pid[1] = hex[lastpos+1];
- int protocol_int = Hex_To_Int(pid);
- struct Protocol* protocol = proto_with_deccode(head, protocol_int);
- if(protocol != NULL)
- {
- //////////Stage 2: Address
- if(strcmp(protocol->name,"ipfs")!=0)
- {
- lastpos = lastpos+2;
- char address[(protocol->size/4)+1];
- memset(address, 0, (protocol->size / 4) + 1);
- memcpy(address, &hex[lastpos], protocol->size / 4);
- //////////Stage 3 Process it back to string
- lastpos= lastpos+(protocol->size/4);
- //////////Address:
- //Keeping Valgrind happy
- char name[30];
- bzero(name,30);
- strcpy(name, protocol->name);
- //
- strcat(results, "/");
- strcat(results, name);
- strcat(results, "/");
- if(strcmp(name, "ip4")==0)
- {
- strcat(results,int2ip(Hex_To_Int(address)));
- }
- else if(strcmp(name, "tcp")==0)
- {
- char a[5];
- sprintf(a,"%lu",Hex_To_Int(address));
- strcat(results,a);
- }
- else if(strcmp(name, "udp")==0)
- {
- char a[5];
- sprintf(a,"%lu",Hex_To_Int(address));
- strcat(results,a);
- }
- /////////////Done processing this, move to next if there is more.
- if(lastpos<size*2)
- {
- goto NAX;
- }
- }
- else//IPFS CASE
- {
- lastpos = lastpos + 4;
- //fetch the size of the address based on the varint prefix
- char prefixedvarint[3];
- memset(prefixedvarint, 0, 3);
- memcpy(prefixedvarint, &hex[lastpos-2], 2);
- int addrsize = HexVar_To_Num_32(prefixedvarint);
- // get the ipfs address as hex values
- unsigned char IPFS_ADDR[addrsize+1];
- memset(IPFS_ADDR, 0, addrsize + 1);
- memcpy(IPFS_ADDR, &hex[lastpos], addrsize);
- // convert the address from hex values to a binary array
- size_t num_bytes = 0;
- unsigned char* addrbuf = Hex_To_Var((char*)IPFS_ADDR, &num_bytes);
- size_t b58_size = strlen((char*)IPFS_ADDR);
- unsigned char b58[b58_size];
- memset(b58, 0, b58_size);
- unsigned char *ptr_b58 = b58;
- int returnstatus = multiaddr_encoding_base58_encode(addrbuf, num_bytes, &ptr_b58, &b58_size);
- free(addrbuf);
- if(returnstatus == 0)
- {
- fprintf(stderr, "Unable to base58 encode MultiAddress %s\n", IPFS_ADDR);
- unload_protocols(head);
- return 0;
- }
- strcat(results, "/");
- strcat(results, protocol->name);
- strcat(results, "/");
- strcat(results, (char*)b58);
- }
- }
- strcat(results, "/");
- unload_protocols(head);
- return 1;
- }
- //
- /**
- * Convert an address string to a byte representation
- * @param protocol the protocol to use
- * @param incoming the byte array
- * @param incoming_size the size of the byte array
- * @param results the results
- * @param results_size the size of the results
- * @returns the results array
- */
- char* address_string_to_bytes(struct Protocol * protocol, const char *incoming, size_t incoming_size, char** results, int* results_size)
- {
- static char astb__stringy[800] = "\0";
- memset(astb__stringy, 0, 800);
- int code = 0;
- code = protocol->deccode;
- switch(code)
- {
- case 4://IPv4
- {
- char testip[16] = "\0";
- bzero(testip,16);
- strcpy(testip,incoming);
- if(is_valid_ipv4(testip)==1)
- {
- uint64_t iip = ip2int(incoming);
- strcpy(astb__stringy,Int_To_Hex(iip));
- protocol = NULL;
- *results = malloc(strlen(astb__stringy));
- memcpy(*results, astb__stringy, strlen(astb__stringy));
- *results_size = strlen(astb__stringy);
- return *results;
- }
- else
- {
- return "ERR";
- }
- break;
- }
- case 41://IPv6 Must be done
- {
- return "ERR";
- break;
- }
- case 6: //Tcp
- {
- if(atoi(incoming)<65536&&atoi(incoming)>0)
- {
- static char himm_woot[5] = "\0";
- bzero(himm_woot, 5);
- strcpy(himm_woot, Int_To_Hex(atoi(incoming)));
- if(himm_woot[2] == '\0')
- {//manual switch
- char swap0='0';
- char swap1='0';
- char swap2=himm_woot[0];
- char swap3=himm_woot[1];
- himm_woot[0] = swap0;
- himm_woot[1] = swap1;
- himm_woot[2] = swap2;
- himm_woot[3] = swap3;
- }
- else if(himm_woot[3] == '\0')
- {
- char swap0='0';
- char swap1=himm_woot[0];
- char swap2=himm_woot[1];
- char swap3=himm_woot[2];
- himm_woot[0] = swap0;
- himm_woot[1] = swap1;
- himm_woot[2] = swap2;
- himm_woot[3] = swap3;
- }
- himm_woot[4]='\0';
- *results = malloc(5);
- *results_size = 5;
- memcpy(*results, himm_woot, 5);
- return *results;
- }
- else
- {
- return "ERR";
- }
- break;
- }
- case 17: //Udp
- {
- if(atoi(incoming)<65536&&atoi(incoming)>0)
- {
- static char himm_woot2[5] = "\0";
- bzero(himm_woot2, 5);
- strcpy(himm_woot2, Int_To_Hex(atoi(incoming)));
- if(himm_woot2[2] == '\0')
- {//Manual Switch2be
- char swap0='0';
- char swap1='0';
- char swap2=himm_woot2[0];
- char swap3=himm_woot2[1];
- himm_woot2[0] = swap0;
- himm_woot2[1] = swap1;
- himm_woot2[2] = swap2;
- himm_woot2[3] = swap3;
- }
- else if(himm_woot2[3] == '\0')
- {//Manual switch
- char swap0='0';
- char swap1=himm_woot2[0];
- char swap2=himm_woot2[1];
- char swap3=himm_woot2[2];
- himm_woot2[0] = swap0;
- himm_woot2[1] = swap1;
- himm_woot2[2] = swap2;
- himm_woot2[3] = swap3;
- }
- himm_woot2[4]='\0';
- *results = malloc(5);
- *results_size = 5;
- memcpy(*results, himm_woot2, 5);
- return *results;
- }
- else
- {
- return "ERR";
- }
- break;
- }
- case 33://dccp
- {
- return "ERR";
- }
- case 132://sctp
- {
- return "ERR";
- }
- case 301://udt
- {
- return "ERR";
- }
- case 302://utp
- {
- return "ERR";
- }
- case 42://IPFS - !!!
- {
- // decode the base58 to bytes
- char * incoming_copy = NULL;
- incoming_copy = (char*)incoming;
- size_t incoming_copy_size = strlen(incoming_copy);
- size_t result_buffer_length = multiaddr_encoding_base58_decode_max_size((unsigned char*)incoming_copy);
- unsigned char result_buffer[result_buffer_length];
- unsigned char* ptr_to_result = result_buffer;
- memset(result_buffer, 0, result_buffer_length);
- // now get the decoded address
- int return_value = multiaddr_encoding_base58_decode(incoming_copy, incoming_copy_size, &ptr_to_result, &result_buffer_length);
- if (return_value == 0)
- {
- return "ERR";
- }
- // throw everything in a hex string so we can debug the results
- char addr_encoded[300];
- memset(addr_encoded, 0, 300);
- int ilen = 0;
- for(int i = 0; i < result_buffer_length; i++)
- {
- // get the char so we can see it in the debugger
- char miu[3];
- sprintf(miu,"%02x", ptr_to_result[i]);
- strcat(addr_encoded, miu);
- }
- ilen = strlen(addr_encoded);
- char prefixed[3];
- memset(prefixed, 0, 3);
- strcpy(prefixed,Num_To_HexVar_32(ilen));
- *results_size = ilen + 3;
- *results = malloc(*results_size);
- memset(*results, 0, *results_size);
- strcat(*results, prefixed); // 2 bytes
- strcat(*results, addr_encoded); // ilen bytes + null terminator
- return *results;
- }
- case 480://http
- {
- return "ERR";
- }
- case 443://https
- {
- return "ERR";
- }
- case 477://ws
- {
- return "ERR";
- }
- case 444://onion
- {
- return "ERR";
- }
- case 275://libp2p-webrtc-star
- {
- return "ERR";
- }
- default:
- {
- printf("NO SUCH PROTOCOL!\n");
- return "ERR";
- }
- }
- }
- /**
- * convert a string address into bytes
- * @param finalbytes the destination
- * @param realbbsize the ultimate size of the destination
- * @param strx the incoming string
- * @param strsize the string length
- */
- int string_to_bytes(uint8_t** finalbytes, size_t* realbbsize, const char* strx, size_t strsize)
- {
- if(strx[0] != '/')
- {
- fprintf(stderr, "multiaddr:string_to_bytes: Error, must start with '/' : [%s].\n", strx);
- return 0;
- }
- //Initializing variables to store our processed HEX in:
- int malf=0; //In case something goes wrong this will be 1.
- char processed[800];//HEX CONTAINER
- bzero(processed,800);
- //Now Setting up variables for calculating which is the first
- //and second word:
- int firstorsecond = 1; //1=Protocol && 2 = Address
- // copy input so as to not harm it
- char pstring[strsize + 1];
- strcpy(pstring,strx);
- // load up the list of protocols
- struct ProtocolListItem* head = NULL;
- load_protocols(&head);
- //Starting to extract words and process them:
- char * wp;
- char * end;
- wp=strtok_r(pstring,"/",&end);
- struct Protocol * protx;
- while(wp)
- {
- if(firstorsecond==1)//This is the Protocol
- {
- protx = proto_with_name(head, wp);
- if(protx != NULL)
- {
- strcat(processed, Int_To_Hex(protx->deccode));
- firstorsecond=2;//Since the next word will be an address
- }
- else
- {
- printf("\nNo such protocol!\n\n");
- malf=1;
- break;
- }
- }
- else//This is the address
- {
- char* s_to_b = NULL;
- int s_to_b_size = 0;
- if( strcmp(address_string_to_bytes(protx, wp,strlen(wp), &s_to_b, &s_to_b_size), "ERR") == 0)
- {
- malf = 1;
- }
- else
- {
- int temp_size = strlen(processed);
- strncat(processed, s_to_b, s_to_b_size);
- processed[temp_size + s_to_b_size] = 0;
- free(s_to_b);
- }
- protx=NULL;//Since right now it doesn't need that assignment anymore.
- firstorsecond=1;//Since the next word will be an protocol
- }
- wp=strtok_r(NULL,"/",&end);
- }
- protx=NULL;
- unload_protocols(head);
- if(malf==1)
- {
- return 0;
- }
- else
- {
- *finalbytes = Hex_To_Var(processed, realbbsize);
- return 1;
- }
- }
|