Hello,
Thanks for reading and you valuable time. I appreciate.
Would you pls check if the code below works in your Linux IPv6 machine?
This code opens
an IPv6 raw socket and call select to read raw data from this socket.
I have spent many hours to find out why I am getting 0 from select in my
machine.
I am getting EAGAIN due to select timeout on my machine.
Is my code wrong OR Linux IPv6 setting on my machine is wrong?????
Have nice time.
Thanks
Arif
-----------------------test.c-----------------------------
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <errno.h>
/* for select() */
#include <sys/select.h>
#include <sys/time.h>
int main(void) {
/* variables for opening socket & sending data */
struct sockaddr_in6 addr6;
int size, sd, enable = 1, i;
struct msghdr msg;
struct iovec io;
char buf[15];
/* variables for receiving data */
struct sockaddr_in6 remSockAddr6;
struct msghdr msgRecv;
struct iovec ioRecv;
char bufRecv[100];
int recvLen = 0;
/* variables for select() */
fd_set rFdSet;
struct timeval selTime;
int num;
sd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
printf("sd is %d\n",sd);
if(sd == -1)
{ perror("socket()"); exit(1); }
if(ioctl(sd, FIONBIO, &enable) == -1)
{ perror("ioctl()"); exit(1); }
if(setsockopt(sd, SOL_SOCKET, SO_BSDCOMPAT, &enable, sizeof(enable)) ==
-1)
{ perror("setsockopt()"); exit(1); }
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) ==
-1)
{ perror("setsockopt()"); exit(1); }
memset(&addr6, 0, sizeof(addr6));
size = sizeof(struct sockaddr_in6);
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(42);
memcpy(&addr6.sin6_addr, &in6addr_loopback, sizeof(struct in6_addr));
if(bind(sd, (struct sockaddr *)&addr6, size) == -1)
{ perror("bind()"); exit(1); }
sprintf(buf, "This is a test");
io.iov_base = buf; io.iov_len = 15;
msg.msg_name = &addr6; msg.msg_namelen = sizeof(struct sockaddr_in6);
msg.msg_iov = &io; msg.msg_iovlen = 1;
msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0;
i = sendmsg(sd, &msg, 0);
printf("%d bytes sent\n", i);
if(i == -1)
{ perror("sendmsg()"); exit(1); }
/* receiving Raw IPv6 Data */
FD_ZERO(&rFdSet);
FD_SET(sd, &rFdSet);
selTime.tv_sec = 20; /* select will wait 20 sec for data */
selTime.tv_usec = 0;
num = select(sd+1, &rFdSet, NULL, NULL, &selTime);
if(num <= 0)
printf("No data arrived as no socket!\n");
else if FD_ISSET(sd, &rFdSet)
{
memset(&remSockAddr6, 0, sizeof(remSockAddr6));
memset(&msgRecv, 0, sizeof(msgRecv));
ioRecv.iov_base = bufRecv;
ioRecv.iov_len = 0;
msgRecv.msg_name = (void *)&remSockAddr6;
msgRecv.msg_namelen = sizeof(remSockAddr6);
msgRecv.msg_control = NULL;
msgRecv.msg_controllen = 0;
msgRecv.msg_iov = &ioRecv;
msgRecv.msg_iovlen = 1;
msgRecv.msg_flags = 0;
recvLen = recvmsg(sd, &msgRecv, 0);
printf("error no: %d\n",errno);
if(errno == EINVAL)
printf("Invalid Argument\n");
printf("Data recvd %d Bytes\n",recvLen);
}
exit(0);
}
-----Original Message-----
From: Heikki Kallasjoki [mailto:fizban@xxxxxx]
Sent: Thursday, March 07, 2002 4:18 PM
To: Hossain, Mohammad
Cc: netdev@xxxxxxxxxxx
Subject: Re: IPv6 Raw socket problem in Linux 7.2
On Thu, Mar 07, 2002 at 03:09:58PM -0800, Hossain, Mohammad wrote:
> Problem:
> I am opening am raw ipv6 socket. Then trying to send and receive data
> using it. But I get invalid argument(EINVAL) from both sendmsg()
> and recvfrom() system call when trying to send data. Why is this
happening?
Not sure, but trying to answer the first question..
> Q: What is wrong in following code?
By simply looking, can't spot any errors. The following code runs
without any error messages on my system, you might want to check if it
works there - if it doesn't, the problem is most probably in your system
setup, not in the code:
--- test.c ---
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
int main(void) {
struct sockaddr_in6 addr6;
int size, sd, enable = 1, i;
struct msghdr msg; struct iovec io; char buf[100];
sd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
if(sd == -1) { perror("socket()"); exit(1); }
if(ioctl(sd, FIONBIO, &enable) == -1) { perror("ioctl()"); exit(1);
}
if(setsockopt(sd, SOL_SOCKET, SO_BSDCOMPAT, &enable, sizeof(enable))
== -1) { perror("setsockopt()"); exit(1); }
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))
== -1) { perror("setsockopt()"); exit(1); }
memset(&addr6, 0, sizeof(addr6));
size = sizeof(struct sockaddr_in6);
addr6.sin6_family = AF_INET6; addr6.sin6_port = htons(42);
memcpy(&addr6.sin6_addr, &in6addr_loopback, sizeof(struct
in6_addr));
if(bind(sd, (struct sockaddr *)&addr6, size) == -1) {
perror("bind()"); exit(1); }
io.iov_base = buf; io.iov_len = 100;
msg.msg_name = &addr6; msg.msg_namelen = sizeof(struct
sockaddr_in6);
msg.msg_iov = &io; msg.msg_iovlen = 1;
msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0;
i = sendmsg(sd, &msg, 0);
if(i == -1) { perror("sendmsg()"); exit(1); }
exit(0);
--- test.c ---
It should be essentially equivalent to what you posted.
> Q: Kernel missing some module????
> How to know if my machine has raw IPv6 support or raw6 module in
> the kernel is installed or not. I see
> raw6 module is there in /proc/net dir.
/proc/net/raw6 should be a list of opened raw sockets, AFAIK. Kernel
version numbers (output of 'uname -a') might be helpful, my system is
"Linux <hostname> 2.4.18 #21 Tue Feb 26 13:02:07 EET 2002 i586 unknown"
and raw v6 sockets seem to work well on this.
--
>#v1&#:<-1<-1\0\_.@ "You cannot escape from window 0!"
>2-!#v_:2\^fibre^-< fizban at iki dot fi
^:_ >$1>\#+:#$!_1^ PGP key fp 657AF64968F12E6ECBE5F90E421C1FDF9EC09E94
|