Simple (?) socket TCP/IP en0 problem...

I’m using QNX 6.3 on Win XP host, target is Freescale lite5200b PPC. Trying to write a simple program that will send a fixed message to another device on a small network. The significant lines of code are “sfd=socket(AF_INET, SOCK_STREAM, 0)”, “connect(sfd, (struct sockaddr *) &sa_in, sizeof(sa_in)”, and “send_bytes = send(sfd, packet, packet_data_length, 0)” which should send the message. Error checking is done after each step, with no errors being found. According to ‘send’, a total of 40 bytes are sent. But according to the destination device, nothing is received. A packet sniffer (operates in promiscuous mode) confirms nothing was sent. Through the target’s console, I can ping the successfully destination device. Sniffer detects other activity of the target, so it must be my code (I’ll be you don’t read that too often!) :smiley:

Any thoughts as to where I may be going wrong? Thanks!

Kasssa,

Any chance you can post your actual code including the error checking? That would help a great deal in diagnosing your problem.

Your calls certainly look correct as I use the exact same ones without any trouble. So without seeing the rest of the code it’s hard to tell what may be going wrong (for example you didn’t post what’s filled out in your sa_in struct that your passing to connect).

Tim

Hi Tim,

I didn’t see any other code posted in my quick glance around, so I wasn’t sure if it was ‘politically correct’ to do so. But since you’ve asked… :wink:

Thanks!

int main() {
char *packet_ptr = NULL;
int n;
int sfd;
struct sockaddr_in sa_in;

int send_bytes = 0;
int recv_bytes = 0;

memset(&sa_in,0,sizeof(sa_in));

/* AF_INET is used for internet communications */
/* SOCK_STREAM is used for connected oriented protocols */
/* IPPROTO_TCP means to use TCP at the transport layer */
//if ( (sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) {
if ( (sfd = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) {
	cout << "\nFailed to create socket; errno = " << errno << "\n";
	cout << "Error: " << strerror(errno) << "\n";
	return errno;
} else {
	cout << "\nsfd = " << sfd << "\n";
}

/* information about the machine we are connecting to */
sa_in.sin_family = AF_INET;  /* Used for internet comunications */
/* inet_addr and htons to convert the numbers to network byte order */
sa_in.sin_addr.s_addr = inet_addr(dest_ip);
sa_in.sin_port = htons(80);

/* connect to a machine before using the send and recv functions when using TCP */
/* connect to the machine specified by sa_in on the socket s */
if ( (connect(sfd, (struct sockaddr *) &sa_in, sizeof(sa_in))) == SOCKET_ERROR) {
	cout << "\nFailed to connect to socket; errno = " << errno << "\n";
	cout << "Error: " << strerror(errno) << "\n";
	return errno;
} else {
	cout << "\nConnected to socket.\n";
}

if (create_config_request() == SUCCESS) {
	packet_ptr = packet;
	print_packet();
	
	/* send data on socket sfd pointed by the buffer */
	if ( (send_bytes = send(sfd, packet, packet_data_length, 0)) == SOCKET_ERROR) {
		cout << "\nError sending the data; errno = " << errno << "\n";
		cout << "Error: " << strerror(errno) << "\n";
		return errno;
	} 
	else {
		cout << dec << "\n" << send_bytes << " byte(s) sent.\n";
	}

	print_packet();
	
	//usleep(HALF_SECOND);
	sleep(1);

	/* if recv returns greater than 0 then either an error occured, or there is no more data to be sent */
	while ( (recv_bytes = recv(sfd, recv_buffer, MAX_BUFFER_SIZE, 0) > 0 )) {
		cout << "\nReceived " << recv_bytes << " bytes of data.\n";
		//cout << "\nReceived the following data: " << recv_buffer << "\n";

		/* Purge the receive buffer for next use */
		for (n=0; n<=MAX_BUFFER_SIZE; n++) {
			recv_buffer[n] = 0;
		}
	}

	cout << "\n" << recv_bytes << " bytes received\n";

	if (recv_bytes == SOCKET_ERROR) {
		cout << "\nError receiving the data; errno = " << errno << "\n";
		cout << "Error: " << strerror(errno) << "\n";
		return errno;
	}

	if ( (close(sfd)) == SOCKET_ERROR) {
		printf("\nFailed to close the socket\n\a");
		printf("%s", strerror(errno));
		cout << "\nFailed to close the socket.\n";
		return errno;
	}
}
else {
	cout << "ERROR: create_config_request FAILED!!\n";
}
return 0;

}

God I hate cout, not only does it bloat to code to no end but it’s very hard to read ;-) Please ignore, just venting, hihi!

Make sure ip_dest is ok and not 127.0.0.1 . Check that sfd is ok before doing a send. If for example it’s set to 0 or 1, it could end up writing to stdin or stdout ;-)

Also since tcpip is a streaming protocol is good never to expect read to get the exact number of data you requested.

What’s packet_ptr for?

/* Purge the receive buffer for next use */
for (n=0; n<=MAX_BUFFER_SIZE; n++) {
recv_buffer[n] = 0;
}

Can be replace by a nice looking memset ( recv_buffer, 0, MAX_BUFFER_SIZE * sizeof( recv_buffer[0] ) );
Sorry can’t help it, I’m an environmentalist, save the cpu cycle !!!

Setting the socket to TCP_NODELAY would be a good idea as well.

Aside from that I don’t see anything else.

Hi Mario,

Thanks for your comments; glad to provide a vehicle for your venting. :slight_smile:

ip_dest has been hard coded for test purposes (char dest_ip[]=“192.168.1.40”) ;).

right now I’m just trying to see if I get anything back, so not a problem if I don’t read the entire message.

returned value for sfd is 3 - does that seem like a reasonable value?

packet_ptr is a local variable with the address of the packet I’m trying to send. Haven’t been able to figure out how to get QNX Momentics IDE to display a global var that is a char (only works for ints?), so I stick the address into packet_ptr so I can see what is in memory.

thanks for the memset suggestion. It is in a snippet that I borrowed, but I should have caught it too! :blush:

Will check into TCP_NODELAY.

I appreciate your help and suggestions!

Kasssa,

Posting code snippets is not only allowed, it’s encouraged. Many posts have snippets in them so I am surprised you didn’t find any.

The return value from sfd sounds fine.

Aside from Mario’s suggestions I have 3 other comments:

  1. Your using port 80. Is there a reason why you are using that one. I only ask because port 80 is the normal TCP/IP port for web servers. This means that many ISP’s (and IT dept’s) block this port to prevent attacks on computers. I wonder if this is happening to you in some way?

  2. Are you running as root or non-root? This is related to the port number again. Ports < 1024 are privileged ports normally requiring root access (not sure if this is true in QNX or not). Normally I pick a port far above the 1024 number for my sockets.

  3. This one’s fairly obvious, but I assume your QNX machine has an IP that is on the 192.168.1.X subnet :slight_smile: I further assume you have defined SOCKET_ERROR to be -1.

It’s got to be something silly like this because I have almost the same exact code running just fine.

Tim

YEs sfd is 3 makes a lot of sense. Utilise file handle are allocated sequentially. 0,1,2 are preallocated for stdin, stdout, stderr, so 3 is the next logical file handle number!

What does ifconfig en0 and ifconfig en1 report?

Where if the sniffer physically connected, are you using a hub or a switch?

Hi Tim and Mario,

Here is my setup: QNX Momentics IDE resides on a laptop whose ethernet port is connected to a hub; serial port of laptop is connected to Freescale LITE5200B devel/eval board. LITE5200B ethernet port is conected to same hub as laptop; (same serial line goes back to laptop). :smiley: Other device (a radio that responds to different commands causing it to send different info) is connected to the same hub. Nothing else on the network, no IT departments to worry about.

laptop=192.168.1.140, LITE5200B=192.168.1.11; radio=192.168.1.40
Using console of LITE5200B I can ping radio and laptop. From laptop I can ping LITE5200B and radio. From radio console I can ping laptop and LITE5200B.

Port 80 was an arbitrary number that I picked, based on some code snippets.

I think I’m root, but not 100% sure. The LITE5200B has been set to automatically boot the OS upon powerup; there is no login process, and it seems I can do anything. There is probably a command that will tell me who I am, but I don’t recall what it is (been a while since I’ve had to do this on unix-like systems).

It never hurts to check what should be obvious (I was Tech Support for a while). Yes to both the assumptions in 3).

ifconfig en0

en0: flags=8c43<UP,BROADCAST,RUNNING,OACTIVE,SIMPLEX,MULTICAST> mtu 1500
address: 00:04:9f:00:27:95
inet 192.168.1.11 netmask 0xffffff00 broadcast 192.168.1.255

ifconfig en1

ifconfig: SIOCGIFFLAGS en1: No such device or address

Sniffer is running on the laptop that is connected to the hub.

My OS image loads npm-tcpip.so - isn’t that what configures en0? Should I be seeing an en1? LITE2500B only has a single ethernet port on it…

I just tried TCP_NODELAY and it did not appear to make a difference.

I really appreciate your help - thanks!

OK. Nothing unusual about this setup since you can ping and use telnet to get access to the LITE5200B board from the laptop.

Question: Who made the radio your trying to connect to? Are you sure this Radio is actually listening on port 80 for someone to connect? If there isn’t code in the radio listening on port 80 your never going to successfully connect to it with the connect command.

I am not sure what you mean by there is no login process. Somehow your able to get a command terminal on the LITE5200B board. What does the command prompt look like? Is it a $ or a #? A # would indicate you have root privileges.

The above looks good as it displays the TCP/IP correct address. There will be no en1 since you only have 1 ethernet card so the error there is also normal.

OK, I went into my test code which looks like yours other than the port being different. It still works. But I did notice a couple of things:

  1. If my remote side is ‘down’ the connect call hangs for a while before returning with no remote side. A while being more than a few seconds. Do you actually see any of the printf’s/couts printed after the connect call. I ask only because it might be possible the remote side has not yet answered the connect and your still waiting for that to occur. Can you try running your code with the radio turned off and letting it sit for a bit to see if the connect times out properly. Just curious as to what happens for you.

  2. Can you change your IP address to be that of your laptop instead of the radio. Then run the code. I bet Windows refuses the connection right away since I don’t think you have anything running on port 80 (unlikely). I am curious to see what the connect does then in your code.

  3. When you run your sniffer, are you able to see the connect packets being sent from the LITE5200B board to the radio? These should be sniffable as well as your data packets. What about sniffing while you attempt to connect to the laptop?

As far as send goes, if you read the doc’s on it (I just re-read them) you only get an error if there is an internal failure in QNX. There is no way for send to return an error if the packet fails to be sent by the hardware for example. So all that send does is tell you that the 40 bytes were delivered to the TCP/IP stack (npm-tcpip.so). Now I don’t believe you have a hardware failure or else you would not be able to telnet into the LITE5200B board (you are telneting in and not coming in on the serial line, right? Why IS that serial line connected to the board?)

Tim

Are you 100% I say 100% sure it’s a hub and not a switch. Switch are so cheap these day it’s hard to find a hub :wink: If it is a switch, all the pings, telnet, etc would work but you won’t be able to sniff anything. As a matter of fact can you sniff the ping between the QNX machine and the radio node.

You can’t pick and arbitrary number, it’s the server side that decides which port are available. In that case the radio node must make port 80 (funny cause port 80 is typically for http request) available for incoming connection and once the connection is made something must read th data and respond accordingly. If port 80 is waiting for connection (let’s say inetd) you will be able to connect to it, but if inetd start a process which isn’t reading incomming data you will get the exact same behavior you are seeing (minus not seeing anything with the sniffer. To test if your application is the problem or if it’s the set, from the QNX system run telnet 192.168.1.40 80. This will basicaly do the same thing as your program. Once the connection is made type 40 characters (size of your send buffer) and see if telnet receives something, the problem is your app. If it receives nothing (and I pretty sure that is what is going to happen) the problem is NOT in your program.

You program will work root or not.

I asked for en1 just to check if there was not another device where connection could be made over.

I suspected that, but never hurts to put it there.

I appreciate that you appreciate :wink:

Here is some more info based on some of the questions asked…

I think 80 is the correct port - will try to verify it with somebody. With the radio on, it takes maybe 15 seconds for my program to print its debug messages. With the radio off, after 60+ seconds it times out (errno 260), failing to connect to the socket. Just for grins, I tried using port 23 (telnet), and I did receive back the radio’s telnet prompt! I think I’m excited by that, but I still have to digest exactly what it means! :smiley:

I connect from the laptop to the LITE5200B via the serial cable, I’m NOT telneting. The serial line is being used as the “console” for the LITE5200B. The LITE5200B is my “QNX machine”, and telnet is not part of the current OS image. Maybe it should be…

The LITE5200B allows me to enter ksh commands, and uses the “#” prompt. When I fat-finger something, I see the “ksh: fat-finger: not found” error.

The device I’m calling a hub is a Linksys “10/100 5-port Netwrok Hub”, Model NH1005 Ver 2.0. I don’t know what is inside, but Linksys is calling it a “hub”.

I need to check more with the sniffer. It looked like when I did a ping from the LITE5200B to the radio, the sniffer saw a broadcast message from the laptop (based on IP addresses), but none of the pings. That has me rather confused. It looks like the sniffer isn’t seeing anything coming from the LITE5200B going to the radio, but the radio is responding to the ping (I realize it is done in the hardware). The sniffer is seeing messages going from the LITE5200B to the laptop.

Time for more head scratching!

Then maybe the problem is simply that what ever you are sending on port 80, is ignored by the device and it’s not sending anything back.

The broadcast must have been an ARP request. It seems that sniffer isn’t working right :wink:

What do you mean done in hardware?

Looks like it isn’t really in promiscuous mode. If it’s an old laptop with old network card it’s possible promiscuous is not supported.

Kasssa,

The fact that your code is able to get the telnet prompt on port 23 tells you that your code is fine (which I always thought was the case looking at it). It also tells you that the radio is running a telnet application on port 23 which is why it responds to your connect.

Now the fact that nothing happens on port 80 tells you that the radio is running no application on port 80 (something Mario alluded to a couple of posts above and again in his last post). Pictorially it looks like this:

LITE5200B                                               Radio
                                     port 23
(your app) (tcp/ip layer) ---------- (tcp/ip layer)  (telnet)

                                     port 80
(your app) (tcp/ip layer) ---------- (tcp/ip layer) 

So what happens is on port 23 the telnet app responds to the connect request and sends the telnet prompt to you.

On port 80, the connect request is accepted by the TCP/IP layer on the radio but there is nothing to pass the packet to (or if there is some app there is does not respond to the packet). So the connect succeeds and you send the packet but there is no response.

When the radio is turned off you see the connect fail due to the radio not being there.

So the question remains, what are you expecting to find on port 80 on the radio? Do you have any doc’s on the radio that tell what applications are running on what ports? That’s where you need to look now.

I also assume your ‘sniffer’ is just etherereal. Is this correct?

Mario,

By done in hardware I think Kasssa means that the ping response is done by the ethernet card on the radio without intervention by the radio’s TCP/IP stack.

As for not being able to sniff the packets I would once again suspect he’s on a switch and not a hub. That’s why he see’s the arp request packet on the laptop when the LITE5200B attempts to connect but no subsequent packets because the arp is broadcast everywhere by the switch but not the connects. It’s also why he can sniff the packets back and forth between the LITE5200B and the laptop.

Tim

Hi Mario and Tim,

Sorry for the delay - had to get some other work done! :slight_smile:

I’m working on trying to verify the port I need to send to. I agree and understand that since sending something to port 23 gets a response, but sending something to port 80 doesn’t, so port 80 must not be the correct one for my purposes.

Sniffer may still be an issue - along with the “hub” I’m using. Oh, the sniffer is “WireShark”, but I may be switching over to “ethereal” since more people seem to prefer it (must be a reason!). Will check Linksys info to see if they identify it as a switching hub. Interesting comment at ethereal.com/faq.html#promiscsniff - “Note also that on the Linksys Web site, they say that their auto-sensing hubs “broadcast the 10Mb packets to the port that operate at 10Mb only and broadcast the 100Mb packets to the ports that operate at 100Mb only”, which would indicate that if you sniff on a 10Mb port, you will not see traffic coming sent to a 100Mb port, and vice versa. This problem has also been reported for Netgear dual-speed hubs, and may exist for other “auto-sensing” or “dual-speed” hubs.” All my nodes are 100Mb, but reading this makes me wonder about the hub I’m using.

Correct - by “done in the hardware” I mean the ethernet card card does it, without having to be handled by application software.

Did notice one small bug in the software. When I’m receiving data back, the value assigned to recv_bytes was wrong. It was being set to 1, which was the result of the logical > comparison between recv(…) and 0! A couple of matched parentheses in the right places redefined the precedence of that line of code! :smiley:

Will check into the radio’s ports and see what I can find out.

Also just did a quick check of Linksys’ website - no mention of a NH1005 hub. googling around leads me to believe that you’re both right about it being a switch. So much for my sniffing! :imp:

Thanks for your thoughts, suggestions and interest. At this point I’m concluding that finding the right port will take care of most of my problems… :smiley:

kasssa.

If you talk about the command line program ping, no it’s not handle by the ethernet card. It’s handle by the tcp/ip stack.