Advertisement
Guest User

Untitled

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