Help With TCP/IP

Yikes! I posted this just a few minutes ago. The code fails on 6.3.2. But after correcting a few compiler isms, it works correctly under 6.4. As it turns out the target for this code is 6.5 so I’m ok, but does anyone have any idea what is going wrong on 6.3.2?


Maybe someone can look over my shoulder with this basic TCP/IP problem I’m having.

The code attached should make TCPdaytime without any errors. The code is copied almost exactly from Comer and Steven’s classic “Internetworking with TCP/IP VOlume III/BSD Socket Version”.

Basically the code sets up a socket, listens, and then runs accept. Accept fails every time with a bad-file errno. If you put in a sleep before the accept, and you run “netstat -a” you can see a perfectly good socket listening on the port.

I’m almost 100% sure that I entered this code and had it working a year ago, so I’m baffled. I’ve run it on two different machines so it probably isn’t some local config thing either.

Thanks for any help.

No attached code to be found.

Hmmm, was sure I added it. Try #2 coming up.

maschoen,

I initially got the same error you did.

When I printed out errno it reported 13 - no access

Running again as root worked fine.

Then I looked closely again at the port number you are trying to bind to which also happens to be 13. Then I remembered that port numbers <1024 are privileged ports requiring root access (in fact in the passiveport.c file there is a comment about using non-root ports).

I guess the privileged ports access was relaxed in 6.4/6.5.

Tim

Tim,

 What version of QNX are you running?  My results were different.   I was always running as root.   If you give the program a parameter, it uses it as a port.  If I gave port 2000 it still failed.   Also, the error I got was not "no access" it was BADF or bad file descriptor.  This happened on two different QNX 6.3.2 systems.

Mitchell

It fails if compiled with 3.3.5, if compiled with 2.95 it’s ok. However if I run the bad binary on 6.4.1 ( build on 6.3.2) I get error 79 and not 9.

This seems simple enough, don’t understand what is going on.

Will do more test later.

Masochen,

QNX 6.3.0 SP3 which is “technically” the same as 6.3.2. Technically meaning they are supposed to be the same minus a few SMP kernel options and the fact the libraries were re-compiled for 6.3.2 (I know this because we have 6.3.0 SP3 code that won’t run on 6.3.2 without being recompiled).

I ran again in user mode and specified a port of 2000 and the program runs just fine with no errors since I am not using a privileged port.

Mario,

I was building with 2.95.3 (default compiler). I went and changed the Makefile to use 3.3.5 (note that by changed I completely dropped the ar command and manually specified everything in order to manually select the 3.3.5 compiler + linker + dinkum libraries).

It still works for me if I specify a port of 2000.

So maybe there is a bug introduced in 6.3.2 (ie they forgot to recompile the socket library for 3.3.5) that isn’t in 6.3.0 SP3 or 6.4/6.5?

In any case it’s clear the problem is 6.3.2 related and has nothing to do with tcp or the sample program.

Tim

Tim,

What I find odd is that we have many 6.3.2 systems that do the same logic and are working just fine.

I did more work and have solved the problem, sort of. When I previously stated that it worked under QNX 6.4, I was hedging a bit. To get it all to compile on QNX 6.4 I had to make a few changes. I had to include a

typedef unsigned short u_short;

I also needed a couple other include files. When I re-did this all carefully, it started failing again.

However I found this time that if I entered a service with 5 or less characters, it worked. Hmmmmm! After lots of trial and error I found that if I put a buffer here:

TCPdaytimed.c


struct sockaddr_in fsin;
char safety_buffer[xx]; ← HERE
char *service = “daytime”;

I could get it to work. Strangely enough for QNX 6.4 I needed only about 32 bytes, but for QNX 6.3.2 132 bytes. This suggests that accept() really wanted a sockaddr, not a sockaddr_in. Here’s the funny part. Look at
/usr/include/sys/socket.h:

struct sockaddr {
_Uint8t salen; /* total length /
sa_family_t sa_family; /
address family /
char sa_data[14]; /
actually longer; address value */
};

Isn’t that cheery. “ACTUALLY LONGER”. Does that mean designed to fail?

Ok, but now I see the right solution. If you set alen=sizeof(struct sockaddr_in) before calling accept, it now works.

So I guess there really isn’t anything wrong except for Comer and Stevens code. Out of date might be better. I’m guessing this is related to things like V6?

Thanks to all who looked over my shoulder.

By the way Mitchell I`ve become a big fan of the C++ Poco library. It make dealing with Sockets SO MUCH easier.