This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DNS query always responding NODNSREPLY

Other Parts Discussed in Thread: EK-TM4C1294XL

Hello,

I have been trying to set up a DNS client on EK-TM4C1294XL for a week now. I have recompiled NDK to support everything and tried seemingly every possible combination of the NDK modules.

I use a DHCP client to get my IP, which works well. I have successfully connected to a secure server using wolfSSL via a hardcoded IP address and I can ping my device on the local network. The only problem I have is that DNSGetHostByName() always returns NODNSREPLY (19). Although I have spent countless hours trying to find a solution or even example code to verify against, I have so far come up with nothing and am slowly getting desperate.

Below is my .cfg file, excerpts of the code I use and the Global Service Report output:

NOTE that my config file has gone through numerous changes over the past week.

/* ================ General configuration ================ */
var Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
var Error = xdc.useModule('xdc.runtime.Error');
var Log = xdc.useModule('xdc.runtime.Log');
var Main = xdc.useModule('xdc.runtime.Main');
var Memory = xdc.useModule('xdc.runtime.Memory');
var System = xdc.useModule('xdc.runtime.System');
var Text = xdc.useModule('xdc.runtime.Text');

var BIOS = xdc.useModule('ti.sysbios.BIOS');
var Clock = xdc.useModule('ti.sysbios.knl.Clock');
var Task = xdc.useModule('ti.sysbios.knl.Task');
var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
var Hwi = xdc.useModule('ti.sysbios.hal.Hwi');
var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
var Global = xdc.useModule('ti.ndk.config.Global');
var Tcp = xdc.useModule('ti.ndk.config.Tcp');
var Ip = xdc.useModule('ti.ndk.config.Ip');
var Emac = xdc.useModule('ti.ndk.config.Emac');
var Udp = xdc.useModule('ti.ndk.config.Udp');
var Dns = xdc.useModule('ti.ndk.config.Dns');
var DhcpClient = xdc.useModule('ti.ndk.config.DhcpClient');
Global.enableCodeGeneration = true;
// Global.enableCodeGeneration = {true or false};
/*
 *  Program.stack is ignored with IAR. Use the project options in
 *  IAR Embedded Workbench to alter the system stack size.
 */
if (!Program.build.target.$name.match(/iar/)) {
    /*
     *  Reducing the system stack size (used by ISRs and Swis) to reduce
     *  RAM usage.
     */
Program.stack = 2048;
}

/* ================ System configuration ================ */
var SysMin = xdc.useModule('xdc.runtime.SysMin');
System.SupportProxy = SysMin;

/* Enable Semihosting for GNU targets to print to CCS console */
if (Program.build.target.$name.match(/gnu/)) {
    var SemiHost = xdc.useModule('ti.sysbios.rts.gnu.SemiHostSupport');
}

/* ================ Logging configuration ================ */
var LoggingSetup = xdc.useModule('ti.uia.sysbios.LoggingSetup');

/* ================ Kernel configuration ================ */
/* Use Custom library */
var BIOS = xdc.useModule('ti.sysbios.BIOS');
BIOS.libType = BIOS.LibType_Instrumented;
BIOS.logsEnabled = true;
BIOS.assertsEnabled = true;

var task0Params = new Task.Params();
task0Params.instance.name = "heartBeat";
task0Params.arg0 = 1000;
task0Params.stackSize = 512;
Program.global.heartBeatTask = Task.create("&heartBeatFxn", task0Params);

/* ================ Driver configuration ================ */
var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS');
TIRTOS.useGPIO = true;
BIOS.heapSize = 90112;
Global.networkIPAddrHook = "&netIPAddrHook";
Global.stackLibType = Global.PPP_PPPOE;
Global.IPv6 = false;
TIRTOS.libType = TIRTOS.LibType_Instrumented;
Ip.DHCPOPT_NAME_SERVERS = true;
Udp.receiveBufSize = 4096;
Ip.ResolveIP = false;
Ip.dhcpClientMode = 9;
Dns.externDnsServIp = "192.168.8.1";
Ip.IfIdXValid = true;
Ip.mask = "255.255.255.0";
Ip.enableForwarding = true;
Ip.enableFiltering = true;
Ip.RestartIPTerm = true;

void getServerIPTask(UArg arg0, UArg arg1)
{
	while (1) {
            uint8_t ret = DNSGetHostByName("www.google.com", &host, sizeof(host)); // HOSTENT host is defined globally
		System_printf("RET %d\n", ret);
	    System_flush();
		Task_sleep(1000);
	}
}


/*
 *  ======== netIPAddrHook ========
 *  This function is called when IP Addr is added/deleted
 */
void netIPAddrHook(unsigned int IPAddr, unsigned int IfIdx, unsigned int fAdd)
{
    static Task_Handle taskHandle;
    Task_Params taskParams;
    Error_Block eb;

    if (fAdd && !taskHandle) {
        Error_init(&eb);

        Task_Params_init(&taskParams);
        taskParams.stackSize = HTTPTASKSTACKSIZE;
        taskParams.priority = 7;
        taskHandle = Task_create((Task_FuncPtr)getServerIPTask, &taskParams, &eb);
        if (taskHandle == NULL) {
            printError("netIPAddrHook: Failed to create HTTP Task\n", -1);
        }
    }
}


/*
 *  ======== main ========
 */
int main(void)
{
    /* Call board init functions */
    Board_initGeneral();
    Board_initEMAC();
    Board_initGPIO();

    /* Turn on user LED */
    GPIO_write(Board_LED0, Board_LED_ON);

    System_printf("Starting the example\nSystem provider is set to SysMin. "
                  "Halt the target to view any SysMin contents in ROV.\n");
    /* SysMin will only print to the console when you call flush or exit */
    System_flush();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

The auto generated Service Report code should start the DNS client when an IP address is assgined:

Void ti_ndk_config_Global_serviceReport(uint Item, uint Status,
        uint Report, HANDLE h)
{
    xdc_runtime_System_printf("Service Status: %-9s: %-9s: %-9s: %03d\n",
            TaskName[Item-1], StatusStr[Status],
            ReportStr[Report/256], Report&0xFF);

    if (Item == CFGITEM_SERVICE_DHCPCLIENT &&
        Status == CIS_SRV_STATUS_ENABLED &&
        (Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPADD) ||
         Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPRENEW)) ) {

        /* add the external DNS server to the configuration. */
        ti_ndk_config_external_dns_init(h);
    }

    xdc_runtime_System_flush();
}

And the Service Report's output:

Using MAC address in flash
Starting the example
System provider is set to SysMin. Halt the target to view any SysMin contents in ROV.
Service Status: DHCPC    : Enabled  :          : 000
Service Status: DHCPC    : Enabled  : Running  : 000
Network Added: If-1:192.168.8.108
RET 19
Service Status: DHCPC    : Enabled  : Running  : 017
RET 19
RET 19
RET 19
RET 19
RET 19

Regards,

Jaan

  • Hi Jaan,

    What version of TI-RTOS are you using?

    Todd

  • Hello Todd,
    I am using the latest one that can be installed through CCS, same for NDK. I use the newest XDC tools available because I had trouble linking the Java Runtime Environment to the makefiles, so I went ahead and got the standalone version.

    If this information is not enough, please let me know so that I can get back to you with exact version numbers when I get into the office again.
  • I am using TI-RTOS 2.14.04.31 with NDK 2.24.03.35 and XDC 3.32.00.06.
  • Hello Todd,

    I have answered your question in the thread. 

    "I am using TI-RTOS 2.14.04.31 with NDK 2.24.03.35 and XDC 3.32.00.06."

    Regards,

    Jaan

  • Sorry. I have a large backlog. Can you attach a sample project that demonstrates the problem?

    Todd
  • Hi,

    no worries. I have attached a simple project that demonstrates the problem. It is the same one that I have copied excerpts of in the OP.  I know my internet connection is fine because I got DNS to work using lwIP not too long ago. 

    In the example project I am using Google's DNS server, but I get the same results when using the local DNS server my PC uses.

    6507.dns_test.zip

  • Great. I've reproduced the issue and I'm looking into it.

    Todd
  • Can you try adding this into your .cfg file?
    Global.autoOpenCloseFD = true;

    Or call fdOpenSession() at the beginning of each task that is using the stack?

    Todd
  • Additionally you are not passing in a large enough buffer into the DNSGetHostByName API. Take a look at the API reference documentation and there is an example of it in the getaddrinfo() API in the <ndk_install_dir>\packages\ti\ndk\nettools\inet\inetaddr.c file.

    Todd
  • Hello Todd,

    thank you for getting back to me! It seems the configuration file I had attached was the only one without the line Global.autoOpenCloseFD = true; and as such the only project DNS would not work in, unmodified. It seems to work now, although I did get some errors at first. Thank you very much!

    Also worth pointing out that the h_addr fields contain pointers to IP addresses, not IP addresses themselves. From what I've read so far, this isn't intended.

    I do have one more question though.

    To use DNSGetHostByName, I include <netmain.h>. 

    I also need to use wolfSSL, for which I include either <ti/net/http/sswolfssl.h> or <wolfssl/ssl.h>. 

    And I would like to use HTTPCli aswell, since I will be using HTTPS for communication. For this I include <ti/net/http/httpcli.h>, which then includes <ti/net/network.h>, which includes libraries NDK libraries.

    Including the former gives me 20 redefinition errors, which I understand come up because some of the libraries I use use  the NDK sockets library while others use BSD socket library.

    I can use DNS with wolfSSL if I include the original wolfSSL header, or I can use HTTPCli with wolfSSL by including the TI headers, but not all three at once.

    How would I go about fixing the issue?

  • Yes. You can’t have both of those headers included in the same file. There’s some explanation on this in the NDK Reference API guide (search for BSD), but in short, BSD code should be its own file and should include sys/socket.h. Wolf code uses BSD so it can also live with NDK BSD code that needs sys/socket.h.

    Any other NDK stuff you need to do that requires netmain.h should be in a separate file. I know this isn’t clean, but it was a problem that came up in the development of the BSD support layer.

    The definition of following function would need to be in a separate file:

    void getServerIPTask(UArg arg0, UArg arg1)

    Thinking about this more, before diving into all of the above, you might also ask what is your desired goal for DNS (i.e. what will you do with the IP address once DNS resolves that host name for you?). Do you need the IP address to create a socket?

    If you just need to resolve the host name so that you can create a socket that connects to that server (Google in his example), then you should just use getaddrinfo(). It will do the host name resolution for you, and as a bonus you won’t need to factor out that DNS code into a separate file (you won’t need that DNS code at all).

    For a TCP/IPv4 connection, you would call it like this:

    struct addrinfo hints;
    struct addrinfo *results = NULL;
    memset(&hints, 0, sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    value = getaddrinfo(“www.google.com”, “<port # in string format>”, &hints, &results);

    You can then use the results struct in your socket calls.

    <see tcpEchoIPv6.c for a full example of getaddrinfo …>
  • I appreciate you taking the time to answer me in detail, thank you very much!