• Please review our updated Terms and Rules here

DNS query packet problem?

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
i just implemented UDP in my QB TCP/IP code, and then i started working on DNS resolution over UDP. i'm having an issue though.

i've followed the format that i've found for DNS query packets online, checked a few pages on it. the server always sends back a malformed request error. can anybody give me some good info on it??

i even used wireshark to capture my windows box sending a DNS request for google.com .... i had my QB code send out the same packet byte for byte, and i still get that error!! :confused:

(i was considering posting this in the programming forum, but it has nothing in particular to do with vintage programming... so here it is)
 
It's vintage programming to me .. you are using QB. I moved it to programming where it belongs.

You need packet dumps .. that's the only way to debug something like this. DNS is brutal compared to the other protocols.

By coincidence last night I cleaned up my DNS name resolver and made it usable for normal people from the command line. It has a trace mode that might help you figure out what the packets look like. I was going to post a 12-30 version of my tools this morning anyway, so it will be ready shortly.

You can also send me your code, if it is somewhat readable.
 
Last edited:
ahh, thanks for the responses guys.. but i figured it out. sorry for the waste of space thread. after hours of going over and comparing the packets from my code and from windows DNS queries, i finally noticed that the dots in hostnames were not actually transmitted as dots.

it looked they were changed to a byte who's value represented how many characters until the next dot (or end of the string if no more dots), and finally terminated with a null byte. (although i already knew it was null terminated) -- i made the fix to my code, and voila! i had DNS resolution.

all works fantastic now! :)

strangely enough, not a single protocol doc i read mentioned this.. or maybe i am too daft to notice. :eek:

to give the code a hearty test, i wrote a little WGET clone for DOS which worked... then i decided to make something a little more serious, and wrote a small HTTP proxy. no issues so far. (on the subject, 8088s seem to not make a very good web proxy. go figure. although it works, i'm posting this message through it.)
 
Last edited:
You are too daft to notice .. it's been like that since day one.

The other thing you have to be careful about is the name compression. The spec allows 'pointers' so that instead of transmitting 'www.brutman.com' and 'mail.brutma.com', it can transfer 'www.brutman.com' and 'mail', with a 1 byte pointer to 'brutman.com' in the first string.

http://www.tcpipguide.com/free/t_DNSNameNotationandMessageCompressionTechnique-2.htm

It took me days to get my DNS resolver working. If you want to make sure your code is good turn off the 'recursion desired' bit - that causes it to bounce around to multiple name servers for each request, each with a new trick up their sleeve. Also try a variety of names, including aliases for existing names so that you can play with canonical names. And don't forget servers in different countries and well known servers like www.ibm.com and www.cnn.com.

I can not describe the fit I threw when some @$%@$ gave me back an IPV6 record that I wasn' expecting. That was a hoot.
 
And you know, it is harder than it looks.

I just found a bug in my code that was on the 'Dont use recursion' path, which is interesting but not used often. (My compiled code doesn't used it, but I have it available for stress tesing.)

The bug is fixed now and I think the code is better than ever, but even after a few months of thinking that I had everything working I still have bugs floating around.


Mike
 
And you know, it is harder than it looks.

I just found a bug in my code that was on the 'Dont use recursion' path, which is interesting but not used often. (My compiled code doesn't used it, but I have it available for stress tesing.)

The bug is fixed now and I think the code is better than ever, but even after a few months of thinking that I had everything working I still have bugs floating around.


Mike

yes, i already turned off recursion. when i used it, sometimes i'd get back weird results. since turning it off, it's worked perfect every time.

also mike, have a question. i know you aren't going to release mTCP source code any time soon, but is there a way to maybe compile it as an OBJ that can be linked in with QB EXEs?

i could give it a good workout.
 
Actually, the 'Recursion Desired' bit is a good thing. That tells the nameserver to do more work for you, and to hide the extra work. Your quickest queries will be done with this bit turned on. And it also limits your exposure to bugs in your own code by making it do less.

I turn it off when I test to burn the hell out of my code. With the recursion desired bit turned off, the first nameserver can do things like send you the name of the nameserver you need to contact, but not provide an IP address for it. Then you have to send another query to get the IP address to contact that nameserver. And then that nameserver will pass you to another nameserver. You get the idea ... A simple packet send and receive can wind up to more than 7 or 8 requests.


also mike, have a question. i know you aren't going to release mTCP source code any time soon, but is there a way to maybe compile it as an OBJ that can be linked in with QB EXEs?

I know how to package the multiple OBJs into a Turbo C++ library. The library can then be used like a giant OBJ file that you can link other code against. I can do that now.

The thing I don't know how to do is how to make it callable/linkable from a non Borland language. I know that within the Borland products you could link different languages together if you followed a few rules. But I don't know if they had interoperability with Microsoft products, and I seriously doubt it. If you do the legwork to tell me if this is possible that will save me some time.

Lastly, there is the possibility of a TSR interface. And I think that's a desirable thing to do, because that essentially makes it callable from anywhere. But the TSR interface has some drawbacks:

  • I have to strip the tracing code out. That's a shame, because the tracing code has been a real help in debugging. (Although it's not used for debug too often anymore.)
  • I have to change the startup code quite a bit to not allocate memory. Memory allocation would have to be done by the user and passed to the library.
  • Performance is going to suffer a bit. The software interrupt mechanism is not exactly high performance compared to a direct call/return.
  • There is a lot of additional work to take every C++ entry point and make a TSR entry point/routing function for it.

If you did an application in Turbo C++ I could give you a library in a day - I just need to clean the header files up. You could have the full library with tracing and all of the performance tomorrow.

Do the legwork to see how MS languages interact with Borland Turbo C. I'll do the same. I was thinking of starting an FTP client next because I think there is a lot of need for that, but getting you coding with this library would be a good thing too.


Mike
 
that sounds awesome.. thanks. after a little googling, borland C++ OBJ should work fine with QB. it's a standard format. even if for some reason, it doesn't work. i have Turbo C++ 3.0 installed, and i'm ready to start working with that.

thanks again. this will also be good for your bug testing, to have somebody else run it extensively.

as far as your FTP client idea, i like it. there already is one that uses wattcp, but it is riddled with bugs. it gets the job done, but it's not pretty. i honestly think whoever programmed it was drunk.
 
Last edited:
Without going too far off topic on this thread ...

It looks like the OBJ and LIB files that all of the compilers of the era use is in OMF format. So in theory, we can link C and QB code. The devil is in the details though:


  • Parameter ordering. I think this can be fixed easily using keywords to specify the ordering needed
  • NEAR vs. FAR pointers - Not quite sure how this is going to work yet.
  • C runtime and QB runtime - both of these runtimes will have to be linked in.

I think we're going to have to start small first by seeing if we can make QB call a C function in a LIB. The C function will do some fun stuff, like call the C runtime and make a few other calls. If we can make that work reliably then we can move to the full TCP/IP API.
 
Without going too far off topic on this thread ...

It looks like the OBJ and LIB files that all of the compilers of the era use is in OMF format. So in theory, we can link C and QB code. The devil is in the details though:


  • Parameter ordering. I think this can be fixed easily using keywords to specify the ordering needed
  • NEAR vs. FAR pointers - Not quite sure how this is going to work yet.
  • C runtime and QB runtime - both of these runtimes will have to be linked in.

I think we're going to have to start small first by seeing if we can make QB call a C function in a LIB. The C function will do some fun stuff, like call the C runtime and make a few other calls. If we can make that work reliably then we can move to the full TCP/IP API.

as far as the pointers, do you mean QB supplying a far pointer to a data buffer for the call? if so, that's no problem. VARSEG() and VARPTR() return that info. i can also read data from any far pointer C returns, using DEF SEG and PEEK.

linking the two runtime libs are not a problem either. let me know when you have the test lib ready to try and i'll give it a go. atm, i am looking at the TCPACKET stuff from your site. it's neat. there isn't too much code, but i wouldn't expect there to be. packet drivers don't really do much other than send and buffer data, leaving you to do the hard stuff like encapsulation protocols.
 
ChuckG pointed out an interesting problem in a response he sent on the classiccmp mailing list. While linking is technically possible between the OBJs created by the two different toolchains, there will probably be name collisions that will be difficult to fix.

Besides my LIB I use the C runtime, so I need to provie the LIBs that my compiler comes with. My function names probably won't cause any collisions, but the C runtime functions like sprintf, malloc, atoi, getenv might be a problem. Even though you have Visual BASIC there is a good possibility that we will have collisions, as I'm betting VB is programmed in MS C.

So we have three approaches for doing this ..

  • Program in Turbo C++ and use my LIB directly. This means you have to learn C/C++ but we won't have any compiler or linking issues to worry about. And I don't have to do any work or change the library in any way.
  • Try to link my LIB with the Microsoft OBJs you create. Technically possible, but it might be a royal pain to resolve name collisions. And I probably have to write a wrapper for every function using extern "C" so that it is callable from other languages. (Tedious, but possible)
  • Wrapper my code in a TSR. This makes it open for everybody to use, but also significantly changes the code. From a maintenance standpoint this is least likely to happen.

I'll give you a sample LIB that calls some common C runtime functions that I use. I'll also give you the C runtime that goes with it. We'll see how big the name collision problem is going to be.

I still think you should take a shot at learning C. You've got the compiler already. You'd have a known good working libary to work with, access to technical help, and better capabilities overall.

Given a choice of things to do next, I'd rather be working on a usable FTP client.
 
yeah, that is a PITA. well let me try the sample lib, we'll see how it goes. if there are any issues, i'll just sit down and start working with it in C.
 
I posted a test library, a driver program, and the runtime libraries to test with at:

http://www.brutman.com/modtest.zip

The test library prints out the incoming parameters (a far pointer, a 16 bit int and a 32 bit int), allocates and deallocates some memory, prints some status, and returns a return code.

If anybody else wants to try to link QB objs against the library and call the library routine, give it a shot ..


Mike
 
I posted a test library, a driver program, and the runtime libraries to test with at:

http://www.brutman.com/modtest.zip

The test library prints out the incoming parameters (a far pointer, a 16 bit int and a 32 bit int), allocates and deallocates some memory, prints some status, and returns a return code.

If anybody else wants to try to link QB objs against the library and call the library routine, give it a shot ..


Mike

no, it looks like it can't link. it doesn't like ccmodule.lib

oh, well... it was worth a try. thanks for the effort. i'm still down with working mTCP in C++!! last night i spent about an hour just messing around in TC, compiled a couple simple little programs that i wrote successfully without documentation... it's a start.

actually having a goal for a program is going to be the best way for me to get motivated to learn it properly lol. my thought is start with something simple involving your library, and i'm thinking a small DOS wget clone.

whenever you can get it uploaded, i'll start working with it. thanks, mike!
 
I'll get the real LIB packaged up in the next few days. I'll also put some sample code in there to get you started on wget.

Just out of curiosity, what did you try and how did it fail? You had both an OBJ and a LIB to work against - did you try the OBJ too?
 
I'll get the real LIB packaged up in the next few days. I'll also put some sample code in there to get you started on wget.

Just out of curiosity, what did you try and how did it fail? You had both an OBJ and a LIB to work against - did you try the OBJ too?

awesome, thanks mike. and yes, i ran BC.EXE to compile my test code to my own OBJ:

Code:
DECLARE FUNCTION moduletest% (BYVAL farp%, BYVAL num1%, BYVAL num2&)

PRINT "Trying to call C++ module..."
returncode% = moduletest(&HB800, 1, 2)
PRINT "Tried to call... test module returned:" + STR$(returncode%)

then i ran LINK.EXE and supplied my OBJ plus all of yours to it, along with BCL71EFR.LIB and all of your libs. it didn't like ccmodule.lib, but it can't compile without it of course because then it's missing code it needs. i always like to include BCL71EFR.LIB because it's the runtime, that way it's built into EXE and i don't need to include a separate EXE.
 
Back
Top