LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices


Reply
  Search this Thread
Old 03-15-2008, 05:48 PM   #1
stees
Member
 
Registered: May 2006
Distribution: OpenSuse 11, Red Hat, Fedora
Posts: 34

Rep: Reputation: 15
Why is recvfrom() buffer null when bytes are received ?!!


Ok. Long story short.
I am programming a TFTP server.
The server is awaiting the WRQ/RRQ packet.

I connect with a client and request to write (WRQ).

The recvfrom() returns 14 bytes received.
But when I try to read what's in the buffer it is blank.

This is the call:
Code:
recvd = recvfrom(socket,buf,BUFFER_SIZE,0,(struct sock_addr *) &client, &client_len);
if ( recvd > 0 ) {
   printf("[LOG] PACKET RECVD: %d bytes from [%s:%d]\n--PACKET CONTENTS=[%s]\n", recvd,inet_ntoa(client.sin_addr),ntohs(client.sin_port), buf); //--- buf seems to be NULL on printf()
   pbuf = buf; //--- pointer to buf[0]
   pbuf++;     //--- increment to buf[1]
   char pkt_head = *buf;
   char this_op = *(buf+1);
   char that_op = *(char *)pbuf;
   printf("      opcode=[%c - %c - %c] ...\n", pkt_head,this_op,that_op);
   ...
   ...
}
my buffer variable, buf, is defined as:
Code:
typedef char String[MAX_STRING];
String buf;
As you can see from above, I tried printf, sprintf (omitted), and even pointers to buf[0] and buf[1]

All are blank. Any ideas?
I need to read the buffer so I can grab the opcode of the TFTP packet.

Thanks.

Last edited by stees; 03-15-2008 at 05:50 PM. Reason: grammar
 
Old 03-15-2008, 09:31 PM   #2
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
First, are you sure the buffer is full of ASCII NUL? The way you’re testing, it might come out as non-printable characters. Also, the values are most likely non-NUL prior to the call (you can even check what the values are prior to and after the call). Also, check numerical values rather than trying to print the textual values (unless of course you want to pipe to od or something):
Code:
#define CANARY "\xde\xad\xbe\xef"

typedef char String[MAX_STRING];
String buf = CANARY CANARY CANARY CANARY;
char *t;

printf("Initially, buf is 0x");
t = buf;
while(t < buf+14)
	printf("%hhx", *t++);
printf("\n");

recvd = recvfrom(socket,buf,BUFFER_SIZE,0,(struct sock_addr *) &client, &client_len);
if ( recvd > 0 ) {
	printf("[LOG] PACKET RECVD: %d bytes from [%s:%d]\n--PACKET CONTENTS=[0x", recvd,inet_ntoa(client.sin_addr),ntohs(client.sin_port));
	t=buf;
	while(t < buf+14)
		printf("%hhx", *t++);
	printf("]\n");
}
 
Old 03-16-2008, 02:08 AM   #3
stees
Member
 
Registered: May 2006
Distribution: OpenSuse 11, Red Hat, Fedora
Posts: 34

Original Poster
Rep: Reputation: 15
Thanks for your help. I eventually figured it out.
I ran a for loop to spit out the contents of the buf array.
[where 'int i < recvd' from the recvfrom()]

I printf'd each buf[i] as both a '%u' and a '%c'.
The '%u' showed every byte of the packet. While '%c' was only populated on certain bytes like the transfer mode and filename.

So I guess I might have confused myself by typecasting 'buf' to a String?
I'm saying this because 'buf' doesnt printf as '%s', but each element in the 'buf' array will printf as a single '%u' or '%c'.

I wasn't quite following what you meant by ASCII NUL.
Perhaps these are those elements in the 'buf' array that did not print as '%c' but would print as '%u'?

As far as values being not-NUL before the call...
Is this why you would see a memset() being called to 'clear' a variable because when C allocates memory for that variable, that memory location may already have data there?

Last edited by stees; 03-16-2008 at 02:11 AM. Reason: grammar
 
Old 03-16-2008, 01:04 PM   #4
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Quote:
Originally Posted by stees View Post
I printf'd each buf[i] as both a '%u' and a '%c'.
The '%u' showed every byte of the packet. While '%c' was only populated on certain bytes like the transfer mode and filename.
There is a difference between printable and non-printable characters. In C, char is an integer type, but it is wide enough to hold a character from a basic charset (usually 8 bits and usually representing some superset of ASCII). Some of these characters have a glyph when printed, others have some other meaning when printed, and others don’t have any effect on modern-day hardware.

For example, in the following code (under an ASCII-compatible locale):
Code:
printf("%c", 65);
printf("%c", 10);
printf("%c", 1);
The first statements prints the character ‘A’. The second statement does not print a character, but moves the cursor to the beginning of the next line (because in ASCII 10=='\n'). The third statement has no visible effect. You can use the standard C function isprint() to determine whether or not a particular character prints in your locale.
Quote:
Originally Posted by stees View Post
I wasn't quite following what you meant by ASCII NUL.
Perhaps these are those elements in the 'buf' array that did not print as '%c' but would print as '%u'?
In C “strings” are terminated by the NUL character ('\0') which is semantically different from the NULL pointer (even though they will evaluate to the same value—0—in many situations). For example, suppose I have the following code:
Code:
char buf[] = "Hello\0 World!\n";
//char buf[] = {'H','e','l','l','o','\0',' ','W','o','r','l','d','!','\n','\0'};
//char buf[] = {72,101,108,108,111,0,32,87,111,114,108,100,33,10,0};
printf("%s", buf);
The two commented lines are equivalent to the first line. The output of the above code is just “Hello” (since the string-expecting printf will stop output when it encounters the first '\0').
Quote:
Originally Posted by stees View Post
As far as values being not-NUL before the call...
Is this why you would see a memset() being called to 'clear' a variable because when C allocates memory for that variable, that memory location may already have data there?
With automatic storage, you always already have data there. It is not specified what this data is (but it’s usually stack space, so it may have remnants of previously-called functions). So if you want to be sure there is a specific value, you initialize it to something (like the CANARY in my other post). If you specifically allocate memory, or if your buffer is large, you might want to use memset(). Only if you use static storage is your data guaranteed to be initialized to zero upon first use.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
C: convert char buffer received from socket to host endianess buffer kpachopoulos Programming 3 06-07-2007 05:06 PM
Fatal error: Allowed memory size of 15728640 bytes exhausted at (null):0 (tried to al Niceman2005 Linux - Software 0 03-07-2007 02:15 AM
No of bytes in the serial drivers transmit buffer igjesdal Programming 0 10-13-2004 10:58 AM
NULL buffer in read sys call unpredictable jwstric2 Programming 3 09-02-2004 07:13 PM
Determining sent/received bytes ? Stingreen Linux - Networking 8 06-06-2002 07:20 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 03:30 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration