2001-07-08 16:15:05

by Adam

[permalink] [raw]
Subject: recvfrom and sockaddr_in.sin_port


hello,
I'm using recvfrom, and upon return it should fill in
from argument with sockaddr_in data structure. from
ip(7) man page I get that it has format of :

struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
u_int16_t sin_port; /* port in network byte order*/
struct in_addr sin_addr; /* internet address */
};

for PF_INET type of socket. Now if I run the program the, data in
the from field comes out as:

2 0 0 0 192 168 1 4 61 63 140 200 85 214 2

| | |

AF_INET :2
IP :192.168.1.4

and as show in above example and other repeated test, the port
part is always set to 0. Shouldn't that be set to port number?

on similar token the "padding" part after the IP is always set
to the same pattern. Shouldn't it rather be zeroed, or be
some random data?

I have attached a simple program I used for generating those
results.

--
Adam
http://www.eax.com The Supreme Headquarters of the 32 bit registers


Attachments:
test.c (1.67 kB)

2001-07-08 17:06:29

by Chris Wedgwood

[permalink] [raw]
Subject: Re: recvfrom and sockaddr_in.sin_port

On Sun, Jul 08, 2001 at 12:14:47PM -0500, Adam wrote:

I have attached a simple program I used for generating those
results.

'fromlen' needs to be set to sizeof 'from' before the recvfrom syscall



--cw

2001-07-08 17:08:59

by Adam Sulmicki

[permalink] [raw]
Subject: Re: recvfrom and sockaddr_in.sin_port

> I have attached a simple program I used for generating those
> results.
>
> 'fromlen' needs to be set to sizeof 'from' before the recvfrom syscall

isn't it set? to quote from the example I have attached:

socklen_t fromlen = sizeof(struct sockaddr_in);



2001-07-08 17:21:29

by Chris Wedgwood

[permalink] [raw]
Subject: Re: recvfrom and sockaddr_in.sin_port

On Sun, Jul 08, 2001 at 01:08:37PM -0500, Adam wrote:

isn't it set? to quote from the example I have attached:

socklen_t fromlen = sizeof(struct sockaddr_in);

sorry, I misread the source (the memset line)

you are using raw sockets, what does port mean for raw sockets?



--cw

2001-07-08 17:42:44

by Adam Sulmicki

[permalink] [raw]
Subject: Re: recvfrom and sockaddr_in.sin_port

> isn't it set? to quote from the example I have attached:
> socklen_t fromlen = sizeof(struct sockaddr_in);
> sorry, I misread the source (the memset line)
> you are using raw sockets, what does port mean for raw sockets?

well, from raw(7) man page:

raw_socket = socket(PF_INET, SOCK_RAW, int protocol);
[...]
All packets [...] matching the protocol number speci
fied for the raw socket are passed to this socket.

so it seem to imply that only tcp packets only are to be passed.
still group "SOCK_RAW" is subset of the PF_INET group (the way
I see it), so from ip(7) man page I should use sockaddr_in
structure, which should be defined in this particular case,
as it ought be for IPPROTO_UDP.


2001-07-08 18:31:49

by Chris Wedgwood

[permalink] [raw]
Subject: Re: recvfrom and sockaddr_in.sin_port

On Sun, Jul 08, 2001 at 01:42:28PM -0500, Adam wrote:

so it seem to imply that only tcp packets only are to be passed.
still group "SOCK_RAW" is subset of the PF_INET group (the way
I see it), so from ip(7) man page I should use sockaddr_in
structure, which should be defined in this particular case,
as it ought be for IPPROTO_UDP.

have you dumped the packet contents? presumably its a raw packet,
protocol 6, and the header and such like is returned

i see no reason, for raw packets to fill out sin_port whatoever, it
just doesn't make sense that raw packets have a port



--cw



2001-07-08 19:28:52

by Andi Kleen

[permalink] [raw]
Subject: Re: recvfrom and sockaddr_in.sin_port

Adam <[email protected]> writes:
>
> and as show in above example and other repeated test, the port
> part is always set to 0. Shouldn't that be set to port number?

SOCK_RAW has no ports, so no.

>
> on similar token the "padding" part after the IP is always set
> to the same pattern. Shouldn't it rather be zeroed, or be
> some random data?

It should stay at the old value or alternatively be zeroed. That's a
kernel bug.

Here is a patch that implements the first alternative. David, please consider
applying.

diff -burp linux/include/linux/in.h linux-work/include/linux/in.h
--- linux/include/linux/in.h Thu Jul 5 13:18:27 2001
+++ linux-work/include/linux/in.h Sun Jul 8 19:05:30 2001
@@ -109,6 +109,10 @@ struct in_pktinfo
};

/* Structure describing an Internet (IP) socket address. */
+/* Note here and in others places is the assumption made that there
+ are no holes in in this structure. This is ok for all architectures
+ which layout structures members at worst to their natural
+ alignment. -AK */
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
struct sockaddr_in {
sa_family_t sin_family; /* Address family */
@@ -119,7 +123,7 @@ struct sockaddr_in {
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
-#define sin_zero __pad /* for BSD UNIX comp. -FvK */
+#define sin_zero __pad


/*
diff -burp linux/net/ipv4/af_inet.c linux-work/net/ipv4/af_inet.c
--- linux/net/ipv4/af_inet.c Wed Jul 4 17:21:32 2001
+++ linux-work/net/ipv4/af_inet.c Sun Jul 8 19:05:31 2001
@@ -729,7 +729,7 @@ static int inet_getname(struct socket *s
sin->sin_port = sk->sport;
sin->sin_addr.s_addr = addr;
}
- *uaddr_len = sizeof(*sin);
+ *uaddr_len = sizeof(offsetof(struct sockaddr_in, sin_zero));
return(0);
}

diff -burp linux/net/ipv4/raw.c linux-work/net/ipv4/raw.c
--- linux/net/ipv4/raw.c Wed Jul 4 17:21:32 2001
+++ linux-work/net/ipv4/raw.c Sun Jul 8 19:06:10 2001
@@ -493,7 +493,7 @@ int raw_recvmsg(struct sock *sk, struct
goto out;

if (addr_len)
- *addr_len = sizeof(*sin);
+ *addr_len = offsetof(struct sockaddr_in, sin_zero);

if (flags & MSG_ERRQUEUE) {
err = ip_recv_error(sk, msg, len);
diff -burp linux/net/ipv4/udp.c linux-work/net/ipv4/udp.c
--- linux/net/ipv4/udp.c Thu Apr 12 21:11:39 2001
+++ linux-work/net/ipv4/udp.c Sun Jul 8 19:05:31 2001
@@ -635,7 +635,7 @@ int udp_recvmsg(struct sock *sk, struct
* Check any passed addresses
*/
if (addr_len)
- *addr_len=sizeof(*sin);
+ *addr_len=offsetof(struct sockaddr_in, sin_zero);

if (flags & MSG_ERRQUEUE)
return ip_recv_error(sk, msg, len);


-Andi