Advertisement
Guest User

Untitled

a guest
Nov 16th, 2019
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.97 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6.  
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. #include <sstream>
  11. #include <regex>
  12.  
  13. #ifdef __WIN32__
  14. #include <winsock2.h>
  15. #include <ws2tcpip.h>
  16. #else
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #endif
  21.  
  22. #define PORT 8080
  23. #define MAXLINE 1024
  24.  
  25. using namespace std;
  26.  
  27. /*
  28. Spuštění aplikace
  29. Použití: dns [-r] [-x] [-6] -s server [-p port] adresa
  30.  
  31. Pořadí parametrů je libovolné. Popis parametrů:
  32. -r: Požadována rekurze (Recursion Desired = 1), jinak bez rekurze.
  33. -x: Reverzní dotaz místo přímého.
  34. -6: Dotaz typu AAAA místo výchozího A.
  35. -s: IP adresa nebo doménové jméno serveru, kam se má zaslat dotaz.
  36. -p port: Číslo portu, na který se má poslat dotaz, výchozí 53.
  37. adresa: Dotazovaná adresa.
  38. */
  39.  
  40. class DNS
  41. {
  42. public:
  43. string domainName;
  44. string IPaddress;
  45.  
  46. void printname()
  47. {
  48. cout << "Domain name is: " << domainName << "\n";
  49. }
  50. void printIP()
  51. {
  52. cout << "IP address is: " << IPaddress << "\n";
  53. }
  54. };
  55.  
  56. class Response
  57. {
  58. public:
  59. uint16_t QDCOUNT;
  60. uint16_t ANCOUNT;
  61. uint16_t NSCOUNT;
  62. uint16_t ARCOUNT;
  63. uint16_t AA; // Authoritative Answer
  64. uint16_t TC; // TrunCation
  65. uint16_t RA; // Recursion Available
  66. string QNAME; // name
  67. uint16_t QTYPE; // type
  68. uint16_t QCLASS; // class
  69.  
  70. void printEverything()
  71. {
  72. /**
  73. * @brief Debugging function that prints raw information
  74. * read from server answer packet.
  75. */
  76. cout << "\n\n***RECEIVED INFORMATION***\n";
  77. cout << "Questions: " << QDCOUNT << "\n";
  78. cout << "Answer RRs: " << ANCOUNT << "\n";
  79. cout << "Authority RRs: " << NSCOUNT << "\n";
  80. cout << "Additional RRs: " << ARCOUNT << "\n";
  81. cout << "Authoritative Answer: " << AA << "\n";
  82. cout << "Truncation: " << TC << "\n";
  83. cout << "Recursion Available: " << RA << "\n";
  84. cout << "Queries - Name: " << QNAME << "\n";
  85. cout << "Queries - Type: " << QTYPE << "\n";
  86. cout << "Queries - Class: " << QCLASS << "\n";
  87. cout << "\n\n\n";
  88. }
  89.  
  90. void printNicely()
  91. {
  92. /**
  93. * @brief Printing nicely formatted information.
  94. */
  95. string a,b;
  96. a = (this->AA == 1) ? "Yes, " : "No, ";
  97. cout << "Authoritative: " << a;
  98. a = (this->RA == 1) ? "Yes, " : "No, ";
  99. cout << "Recursive: " << a;
  100. a = (this->TC == 1) ? "Yes, " : "No\n";
  101. cout << "Truncated: " << a;
  102.  
  103. cout << "Question section(" << this->QDCOUNT << ")\n";
  104. a = (this->QTYPE == 1) ? "A" : "?";;
  105. b = (this->QCLASS == 1) ? "IN" : "?";
  106.  
  107. cout << " " << this->QNAME << ", " << a << ", " << b << "\n";
  108. //A IN
  109. cout << "Answer section(" << this->ANCOUNT << ")\n";
  110. cout << "Authority section(" << this->NSCOUNT << ")\n";
  111. cout << "Additional section(" << this->ARCOUNT << ")\n";
  112. }
  113.  
  114. int decodeDomainName(unsigned char *s)
  115. {
  116. /**
  117. * @brief Function gets a pointer to unsigned char array (outBuf) where
  118. * domain name begins (format '0x03'www'0x06'google'0x03'com'0x00'), reads the first
  119. * char as int to know the length of the following label, stores the
  120. * value, decrements that in each step. Reaching 0 indicates another
  121. * char representing following label length. Finally fills the Response attribute QNAME.
  122. * @param1 Pointer to received unsigned char array, where queried domain name begins
  123. * @return Lenght of the domain name in bytes
  124. */
  125. string domainName;
  126. unsigned char *t;
  127. int labelLen = (int)s[0]; // Means the lenght of the first label
  128. int domainLegth = 1;
  129.  
  130. for (t = ++s; *t != '\0'; t++)
  131. {
  132. domainLegth++;
  133. if (labelLen == 0)
  134. {
  135. labelLen = (int)t[0];
  136. domainName += '.';
  137. }
  138. else
  139. {
  140. //cout << t[0] << labelLen << "\n";
  141. domainName += t[0];
  142. labelLen--;
  143. }
  144. }
  145. this->QNAME = domainName;
  146. return (domainLegth + 1); // '\n' counts as well
  147. }
  148. };
  149.  
  150. class Resource
  151. {
  152. public:
  153. string NAME;
  154. string TYPE;
  155.  
  156.  
  157. int decodeDomainName(unsigned char *s)
  158. {
  159. /**
  160. * @brief Function gets a pointer to unsigned char array (outBuf) where
  161. * domain name begins (format '0x03'www'0x06'google'0x03'com'0x00'), reads the first
  162. * char as int to know the length of the following label, stores the
  163. * value, decrements that in each step. Reaching 0 indicates another
  164. * char representing following label length. Finally fills the Response attribute QNAME.
  165. * @param1 Pointer to received unsigned char array, where queried domain name begins
  166. * @return Lenght of the domain name in bytes
  167. */
  168. string domainName;
  169. unsigned char *t;
  170. int labelLen = (int)s[0]; // Means the lenght of the first label
  171. int domainLegth = 1;
  172.  
  173. for (t = ++s; *t != '\0'; t++)
  174. {
  175. domainLegth++;
  176. if (labelLen == 0)
  177. {
  178. labelLen = (int)t[0];
  179. domainName += '.';
  180. }
  181. else
  182. {
  183. //cout << t[0] << labelLen << "\n";
  184. domainName += t[0];
  185. labelLen--;
  186. }
  187. }
  188. this->NAME = domainName;
  189. return (domainLegth + 1); // '\n' counts as well
  190. }
  191.  
  192. void hello(){
  193. cout << "Hello\n";
  194. }
  195.  
  196. };
  197.  
  198.  
  199. // GLOBAL VARIABLES
  200. DNS serverToBeAsked;
  201. int port = 53; // Destination port, default value is 53
  202. bool ipv6 = false; // Flag IPV4/IPV6
  203. bool reversed = false;
  204. bool recursion = false;
  205. int mySocket;
  206. string askingFor;
  207. unsigned char outBuf[MAXLINE];
  208. unsigned char inBuf[65536], *qname, *reader;
  209. struct sockaddr_in to;
  210. struct sockaddr from;
  211.  
  212.  
  213.  
  214. int kill(int erNo)
  215. {
  216. if (erNo == 10)
  217. {
  218. fprintf(stderr, "Error: Empty label in the address\n");
  219. }
  220. else if (erNo == 11)
  221. {
  222. fprintf(stderr, "Error: Label has more than 63 characters\n");
  223. }
  224. else if (erNo == 12)
  225. {
  226. fprintf(stderr, "Error: Label contains forbidden character\n");
  227. }
  228. else if (erNo == 13)
  229. {
  230. fprintf(stderr, "Error: Domain name cannot end by dot character\n");
  231. }
  232. else if (erNo == 14)
  233. {
  234. fprintf(stderr, "Error: Wrong IPv4 format\n");
  235. }
  236. else if (erNo == 15)
  237. {
  238. fprintf(stderr, "Error: Port must be number\n");
  239. }
  240. else if (erNo == 16)
  241. {
  242. fprintf(stderr, "Error: No address to be asked for\n");
  243. }
  244. else if (erNo == 17){
  245. fprintf(stderr, "Error: Function inet_ntop\n");
  246. }
  247. else if (erNo == 18){
  248. fprintf(stderr, "Error: Function gethostbyname\n");
  249. }
  250. else
  251. {
  252. fprintf(stderr, "Error: Wrong argument number %d \n", erNo);
  253. }
  254. exit(-1);
  255. }
  256.  
  257. bool checkDomainNameSyntax(string probablyDomainName)
  258. {
  259. /**
  260. * @brief Function checks whether given string is a domain name.
  261. * Checks the following rules:
  262. * 1) Label consists of 1 to 63 characters
  263. * 2) Full domain name consists of max 253 ASCII characters
  264. * 3) Domain name is not case-sensitive
  265. *
  266. */
  267. if (probablyDomainName.back() == '.')
  268. {
  269. // Domain name cannot end by dot symbol
  270. kill(13);
  271. }
  272. vector<string> tokens;
  273. stringstream check1(probablyDomainName);
  274. string intermediate;
  275.  
  276. // Split into tokens by dot symbol
  277. while (getline(check1, intermediate, '.'))
  278. {
  279. tokens.push_back(intermediate);
  280. }
  281.  
  282. // Looping through the token vector, check each member
  283. for (int i = 0; i < tokens.size(); i++)
  284. {
  285. if (tokens[i].empty())
  286. {
  287. //when label is empty
  288. kill(10);
  289. }
  290. else if (tokens[i].size() > 63)
  291. {
  292. // when label is too long
  293. kill(11);
  294. }
  295. else if (tokens[i].find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-") != std::string::npos)
  296. {
  297. // when label contains forbidden character
  298. kill(12);
  299. }
  300. }
  301. return true;
  302. }
  303.  
  304. bool checkIPAdressSyntax(string probablyIPAdress)
  305. {
  306. if (probablyIPAdress.back() == '.')
  307. {
  308. // IP address cannot end by dot symbol
  309. kill(13);
  310. }
  311. vector<string> tokens;
  312. stringstream check1(probablyIPAdress);
  313. string intermediate;
  314.  
  315. // Split into tokens by dot symbol
  316. while (getline(check1, intermediate, '.'))
  317. {
  318. tokens.push_back(intermediate);
  319. }
  320.  
  321. // Looping through the token vector, check each member
  322. int IPv4_byte_length, IPv4_byte;
  323. for (int i = 0; i < tokens.size(); i++)
  324. {
  325. IPv4_byte_length = tokens.at(i).length();
  326. if(IPv4_byte_length > 3){
  327. return false;
  328. }else if(tokens[i].find_first_not_of("0123456789") != std::string::npos){
  329. return false;
  330. }
  331. IPv4_byte = stoi(tokens.at(i));
  332. if( !((IPv4_byte >= 0) && (IPv4_byte <= 255)) ){
  333. return false;
  334. }
  335. //std::cout << "Byte " << i << " is: " << tokens.at(i) << IPv4_byte << "\n";
  336. }
  337. return true;
  338. }
  339.  
  340. int setDNS(char *probablyServer, int argNo)
  341. {
  342. /**
  343. * @brief Function sets the DNS domain name/IP address. Option is required after -s.
  344. * Functions to check correct format are called. If the domain name was given, fills
  345. * the IP address, which is needed later.
  346. * @param1 Command line argument after -s option.
  347. * @param2 Actual position in the array of command line arguments.
  348. * @return Returns new position in the array of command line arguments.
  349. */
  350.  
  351. // converting char* to string
  352. std::string givenDNS = probablyServer;
  353.  
  354. if (checkIPAdressSyntax(givenDNS))
  355. {
  356. serverToBeAsked.IPaddress = givenDNS;
  357. }
  358. else if (checkDomainNameSyntax(givenDNS))
  359. {
  360. // Getting Ip address from structure of type hostent given by gethostbame()
  361. #ifdef __linux__
  362. serverToBeAsked.domainName = givenDNS;
  363.  
  364. struct hostent *host;
  365. char ip[16];
  366. char *ntopRet;
  367. int hostname;
  368.  
  369. struct sockaddr_in sock_addr;
  370. int n = givenDNS.length();
  371. char givenDNS_char_array[n + 1];
  372. strcpy(givenDNS_char_array, givenDNS.c_str());
  373.  
  374. // Getting host information
  375. host = gethostbyname(givenDNS_char_array);
  376. if (NULL == host)
  377. { //TODO: kontrola podmínky
  378. kill(18);
  379. }
  380. sock_addr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
  381. ntopRet = inet_ntop(AF_INET, &sock_addr.sin_addr, ip, sizeof(ip));
  382. if (NULL == ntopRet)
  383. { //TODO: kontrola podmínky
  384. kill(17);
  385. }
  386.  
  387. string s(ip);
  388. // save for later actions
  389. serverToBeAsked.IPaddress = s;
  390. #else
  391. printf("Run this on Linux. \n");
  392. exit(0);
  393. #endif
  394. }
  395. argNo++;
  396. // TODO: nesmí začínat pomlčkou
  397. return argNo;
  398. }
  399.  
  400. int setPort(char *probablyPort, int argNo)
  401. {
  402. /**
  403. * @brief Function sets the destination port number. Default 53, if there is no integer given.
  404. * @param1 Command line argument after -p option.
  405. * @param2 Actual position in the array of command line arguments.
  406. * @return Returns new position in the array of command line arguments. Only increment if port number was given.
  407. */
  408. int length = strlen(probablyPort);
  409. for (int i = 0; i < length; i++)
  410. {
  411. if (!isdigit(probablyPort[i]))
  412. {
  413. // Argument contains a non-digit character (port number was not specified) -> set default value 53
  414. kill(15);
  415. }
  416. }
  417. port = atoi(probablyPort);
  418. argNo++;
  419. return argNo;
  420. }
  421.  
  422.  
  423. string changeAddressFormat(string askingFor)
  424. {
  425. /**
  426. * @brief Function changed host address format (www.seznam.cz to '0x03'www''0x06'seznam'0x02'cz'0x00')
  427. * @param1 Hostname given as argument to be transformed
  428. * @return Transformed string
  429. */
  430. istringstream iss(askingFor);
  431. vector<string> tokens;
  432. string token;
  433. string temporaryQname;
  434. int tokenLenght;
  435. string wwwPrefix("www");
  436.  
  437. auto it = std::mismatch(wwwPrefix.begin(), wwwPrefix.end(), askingFor.begin());
  438. /*if( !(it.first == wwwPrefix.end()) ){
  439. // if 'www' is not a prefix of the given host name -> add
  440. // 3www to the beggining of temporaryQname
  441. temporaryQname.append("3wwww");
  442. }*/ TODO:
  443.  
  444. // split by dot symbol into a string vector
  445. while (std::getline(iss, token, '.'))
  446. {
  447. if (!token.empty()){
  448. tokens.push_back(token);
  449. }
  450. }
  451.  
  452. for (int i = 0; i < (tokens.capacity()-1); i++)
  453. {
  454. if(!tokens[i].empty()){
  455. // The length of the token is the hexadecimal value of the final char (0b01110111 -> 0x77 -> 'w')
  456. tokenLenght = tokens[i].length();
  457. unsigned char domainLength = 'a';
  458. domainLength &= 0; // set all bits to 0
  459. domainLength |= 0b00001000; // set the final value
  460. temporaryQname.append(to_string(domainLength));
  461. temporaryQname.append(tokens[i]);
  462. }
  463. }
  464. char nullCharacter = 'a';
  465. nullCharacter &= 0;
  466. temporaryQname.append(to_string(nullCharacter)); // has to end by 0
  467.  
  468. return temporaryQname;
  469. }
  470.  
  471.  
  472.  
  473. struct DNS_HEADER
  474. {
  475. unsigned short id; // identification number
  476. unsigned char rd : 1; // recursion desired
  477. unsigned char tc : 1; // truncated message
  478. unsigned char aa : 1; // authoritive answer
  479. unsigned char opcode : 4; // purpose of message
  480. unsigned char qr : 1; // query/response flag
  481. unsigned char rcode : 4; // response code
  482. unsigned char cd : 1; // checking disabled
  483. unsigned char ad : 1; // authenticated data
  484. unsigned char z : 1; // its z! reserved
  485. unsigned char ra : 1; // recursion available
  486. unsigned short q_count; // number of question entries
  487. unsigned short ans_count; // number of answer entries
  488. unsigned short auth_count; // number of authority entries
  489. unsigned short add_count; // number of resource entries
  490. };
  491.  
  492. struct QUESTION
  493. {
  494. unsigned short qtype;
  495. unsigned short qclass;
  496. };
  497.  
  498. struct R_DATA
  499. {
  500. unsigned short type;
  501. unsigned short _class;
  502. unsigned int ttl;
  503. unsigned short data_len;
  504. };
  505.  
  506. struct RES_RECORD
  507. {
  508. unsigned char *name;
  509. struct R_DATA *resource;
  510. unsigned char *rdata;
  511. };
  512.  
  513. typedef struct
  514. {
  515. unsigned char *name;
  516. struct QUESTION *ques;
  517. } QUERY;
  518.  
  519. int main(int argc, char *argv[])
  520. {
  521. int option;
  522. int i = 0;
  523.  
  524. // duplicate cmd line arguments cause getopt changes order
  525. vector<string> argVector;
  526. for(int j = 1; j < argc; j++){
  527. argVector.push_back(argv[j]);
  528. }
  529. /*for (int i = 0; i < argVector.size(); i++)
  530. {
  531. cout << argVector[i] << "\n";
  532. }*/
  533.  
  534. while ((option = getopt(argc, argv, "rx6s:p::")) != -1)
  535. {
  536. i++;
  537. switch (option)
  538. {
  539. case 'r':
  540. //printf("got %d) %c \n", i, option);
  541. recursion = true;
  542. break;
  543. case 'x':
  544. //printf("got %d) %c \n", i, option);
  545. reversed = true;
  546. break;
  547. case '6':
  548. //printf("got %d) %c \n", i, option);
  549. ipv6 = true;
  550. break;
  551. case 's':
  552. // Option -s is followed by IP address or domain name of the server
  553. //printf("got %d) %c \n", i, option);
  554. for (int j = 0; j < argc; ++j)
  555. {
  556. if (strcmp(argv[j], "-s") == 0)
  557. {
  558. //cout << argv[j] << "\n";
  559. i = setDNS(argv[j + 1], j);
  560. }
  561. }
  562. break;
  563. case 'p':
  564. // Option -p is followed by port number otherwise its set to 53
  565. //printf("got %d) %c \n", i, option);
  566. for (int j = 0; j < argc; ++j)
  567. {
  568. if (strcmp(argv[j], "-p") == 0)
  569. {
  570. //cout << argv[j] << "\n";
  571. i = setPort(argv[j + 1], j);
  572. }
  573. }
  574. //i = setPort(argv[i + 1], i);
  575. break;
  576. case ':':
  577. fprintf(stderr, "Option requires a value\n");
  578. kill(i);
  579. break;
  580. case '?':
  581. if (strcmp(argv[i], "-s") == 0)
  582. {
  583. fprintf(stderr, "Option -s requires a value\n");
  584. exit(-1);
  585. }
  586. else
  587. {
  588. kill(i);
  589. }
  590. break;
  591. default:
  592. //printf("got %d) uknown: %c \n", i, option);
  593. //kill(i);
  594.  
  595. break;
  596. }
  597. }
  598.  
  599. // Finding requested address to ask for in the command line arguments
  600. for (int i = 0; i < argVector.size(); i++)
  601. {
  602. regex flagFollowed("^-[sp]$");
  603. regex flagSingle("^-[6rx]$");
  604. if (regex_match(argVector[i], flagFollowed)) // matches flag with attribute
  605. {
  606. i++;
  607. }
  608. else if (regex_match(argVector[i], flagSingle)) // matches flag without attribute
  609. {
  610. ;
  611. }
  612. else
  613. {
  614. askingFor = argVector[i];
  615. }
  616. }
  617.  
  618. // Exit when no requested address found or
  619. if (askingFor.empty())
  620. {
  621. kill(16);
  622. }
  623.  
  624. // Cheching requested domain name syntax
  625. checkDomainNameSyntax(askingFor);
  626.  
  627. printf("!!!RECAP!!!\n");
  628. printf("Port var: %d\n", port);
  629. cout << "Asking for: " << askingFor << "\n";
  630. printf("IPV6: %d\n", (bool)ipv6);
  631. printf("Reverse: %d\n", (bool)reversed);
  632. printf("Recursion: %d\n", (bool)recursion);
  633.  
  634.  
  635. // Creating socket file descriptor
  636.  
  637. #if defined(WIN32) // TODO:
  638. WSADATA Data;
  639. WSAStartup(MAKEWORD(2, 2), &Data); // 2.2 version
  640. #endif
  641.  
  642. if ((mySocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  643. {
  644. perror("Error: Socket was no created succesfully");
  645. exit(EXIT_FAILURE);
  646. }
  647.  
  648. struct RES_RECORD answ[20], auth[20], addit[20]; //the replies from the DNS server
  649. struct DNS_HEADER *dns = NULL;
  650. struct QUESTION *qinfo = NULL;
  651. dns = (struct DNS_HEADER *)&inBuf;
  652.  
  653. memset(&to, 0, sizeof(to));
  654. // Filling server information
  655. to.sin_family = AF_INET;
  656. to.sin_port = htons(port);
  657. to.sin_addr.s_addr = inet_addr(serverToBeAsked.IPaddress.c_str());
  658.  
  659. int pid = GetCurrentProcessId();
  660.  
  661.  
  662. // 1 1 1 1 1 1
  663. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  664. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  665. // | ID |
  666. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  667. // |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
  668. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  669. // | QDCOUNT |
  670. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  671. // | ANCOUNT |
  672. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  673. // | NSCOUNT |
  674. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  675. // | ARCOUNT |
  676. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  677.  
  678. dns -> id = (unsigned short) htons(pid);
  679. dns -> rd = recursion; // 1 = "Do query recursively"
  680. dns -> tc = 0; // 0 = "Message is not truncated"
  681. dns -> aa = 0; // authoritative answer = false(0)
  682. dns -> opcode = 0; // 0 = "Standard query"
  683. dns -> qr = 0; // 0 = "Message is a query(0)", response(1)
  684. dns -> rcode = 0; // response code (0=ok, 1=format error, 2=server failure, 3=domain doesnt exist)
  685. dns -> cd = 0; // chesking disabled
  686. dns -> ad = 0; // 0 = "Non-authenticated data: Unnacceptable"
  687. dns -> z = 0; // reserved
  688. dns -> ra = 0; // recursion available = false
  689. dns -> q_count = htons(1); // number of questions
  690.  
  691. dns -> ans_count = 0; // number of answers
  692. dns -> auth_count = 0; // number of authority entries
  693. dns -> add_count = 0; // number of resource entries
  694.  
  695. qname = (unsigned char *)&inBuf[sizeof(struct DNS_HEADER)];
  696.  
  697. int l = askingFor.length();
  698. char char_array[l + 1];
  699. char new_char_array[l + 2];
  700. memset(new_char_array, '.', sizeof(new_char_array));
  701. strcpy(char_array, askingFor.c_str());
  702. uint8_t counter;
  703.  
  704. int k;
  705. for (k = 0; char_array[k] != '\0'; k++)
  706. {
  707. if (char_array[k] == '.')
  708. {
  709. new_char_array[k - counter] &= 0;
  710. new_char_array[k - counter] |= counter;
  711. counter = 0;
  712. }else{
  713. new_char_array[k + 1] = char_array[k];
  714. counter++;
  715. }
  716. }
  717. //set char 0x03 before com TLD, 0x02 before cz TLD
  718. new_char_array[k - counter] &= 0;
  719. new_char_array[k - counter] |= counter;
  720.  
  721. // set char after TLD to 0x00
  722. new_char_array[sizeof(new_char_array) - 1] &= 0;
  723.  
  724. // copy new_char_array to qname
  725. memcpy(qname, new_char_array, sizeof(new_char_array));
  726.  
  727. /*printf("\n");
  728. for (int i = 0; new_char_array[i] != '\0'; i++)
  729. {
  730.  
  731. printf("%c", new_char_array[i]);
  732. }
  733. printf("\n");*/
  734.  
  735. qinfo = (struct QUESTION *)&inBuf[sizeof(struct DNS_HEADER) + sizeof(new_char_array)];
  736.  
  737. qinfo->qtype = htons(1); // requesting ipv4
  738. qinfo->qclass = htons(1); // stands for IN
  739.  
  740. int sentBytes = sendto(mySocket, (char *)inBuf, sizeof(struct DNS_HEADER) + sizeof(new_char_array) + sizeof(struct QUESTION), 0, (sockaddr *)&to, sizeof(to));
  741. printf("Leti paket neco si prej! %d\n", sentBytes); // TODO: check na sendto
  742.  
  743. int len;
  744. int addrlen = sizeof(from); // needs to be initialized
  745. int receivedBytes = recvfrom(mySocket, (char *)outBuf, MAXLINE, MSG_PEEK, (struct sockaddr *)&from, &addrlen); //TODO: makro MSG_WAITALL
  746. if (receivedBytes == -1)
  747. {
  748. fprintf(stderr, "Error: Function recvfrom.");
  749. exit(-1);
  750. }
  751.  
  752. /*---------------------------------------------------------*/
  753. /*-------------------READING INFORMATION-------------------*/
  754. /*---------------------------------------------------------*/
  755. Response r;
  756.  
  757. /* Questions 2B */
  758. r.QDCOUNT = outBuf[4];
  759. r.QDCOUNT = (r.QDCOUNT << sizeof(outBuf[5])) | outBuf[5];
  760. /* Answers 2B */
  761. r.ANCOUNT = outBuf[6];
  762. r.ANCOUNT = (r.ANCOUNT << sizeof(outBuf[7])) | outBuf[7];
  763. /* Authorities 2B */
  764. r.NSCOUNT = outBuf[8];
  765. r.NSCOUNT = (r.NSCOUNT << sizeof(outBuf[9])) | outBuf[9];
  766. /* Additional 2B */
  767. r.ARCOUNT = outBuf[10];
  768. r.ARCOUNT = (r.ARCOUNT << sizeof(outBuf[11])) | outBuf[11];
  769.  
  770. /* 1 1 1 1 1 1
  771. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  772. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  773. |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
  774. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  775. */
  776.  
  777. /* Authoritative Answer 1b */
  778. uint8_t bitValue = outBuf[2];
  779. bitValue &= 0b00000100;
  780. bitValue >>= 2;
  781. r.AA = bitValue;
  782.  
  783. /* TrunCation 1b */
  784. bitValue = outBuf[2];
  785. bitValue &= 0b00000010;
  786. bitValue >>= 1;
  787. r.TC = bitValue;
  788.  
  789. /* Recursion Available 1b */
  790. bitValue = outBuf[3];
  791. bitValue &= 0b10000000;
  792. bitValue >>= 7;
  793. r.RA = bitValue;
  794.  
  795. /* Queried name VARIABLE LENGTH */
  796. // Asked domain starts at 12th position of array
  797. int qnameLen = r.decodeDomainName(&outBuf[12]);
  798. cout << qnameLen << '\n';
  799.  
  800. /* Queried type 2B */
  801. int qTypeIndex = 12 + qnameLen;
  802. r.QTYPE = outBuf[qTypeIndex];
  803. r.QTYPE = (r.QTYPE << sizeof(outBuf[qTypeIndex + 1])) | outBuf[qTypeIndex + 1];
  804.  
  805. /* Queried class 2B */
  806. int qClassIndex = qTypeIndex + 2;
  807. r.QCLASS = outBuf[qClassIndex];
  808. r.QCLASS = (r.QCLASS << sizeof(outBuf[qClassIndex + 1])) | outBuf[qClassIndex +1];
  809.  
  810. /* Resources */
  811. /* 1 1 1 1 1 1
  812. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  813. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  814. | |
  815. / /
  816. / NAME /
  817. | |
  818. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  819. | TYPE |
  820. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  821. | CLASS |
  822. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  823. | TTL |
  824. | |
  825. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  826. | RDLENGTH |
  827. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
  828. / RDATA /
  829. / /
  830. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-*/
  831.  
  832. int questions = r.QDCOUNT;
  833. int answers = r.ANCOUNT;
  834. int authority = r.NSCOUNT;
  835. int additional = r.ARCOUNT;
  836. // array of resource object
  837. Resource **resourceArray = new Resource *[questions + answers + authority + additional];
  838. int rPos = 0;
  839.  
  840. while(questions){
  841. resourceArray[rPos] = new Resource();
  842. resourceArray[rPos]->hello(); //TODO: do konstruktoru typ a počet výskytu danýho typu
  843. rPos++;
  844. questions--;
  845. }
  846. while (answers){
  847. resourceArray[rPos] = new Resource();
  848. resourceArray[rPos]->hello();
  849. rPos++;
  850. answers--;
  851. }
  852. while (authority){
  853. resourceArray[rPos] = new Resource();
  854. resourceArray[rPos]->hello();
  855. rPos++;
  856. authority--;
  857. }
  858. while (additional){
  859. resourceArray[rPos] = new Resource();
  860. resourceArray[rPos]->hello();
  861. rPos++;
  862. additional--;
  863. }
  864.  
  865. int resrcsIndex = qClassIndex + 2;
  866. unsigned char check = outBuf[resrcsIndex];
  867. uint16_t offset;
  868. int rsrcLen;
  869.  
  870. Resource alpha;
  871. // Check whether name is a pointer. Its truth when 2 leftmost bits are set to '1'.
  872. if ((check & (1 << 7)) && (check & (1 << 6))) // Its a pointer
  873. {
  874. // The rest of the bits in the 2B block define an offset from the beggining on the response
  875. offset = outBuf[resrcsIndex];
  876. offset = (offset << sizeof(outBuf[resrcsIndex + 1]) & 0b00111111) | outBuf[resrcsIndex + 1];
  877. alpha.decodeDomainName(&outBuf[offset]);
  878. rsrcLen = 2;
  879. cout << "TUNA: " << alpha.NAME << "\n";
  880. }else{ // Its a domain name. TODO: • a sequence of labels ending with a pointer
  881. rsrcLen = alpha.decodeDomainName(&outBuf[resrcsIndex]);
  882. cout << "TUNA: " << alpha.NAME << "\n";
  883. }
  884.  
  885. /* Type A or CTYPE*/
  886. uint16_t type = outBuf[resrcsIndex + rsrcLen];
  887. type = (type << sizeof(outBuf[resrcsIndex + rsrcLen + 1]) | outBuf[resrcsIndex + rsrcLen + 1]);
  888. if(type == 5){ // CNAME code
  889. alpha.TYPE = "CNAME";
  890. }else if(type == 1){ // A code
  891. alpha.TYPE = "A";
  892. }
  893. cout << "TUNA: " << alpha.TYPE << "\n";
  894.  
  895. r.printEverything();
  896. r.printNicely();
  897.  
  898. close(mySocket);
  899.  
  900. #if defined(WIN32) //TODO:
  901. WSACleanup();
  902. #endif
  903. return 0;
  904. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement