Advertisement
Guest User

Untitled

a guest
Nov 12th, 2019
512
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.82 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. int port = 53; // Destination port, default value is 53
  58. DNS destinationDNS; // Destination DNS server
  59. bool ipv6 = false; // Flag IPV4/IPV6
  60. bool reversed = false;
  61. bool recursion = false;
  62. int mySocket;
  63. char buffer[MAXLINE];
  64. string askingFor;
  65. struct sockaddr_in servaddr, cliaddr;
  66.  
  67. int kill(int erNo)
  68. {
  69. if (erNo == 10)
  70. {
  71. fprintf(stderr, "Error: Empty label in the address\n");
  72. }
  73. else if (erNo == 11)
  74. {
  75. fprintf(stderr, "Error: Label has more than 63 characters\n");
  76. }
  77. else if (erNo == 12)
  78. {
  79. fprintf(stderr, "Error: Label contains forbidden character\n");
  80. }
  81. else if (erNo == 13)
  82. {
  83. fprintf(stderr, "Error: Domain name cannot end by dot character\n");
  84. }
  85. else if (erNo == 14)
  86. {
  87. fprintf(stderr, "Error: Wrong IPv4 format\n");
  88. }
  89. else if (erNo == 15)
  90. {
  91. fprintf(stderr, "Error: Port must be number\n");
  92. }
  93. else if (erNo == 16)
  94. {
  95. fprintf(stderr, "Error: No address to be asked for\n");
  96. }
  97. else
  98. {
  99. fprintf(stderr, "Error: Wrong argument number %d \n", erNo);
  100. }
  101. exit(-1);
  102. }
  103.  
  104. bool checkDomainNameSyntax(string probablyDomainName)
  105. {
  106. /**
  107. * @brief Function checks whether given string is a domain name.
  108. * Checks the following rules:
  109. * 1) Label consists of 1 to 63 characters
  110. * 2) Full domain name consists of max 253 ASCII characters
  111. * 3) Domain name is not case-sensitive
  112. *
  113. */
  114. if (probablyDomainName.back() == '.')
  115. {
  116. // Domain name cannot end by dot symbol
  117. kill(13);
  118. }
  119. vector<string> tokens;
  120. stringstream check1(probablyDomainName);
  121. string intermediate;
  122.  
  123. // Split into tokens by dot symbol
  124. while (getline(check1, intermediate, '.'))
  125. {
  126. tokens.push_back(intermediate);
  127. }
  128.  
  129. // Looping through the token vector, check each member
  130. for (int i = 0; i < tokens.size(); i++)
  131. {
  132. if (tokens[i].empty())
  133. {
  134. //when label is empty
  135. kill(10);
  136. }
  137. else if (tokens[i].size() > 63)
  138. {
  139. // when label is too long
  140. kill(11);
  141. }
  142. else if (tokens[i].find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-") != std::string::npos)
  143. {
  144. // when label contains forbidden character
  145. kill(12);
  146. }
  147. }
  148. return true;
  149. }
  150.  
  151. bool checkIPAdressSyntax(string probablyIPAdress)
  152. {
  153. if (probablyIPAdress.back() == '.')
  154. {
  155. // IP address cannot end by dot symbol
  156. kill(13);
  157. }
  158. vector<string> tokens;
  159. stringstream check1(probablyIPAdress);
  160. string intermediate;
  161.  
  162. // Split into tokens by dot symbol
  163. while (getline(check1, intermediate, '.'))
  164. {
  165. tokens.push_back(intermediate);
  166. }
  167.  
  168. // Looping through the token vector, check each member
  169. int IPv4_byte_length, IPv4_byte;
  170. for (int i = 0; i < tokens.size(); i++)
  171. {
  172. IPv4_byte_length = tokens.at(i).length();
  173. if(IPv4_byte_length > 3){
  174. return false;
  175. }else if(tokens[i].find_first_not_of("0123456789") != std::string::npos){
  176. return false;
  177. }
  178. IPv4_byte = stoi(tokens.at(i));
  179. if( !((IPv4_byte >= 0) && (IPv4_byte <= 255)) ){
  180. return false;
  181. }
  182. std::cout << "Byte " << i << " is: " << tokens.at(i) << IPv4_byte << "\n";
  183. }
  184. return true;
  185. }
  186.  
  187. int setDNS(char *probablyServer, int argNo)
  188. {
  189. /**
  190. * @brief Function sets the DNS server/IP address. Option is required after -s.
  191. * @param1 Command line argument after -s option.
  192. * @param2 Actual position in the array of command line arguments.
  193. * @return Returns new position in the array of command line arguments.
  194. */
  195. int length = strlen(probablyServer);
  196.  
  197. // converting char* to string variable using std::string::assign
  198. std::string givenDNS;
  199. givenDNS.assign(probablyServer, length);
  200.  
  201. if (checkIPAdressSyntax(givenDNS))
  202. {
  203. destinationDNS.IPaddress = givenDNS;
  204. destinationDNS.printIP();
  205. }
  206. else if (checkDomainNameSyntax(givenDNS))
  207. {
  208. destinationDNS.domainName = givenDNS;
  209. destinationDNS.printname();
  210. }
  211. argNo++;
  212. // TODO: nesmí začínat pomlčkou
  213. return argNo;
  214. }
  215.  
  216. int setPort(char *probablyPort, int argNo)
  217. {
  218. /**
  219. * @brief Function sets the destination port number. Default 53, if there is no integer given.
  220. * @param1 Command line argument after -p option.
  221. * @param2 Actual position in the array of command line arguments.
  222. * @return Returns new position in the array of command line arguments. Only increment if port number was given.
  223. */
  224. int length = strlen(probablyPort);
  225. for (int i = 0; i < length; i++)
  226. {
  227. if (!isdigit(probablyPort[i]))
  228. {
  229. // Argument contains a non-digit character (port number was not specified) -> set default value 53
  230. kill(15);
  231. }
  232. }
  233. port = atoi(probablyPort);
  234. argNo++;
  235. return argNo;
  236. }
  237.  
  238. string changeAddressFormat(string askingFor)
  239. {
  240. /**
  241. * @brief Function changed host address format (www.seznam.cz to 3www6seznam2cz0)
  242. * @param1 Hostname given as argument to be transformed
  243. * @return Transformed string
  244. */
  245. istringstream iss(askingFor);
  246. vector<string> tokens;
  247. string token;
  248. string temporaryQname;
  249. int tokenLenght;
  250. string wwwPrefix("www");
  251.  
  252. auto it = std::mismatch(wwwPrefix.begin(), wwwPrefix.end(), askingFor.begin());
  253. /*if( !(it.first == wwwPrefix.end()) ){
  254. // if 'www' is not a prefix of the given host name -> add
  255. // 3www to the beggining of temporaryQname
  256. temporaryQname.append("3wwww");
  257. }*/ TODO:
  258.  
  259. // split by dot symbol into a string vector
  260. while (std::getline(iss, token, '.'))
  261. {
  262. if (!token.empty()){
  263. tokens.push_back(token);
  264. }
  265. }
  266.  
  267. for (int i = 0; i < (tokens.capacity()-1); i++)
  268. {
  269. if(!tokens[i].empty()){
  270. tokenLenght = tokens[i].length();
  271. temporaryQname.append(std::to_string(tokenLenght));
  272. temporaryQname.append(tokens[i]);
  273. }
  274. }
  275. temporaryQname.append("0"); // has to end by 0
  276.  
  277. return temporaryQname;
  278. }
  279.  
  280. struct DNS_HEADER
  281. {
  282. unsigned short id; // identification number
  283. unsigned char rd : 1; // recursion desired
  284. unsigned char tc : 1; // truncated message
  285. unsigned char aa : 1; // authoritive answer
  286. unsigned char opcode : 4; // purpose of message
  287. unsigned char qr : 1; // query/response flag
  288. unsigned char rcode : 4; // response code
  289. unsigned char cd : 1; // checking disabled
  290. unsigned char ad : 1; // authenticated data
  291. unsigned char z : 1; // its z! reserved
  292. unsigned char ra : 1; // recursion available
  293. unsigned short q_count; // number of question entries
  294. unsigned short ans_count; // number of answer entries
  295. unsigned short auth_count; // number of authority entries
  296. unsigned short add_count; // number of resource entries
  297. };
  298.  
  299. struct QUESTION
  300. {
  301. unsigned short qtype;
  302. unsigned short qclass;
  303. };
  304.  
  305. struct R_DATA
  306. {
  307. unsigned short type;
  308. unsigned short _class;
  309. unsigned int ttl;
  310. unsigned short data_len;
  311. };
  312.  
  313. struct RES_RECORD
  314. {
  315. unsigned char *name;
  316. struct R_DATA *resource;
  317. unsigned char *rdata;
  318. };
  319.  
  320. typedef struct
  321. {
  322. unsigned char *name;
  323. struct QUESTION *ques;
  324. } QUERY;
  325.  
  326. int main(int argc, char *argv[])
  327. {
  328. int option;
  329. int i = 0;
  330.  
  331. // duplicate cmd line arguments cause getopt changes order
  332. vector<string> argVector;
  333. for(int j = 1; j < argc; j++){
  334. argVector.push_back(argv[j]);
  335. }
  336. /*for (int i = 0; i < argVector.size(); i++)
  337. {
  338. cout << argVector[i] << "\n";
  339. }*/
  340.  
  341. //printf("Args: %s %s %s %s %s %s %s \n", argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
  342. while ((option = getopt(argc, argv, "rx6s:p::")) != -1)
  343. {
  344. i++;
  345. switch (option)
  346. {
  347. case 'r':
  348. //printf("got %d) %c \n", i, option);
  349. recursion = true;
  350. break;
  351. case 'x':
  352. //printf("got %d) %c \n", i, option);
  353. reversed = true;
  354. break;
  355. case '6':
  356. //printf("got %d) %c \n", i, option);
  357. ipv6 = true;
  358. break;
  359. case 's':
  360. // Option -s is followed by IP address or domain name of the server
  361. //printf("got %d) %c \n", i, option);
  362. for (int j = 0; j < argc; ++j)
  363. {
  364. if (strcmp(argv[j], "-s") == 0)
  365. {
  366. //cout << argv[j] << "\n";
  367. i = setDNS(argv[j + 1], j);
  368. }
  369. }
  370. break;
  371. case 'p':
  372. // Option -p is followed by port number otherwise its set to 53
  373. //printf("got %d) %c \n", i, option);
  374. for (int j = 0; j < argc; ++j)
  375. {
  376. if (strcmp(argv[j], "-p") == 0)
  377. {
  378. //cout << argv[j] << "\n";
  379. i = setPort(argv[j + 1], j);
  380. }
  381. }
  382. //i = setPort(argv[i + 1], i);
  383. break;
  384. case ':':
  385. fprintf(stderr, "Option requires a value\n");
  386. kill(i);
  387. break;
  388. case '?':
  389. if (strcmp(argv[i], "-s") == 0)
  390. {
  391. fprintf(stderr, "Option -s requires a value\n");
  392. exit(-1);
  393. }
  394. else
  395. {
  396. kill(i);
  397. }
  398. break;
  399. default:
  400. //printf("got %d) uknown: %c \n", i, option);
  401. //kill(i);
  402.  
  403. break;
  404. }
  405. }
  406.  
  407. // Finding requested address to ask for in the command line arguments
  408. for (int i = 0; i < argVector.size(); i++)
  409. {
  410. regex flagFollowed("^-[sp]$");
  411. regex flagSingle("^-[6rx]$");
  412. if (regex_match(argVector[i], flagFollowed)) // matches flag with attribute
  413. {
  414. i++;
  415. }
  416. else if (regex_match(argVector[i], flagSingle)) // matches flag without attribute
  417. {
  418. ;
  419. }
  420. else
  421. {
  422. askingFor = argVector[i];
  423. }
  424. }
  425.  
  426. // Exit when no requested address found or
  427. if (askingFor.empty())
  428. {
  429. kill(16);
  430. }
  431.  
  432. // Cheching requested domain name syntax
  433. checkDomainNameSyntax(askingFor);
  434.  
  435. printf("!!!RECAP!!!\n");
  436. printf("Port var: %d\n", port);
  437. cout << "Asking for: " << askingFor << "\n";
  438. printf("IPV6: %d\n", (bool)ipv6);
  439. printf("Reverse: %d\n", (bool)reversed);
  440. printf("Recursion: %d\n", (bool)recursion);
  441.  
  442. // Creating socket file descriptor
  443.  
  444. #if defined(WIN32) // TODO:
  445. WSADATA Data;
  446. WSAStartup(MAKEWORD(2, 2), &Data); // 2.2 version
  447. #endif
  448.  
  449. if ((mySocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  450. {
  451. printf("\nSOCKET NA PICU!\n");
  452. perror("socket creation failed");
  453. exit(EXIT_FAILURE);
  454. }
  455. else
  456. {
  457. printf("\nDOBREJ SOCKET PANE!\n");
  458. }
  459.  
  460. struct RES_RECORD answers[20], auth[20], addit[20]; //the replies from the DNS server
  461. struct sockaddr_in servaddr;
  462.  
  463. unsigned char buf[65536], *qname, *reader;
  464. struct DNS_HEADER *dns = NULL;
  465. struct QUESTION *qinfo = NULL;
  466. dns = (struct DNS_HEADER *)&buf;
  467.  
  468. memset(&servaddr, 0, sizeof(servaddr));
  469. // Filling server information
  470. servaddr.sin_family = AF_INET;
  471. servaddr.sin_port = htons(port);
  472. servaddr.sin_addr.s_addr = inet_addr("8.8.8.8");
  473.  
  474. int pid = GetCurrentProcessId();
  475.  
  476. dns -> id = (unsigned short) htons(pid);
  477. dns -> rd = recursion; // 1 = "Do query recursively"
  478. dns -> tc = 0; // 0 = "Message is not truncated"
  479. dns -> aa = 0; // authoritative answer = false(0)
  480. dns -> opcode = 0; // 0 = "Standard query"
  481. dns -> qr = 0; // 0 = "Message is a query(0)", response(1)
  482. dns -> rcode = 0; // response code (0=ok, 1=format error, 2=server failure, 3=domain doesnt exist)
  483. dns -> cd = 0; // chesking disabled
  484. dns -> ad = 0; // 0 = "Non-authenticated data: Unnacceptable"
  485. dns -> z = 0; // reserved
  486. dns -> ra = 0; // recursion available = false
  487. dns -> q_count = htons(1); // number of questions
  488.  
  489. dns -> ans_count = 0; // number of answers
  490. dns -> auth_count = 0; // number of authority entries
  491. dns -> add_count = 0; // number of resource entries
  492.  
  493. qname = (unsigned char *)&buf[sizeof(struct DNS_HEADER)+sizeof(struct QUESTION)];
  494. string addrDNSFormat = changeAddressFormat(askingFor);
  495.  
  496. // Converting string to char array
  497. int length = addrDNSFormat.length();
  498. char addrChanged[length + 1];
  499. strcpy(addrChanged, addrDNSFormat.c_str());
  500.  
  501. // filling the hostname
  502. //qname = (unsigned char *)addrChanged;
  503. /*unsigned char ch = 'a';
  504. unsigned char h = 'g';
  505. *qname = ch;
  506. *qname++ = h;*/
  507. for (int i = 0; i < 43; i++) //TODO:
  508. {
  509. *qname++;
  510. }
  511.  
  512.  
  513.  
  514. for (int j = 0; j < 16; j++)
  515. {
  516. *qname = addrChanged[j];
  517. printf("TU: %c", addrChanged[j]);
  518. *qname++;
  519. }
  520. *qname++ = '\0';
  521.  
  522. cout << askingFor;
  523. printf("\nqname: ");
  524. for (int i = 0; i < strlen((char *)qname); i++)
  525. {
  526. printf("%c", qname[i]);
  527. }
  528. printf("\n");
  529. printf("addrChanged: ");
  530. for (int i = 0; i < strlen((char*)addrChanged); i++)
  531. {
  532. printf("%c", addrChanged[i]);
  533. }
  534. printf("\n");
  535.  
  536. qinfo = (struct QUESTION *)&buf[sizeof(struct DNS_HEADER) + (strlen((const char *)qname) + 1)];
  537.  
  538. qinfo->qtype = htons(1); // requesting ipv4
  539. qinfo->qclass = htons(1); // stands for IN
  540.  
  541. int n, len;
  542.  
  543. //int bz = sendto(mySocket, hello, strlen(hello), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr));
  544. //printf("Leti paket neco si prej! %d\n", bz);
  545.  
  546. int er = sendto(mySocket, (char *)buf, sizeof(struct DNS_HEADER) + (strlen((const char *)qname) + 1) + sizeof(struct QUESTION), 0, (sockaddr *)&servaddr, sizeof(servaddr));
  547. printf("Leti paket neco si prej! %d\n", er);
  548. /*
  549. int i = sizeof(dest);
  550. recvfrom(mySocket, (char *)buf, 65536, 0, (sockaddr *)&dest, &i);
  551. */
  552.  
  553. /*n = recvfrom(mySocket, (char *)buffer, MAXLINE, 1, (struct sockaddr *)&servaddr, &len);
  554. buffer[n] = '\0';
  555. printf("Server : %s\n", buffer);*/
  556.  
  557. close(mySocket);
  558.  
  559. #if defined(WIN32) //TODO:
  560. WSACleanup();
  561. #endif
  562. return 0;
  563. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement