I'm using ioctl in my C code, which calls some ioctl command in the linux kernel Fedora 2.6.10 code, which I can easily edit and rebuild.
The ioctl command fails. How can I tell which ioctl command is called?
attached user space code. The second console_printf() is printed
int skfd = -1;
struct ifreq ifr;
if (( skfd = socket( AF_INET, SOCK_DGRAM, 0 )) < 0)
{
console_printf("ac_get_lan_link_ip_address - failed to open socket\n");
return -1;
}
if(ioctl( skfd, SIOCGIFADDR, &ifr ) == -1)
{
console_printf("ac_get_lan_link_ip_address - failed to run ioctl\n");
ac_close(skfd);
return -1;
}
You can use errno to find what exactly failed with your called of ioctl.
"Man ioctl"
Regards.
Use perror to print the system error messages for such calls. They'll yield what goes wrong.
Related
My code is intended to establish a simple connection between two computers using a socket (the winsock2.h one), but the setsockopt phase does not work (returns a negative value) without a valid errno (a null errno unless I initialize the variable beforehand).
Here is my minified code:
// I include winsock2.h, errno.h and other needed (and less important) stuff
int optval = 1;
errno = 0;
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0){
print("TCP socket error, %s", strerr(errno));
exit(EXIT_FAILURE);
}
When running, the program outputs:
TCP socket error, No error
This output, from my point of view, tells me that, either there is no error and the conditional is mistakenly evaluated (perhaps returning under zero does not mean an error), or something strange happens with the errno (as a reminder, if i did not initialize the errno variable it would be null, perhaps winsock2.h does not use it).
Windows sockets functions don't set errno when they fail.
You need to instead call WSAGetLastError to get the most recent error code and FormatMessage message to get the textual equivalent.
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0){
char errbuf[300];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(),
0, errbuf, sizeof(errbuf), NULL);
printf("TCP socket error: %s", errbuf);
}
I expect the following code* to fail since the server address hasn't been set with a valid value (verified in debugger - the whole struct is indeed initialized to 0, making address family AF_UNSPEC).
* incomplete illustrative snippet
static struct sockaddr_in g_server_addr;
int main(void)
{
int hdl;
hdl = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (-1 == hdl)
{
printf("Client Socket creation failed.");
return -1;
}
if(-1 == connect(hdl, (struct sockaddr *) &g_server_addr, sizeof(g_server_addr)))
{
printf("Connect() on socket failed.");
return -1;
}
return 0;
}
I need connect() to fail when called with incorrect input.
(This code is being tested on an Ubuntu machine.)
From the connect manpage:
Connectionless sockets may dissolve the association by connecting to an address with the sa_family member of sockaddr set to AF_UNSPEC (supported on Linux since kernel 2.2).
The manpage is a bit outdated, it will work on any socket, which can be disconnected at all, as for example TCP sockets.
In practice, there is no error when trying to dissolve the association on a stream socket, which is not yet connected. This is, why you don't get an error.
If you need to get an error, initialize the address family with an invalid family:
static struct sockaddr_in g_server_addr = { -1 };
This will yield the error -1 EAFNOSUPPORT (Address family not supported by protocol)
See also net/ipv4/af_inet.c of a recent linux kernel:
int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags) {
...
if (uaddr->sa_family == AF_UNSPEC) {
err = sk->sk_prot->disconnect(sk, flags);
sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
goto out;
}
...
out:
return err;
i am writing a driver code, to read some register values from x86., when i ran my user space application i got the below error.
ioctl:Inappropriate ioctl for device
here is the code sniff..
fd = open_drvfile();
if(ioctl(fd, IOCTL_MSR_CMDS, (long long)msr_start) == -1 ) {
perror("ioctl:");
exit (0);
}
and open_drvfile() just open(create and open) the char file as below
fd = open("/dev/" DEV_NAME, O_RDWR|O_CREAT);
if (fd == -1) {
perror("Failed to open /dev/" DEV_NAME);
}
return fd;
can some one point where i made mistake on this?
A char device implies that it shall be created with mknod(), and not with O_CREAT under open() flags (which will create a regular file, not a char device).
(see question comments).
I wrote a program to get the details of hard disk drive using HDIO_ ioctl calls.
For writing program, I'm referring Documentation/ioctl/hdio.txt in kernel source(2.6.32).
Here is my main part of code:
unsigned char driveid[512];
fd = open("/dev/sda", O_RDONLY); // validated fd.
retval = ioctl(fd, HDIO_GET_IDENTITY, &driveid);
if(retval < 0) {
perror("ioctl(HDIO_GET_IDENTITY)");
exit(3);
}
When I run(as root) the above code, I got below error:
ioctl(HDIO_GET_IDENTITY): Invalid argument
What is the wrong in the program?
Why I'm getting error?
Additional Info: OS: CentOS-6.5, kernel version: 2.6.32, IA:x86_64 (running on VMware).
the HDIO_GET_IDENTITY ioctl() doesn`t take a raw character buffer as its 3rd argument.
it uses a struct defined in linux/hdreg.h.
struct hd_driveid driveid;
fd = open("/dev/sda", O_RDONLY); // validated fd.
retval = ioctl(fd, HDIO_GET_IDENTITY, &driveid);
if(retval < 0) {
perror("ioctl(HDIO_GET_IDENTITY)");
exit(3);
}
this way it should work. Be aware that it only works for IDE/SATA drives, SCSI is not supported.
has
if you are wondering on how to get the information after the command ioctl() has returned succesfully, I suggest going through
http://lxr.free-electrons.com/source/include/linux/hdreg.h?v=2.6.36
Our application uses a non-blocking socket usage with connect and select operations (c code).
The pusedo code is as below
unsigned int ConnectToServer(struct sockaddr_in *pSelfAddr,struct sockaddr_in *pDestAddr)
{
int sktConnect = -1;
sktConnect = socket(AF_INET,SOCK_STREAM,0);
if(sktConnect == INVALID_SOCKET)
return -1;
fcntl(sktConnect,F_SETFL,fcntl(sktConnect,F_GETFL) | O_NONBLOCK);
if(pSelfAddr != 0)
{
if(bind(sktConnect,(const struct sockaddr*)(void *)pSelfAddr,sizeof(*pSelfAddr)) != 0)
{
closesocket(sktConnect);
return -1;
}
}
errno = 0;
int nRc = connect(sktConnect,(const struct sockaddr*)(void *)pDestAddr, sizeof(*pDestAddr));
if(nrC != -1)
{
return sktConnect;
}
if(errno != EINPROGRESS)
{
int savedError = errno;
closesocket(sktConnect);
return -1;
}
fd_set scanSet;
FD_ZERO(&scanSet);
FD_SET(sktConnect,&scanSet);
struct timeval waitTime;
waitTime.tv_sec = 2;
waitTime.tv_usec = 0;
int tmp;
tmp = select(sktConnect +1, (fd_set*)0, &scanSet, (fd_set*)0,&waitTime);
if(tmp == -1 || !FD_ISSET(sktConnect,&scanSet))
{
int savedErrorNo = errno;
writeLog("Connect %s failed after select, cause %d, error %s",inet_ntoa(pDestAddr->sin_addr),savedErrorNo,strerror(savedErrorNo));
closesocket(sktConnect);
return -1;
}
.
.
.
.
.}
Problem statement
In the above code, the select fails with error code 115 which is "Operation in progress". I do not see any documentation on select failing with errno 115.
a. When does the select fails with error code 115 in non-blocking socket? Under what scenario?
b. Do we see any system logs which hints at this problem. Only concern for us me - I could not find any documented feature which describes such problem.
PS : We are using SUSE Linux 11 Enterprise Edition.
The errno EINPROGRESS isn't from select(), it is left over from the prior connect() operation. You enter the block that reports it if either select() returned -1 or the FD isn't set. All this means is that the connection is still in progress. errno is never cleared, only set.
Some thoughts on your code:
I think your condition below the select can be modified to check only to see, if select has returned a value greater than 0 and if that is the case, you can check output of getsockopt for the socket (for SOL_SOCKET and SO_ERROR) options (getsockopt(...,SOL_SOCKET, SO_ERROR,...,...)) to see if connect has not failed.
I am not very sure if the select will always return the socket as writable in case of a connection success. So, in your case, it may (only may) be the case that, the tmp variable is not -1 and the errno it is showing is the errno of the previous connect call.
Additional Reasons:
Another good reason is that, the destination address to which you are connecting is either not reachable, or doesn't have a server waiting at the specified address + port combination. In which case, you can try once with a blocking socket to see if that connects.
As far as I understand, you are trying to make a connection with timeout.
If so, there is a error in your code. After connect() call but before select() you should remove O_NONBLOCK option using fcntl(). Otherwise the select() will always return at once because the operations with your socket (which has O_NONBLOCK) would not block.
The EINPROGRESS which you read is probably generated not by select() but by previous connect() call.
You also should not use bind() call here because connect() implicitly binds your address to socket.