A bug fix for Libevent DNS resolution on Android

Source: Internet
Author: User
Tags strcmp

In testing one of our developed APK (using Libevent-2.1.3-alpha as the network library) when found a strange problem, domain name resolution has the Times wrong non-recoverable name resolution failure. In the company occasionally error, then the program changed a bit, when the error occurred several times, the problem did not appear again, thought good. Yesterday changed a network environment, the result of error is very large.

The internet has found a way to deal with this error, saying that it is necessary to explicitly specify its second parameter salen as sizeof (struct sockaddr_in) or sizeof (struct sockaddr_in6) when using the Getnameinfo () function. It is said that the getnameinfo () implementation on Solaris and Android does not look at the sin_family in saddr to calculate the true Salen. I tried, did not solve the problem, and then think about it, Libevent simply did not use the system's domain name resolution function, completely their own implementation, so had to themselves with the code.

Because the remote debugging environment is not set up, can only continue to add logs, repeated review, very time-consuming. Finally, I found the problem.

Libevent DNS resolution implementation is in the EVDNS.C this file, but if you do not understand the DNS protocol, the code may seem difficult to understand, I revisit the DNS protocol, and then start with the code.

Libevent introduces a random case concept for domain names when dealing with DNS resolution, setting Global_randomize_case to 1 by default in Evdns_base_new (), and then reading the name server configuration file according to the options To modify. There is no resolv.conf on Android, these options have no chance of being corrected, so the final global_randomize_case is still 1.

When libevent constructs a DNS request (Request_new () function), it determines, based on the global_randomize_case, whether to convert the domain name that was passed in when the DNS request was initiated, with the following code:

[CPP]View Plaincopy
  1. if (base->global_randomize_case) {
  2. unsigned i;
  3. Char randbits[(sizeof (NAMEBUF) +7)/8];
  4. strlcpy (namebuf, name, sizeof (NAMEBUF));
  5. Evutil_secure_rng_get_bytes (Randbits, (name_len+7)/8);
  6. For (i = 0; i < Name_len; ++i) {
  7. if (Evutil_isalpha_ (Namebuf[i])) {
  8. if ((Randbits[i >> 3] & (1<< (I & 7 )))
  9. Namebuf[i] |= 0x20;
  10. Else
  11. Namebuf[i] &= ~0x20;
  12. }
  13. }
  14. name = Namebuf;
  15. }

Then, when processing the results returned by the DNS server, find the corresponding request from the DNS request list according to trans_id, and compare the names parsed in the DNS results with the names in the request, and if they are inconsistent, it is considered an error. For details, refer to the Reply_parse () function, where the TESTNAME macro implements the name comparison and the original code is as follows:

[CPP]View Plaincopy
  1. #define TEST_NAME \
  2. Do {tmp_name[0] = ' + '; \  
  3. Cmp_name[0] = ' + '; \  
  4. K = J; \
  5. if (name_parse (packet, length, &j, tmp_name, \
  6. sizeof (Tmp_name)) <0) \
  7. Goto Err; \  
  8. if (Name_parse (Req->request, Req->request_len, &k, \
  9. Cmp_name, sizeof (cmp_name)) <0) \
  10. Goto Err; \  
  11. if (base->global_randomize_case) {\
  12. if (strcmp (tmp_name, cmp_name) = = 0) \
  13. Name_matches = 1; \
  14. } else {\
  15. if (evutil_ascii_strcasecmp (tmp_name, cmp_name) = = 0) \
  16. Name_matches = 1; \
  17. }  \
  18. } while (0)


This code is problematic, the global_randomize_case tag and the string comparison function do not match up, upside down. So there is a problem with the right, sometimes right, sometimes not right. Just modify it to the following code:

[CPP]View Plaincopy
  1. #define TEST_NAME \
  2. Do {tmp_name[0] = ' + '; \  
  3. Cmp_name[0] = ' + '; \  
  4. K = J; \
  5. if (name_parse (packet, length, &j, tmp_name, \
  6. sizeof (Tmp_name)) <0) \
  7. Goto Err; \  
  8. if (Name_parse (Req->request, Req->request_len, &k, \
  9. Cmp_name, sizeof (cmp_name)) <0) \
  10. Goto Err; \  
  11. if (base->global_randomize_case) {\
  12. if (evutil_ascii_strcasecmp (tmp_name, cmp_name) = = 0) \
  13. Name_matches = 1; \
  14. } else {\
  15. if (strcmp (tmp_name, cmp_name) = = 0) \
  16. Name_matches = 1; \
  17. }                           \
  18. } while (0)

A bug fix for Libevent DNS resolution on Android

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.