"resource temporarily unavailable" in recv in socket programming - linux

I want to read and write over Wanpipe driver (a network device driver for Sangoma cards) via socket programming but i get this message error: "resource temporarily unavailable". The card is working and i see it send and receive packets in ifconfig. I have included my code and would be very pleased if somebody help me in this.
A related question: I set the socket to blocking mode but the recv message does not block? how could i block the recv?
int main(void)
{
int sd;
int buflen=WP_HEADER + MAX_PACKET;
char buf[buflen];
struct wan_sockaddr_ll sa;
sd = socket(AF_WANPIPE, SOCK_RAW,0);
if (sd < 0) /* if socket failed to initialize, exit */
{
perror("Error Creating Socket");
exit(1);
}
printf("Socket Descriptor:%d\n",sd);
memset(&sa,0,sizeof(struct wan_sockaddr_ll));
strncpy((char*)sa.sll_card,"wanpipe1",sizeof(sa.sl l_card));
strncpy((char*)sa.sll_device,"w1g1",sizeof(sa.sll_ device));
sa.sll_protocol = htons(PVC_PROT);
sa.sll_family = AF_WANPIPE;
if(bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
{
perror("error bind failed");
close(sd);
exit(1);
}
int data=0;
int ret=ioctl(sd,FIONBIO,&data);
if (ret < 0)
{
perror("ioctl error!");
close(sd);
return 1;
}
fd_set read_fds;
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
FD_ZERO(&read_fds);
FD_SET(sd,&read_fds);
if(select(sd+1, &read_fds, NULL, NULL, &timeout) < 0)
{
perror("select() error!");
exit(1);
}
if (FD_ISSET(sd,&read_fds))
printf("There is data for reading\n");
else
printf("There is no data for reading\n");*/
// MSG_WAITALL | MSG_PEEK | MSG_OOB
int r=recv(sd,buf,buflen,0);
if (r < 0)
{
perror("Wanpipe raw socket reading");
close(sd);
exit(1);
}
printf("\nNumber of bytes read into the buffer: %d",r);
printf("\nThe read buffer: ");
puts(buf);
close(sd);
}
thank you in advance.

Related

Socket changes from SOCK_STREAM to SOCK_DGRAM after binding?

On a Linux machine, I was having trouble with a program called kwallet (part of KDE) not starting on login even though I set it up to with PAM, so I checked out the source code to diagnose the problem. It turns out that the program creates a server that listens on a TCP socket bound to a file.
But the problem is, while the socket is a TCP socket when it's first instantiated, as soon as it's bound to the file, it suddenly becomes a UDP socket, so the call to listen on it fails.
Anyone have any idea what's happening here? Do I just have a faulty installation or something?
Here's the relevant code, with some of the lines I added to help diagnose the problem:
static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], char *fullSocket)
{
//In the child pam_syslog does not work, using syslog directly
//keep stderr open so socket doesn't returns us that fd
int x = 3;
//Close fd that are not of interest of kwallet
for (; x < 64; ++x) {
if (x != toWalletPipe[0]) {
close (x);
}
}
//This is the side of the pipe PAM will send the hash to
close (toWalletPipe[1]);
//Change to the user in case we are not it yet
if (drop_privileges(userInfo) < 0) {
syslog(LOG_ERR, "%s: could not set gid/uid/euid/egit for kwalletd", logPrefix);
free(fullSocket);
goto cleanup;
}
int envSocket;
if ((envSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
syslog(LOG_ERR, "%s: couldn't create socket", logPrefix);
free(fullSocket);
goto cleanup;
}
int socket_type;
socklen_t optlen;
optlen = sizeof socket_type;
if(getsockopt(envSocket, SOL_SOCKET, SO_TYPE, &socket_type, &optlen) < 0) {
syslog(LOG_INFO, "%s-Couldn't read socket option: %d-%s\n", logPrefix, errno, strerror(errno));
} else {
syslog(LOG_INFO, "%s-Socket type is %d\n", logPrefix, socket_type);
if(socket_type != SOCK_STREAM)
syslog(LOG_INFO, "%s-Socket is not SOCK_STREAM.\n", logPrefix);
}
struct sockaddr_un local;
local.sun_family = AF_UNIX;
if (strlen(fullSocket) > sizeof(local.sun_path)) {
syslog(LOG_ERR, "%s: socket path %s too long to open",
logPrefix, fullSocket);
free(fullSocket);
goto cleanup;
}
strcpy(local.sun_path, fullSocket);
free(fullSocket);
fullSocket = NULL;
unlink(local.sun_path);//Just in case it exists from a previous login
syslog(LOG_DEBUG, "%s: final socket path: %s", logPrefix, local.sun_path);
size_t len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
syslog(LOG_INFO, "%s-kwalletd: Couldn't bind to local file\n", logPrefix);
goto cleanup;
}
optlen = sizeof socket_type;
if(getsockopt(envSocket, SOL_SOCKET, SO_TYPE, &socket_type, &optlen) < 0) {
syslog(LOG_INFO, "%s-Couldn't read socket option: %d-%s\n", logPrefix, errno, strerror(errno));
} else {
syslog(LOG_INFO, "%s-Socket type is %d\n", logPrefix, socket_type);
if(socket_type != SOCK_STREAM)
syslog(LOG_INFO, "%s-Socket is not SOCK_STREAM.\n", logPrefix);
}
if (listen(envSocket, 5) == -1) {
syslog(LOG_INFO, "%s-kwalletd: Couldn't listen in socket: %d-%s\n", logPrefix, errno, strerror(errno));
goto cleanup;
}
//finally close stderr
close(2);
// Fork twice to daemonize kwallet
setsid();
pid_t pid = fork();
if (pid != 0) {
if (pid == -1) {
exit(EXIT_FAILURE);
} else {
exit(0);
}
}
//TODO use a pam argument for full path kwalletd
char pipeInt[4];
sprintf(pipeInt, "%d", toWalletPipe[0]);
char sockIn[4];
sprintf(sockIn, "%d", envSocket);
char *args[] = {strdup(kwalletd), "--pam-login", pipeInt, sockIn, NULL, NULL};
execve(args[0], args, pam_getenvlist(pamh));
syslog(LOG_ERR, "%s: could not execute kwalletd from %s", logPrefix, kwalletd);
cleanup:
exit(EXIT_FAILURE);
}
And here's the log output:
Oct 12 19:31:28 fuji login[413]: pam_kwallet5-Socket type is 1
Oct 12 19:31:28 fuji login[413]: pam_kwallet5: final socket path: /run/user/1000/kwallet5.socket
Oct 12 19:31:28 fuji login[413]: pam_kwallet5-Socket type is 2
Oct 12 19:31:28 fuji login[413]: pam_kwallet5-Socket is not SOCK_STREAM.
Oct 12 19:31:28 fuji login[413]: pam_kwallet5-kwalletd: Couldn't listen in socket: 95-Operation not supported

Linux to Windows PC Communication through Socket

I have used the linux part of code in windows to establish RDB communication. Though the socket opening is successful, I am unable to bind the socket with the IP Address defined. Is there any limitation between Linux and Windows over socket?
Here's my code,
SOCKET sock;
SOCKET sClient;
struct sockaddr_in server;
char szServer128; // Server to connect to
char szBuffer204800; // allocate on heap
sClient = udpsock_open(&server, szServer, DEFAULT_RX_PORT);
int udpsock_open(struct sockaddr_in *psa, char *ipv4, uint16_t port) {
WSADATA wsaData;
int opt;
int domain = AF_INET;
int type = SOCK_DGRAM;
int proto = IPPROTO_UDP;
sClient = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (sClient 0)
printf(" WSAStartup Successful %I64d\n", sClient);
else
printf("Failed. Error Code : %d\n", WSAGetLastError());
// Prepare a socket to listen for connections
if ((sock = WSASocket(domain, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return 1;
}
else
{
printf("WSASocket() is OK!\n");
}
if (sock < 0)
{
//rtos_log ( LOG_ERR, "Failed to open socket %m" );
printf("Failed to open socket %I64d\n", sock);
return -1;
}
set_reuse(sock);
memset(psa, 0x00, sizeof(struct sockaddr_in));
psa->sin_family = domain;
psa->sin_port = htons(port);
psa->sin_addr.s_addr = inet_addr(ipv4);
if (bind(sock, ( struct sockaddr *)psa, sizeof(struct sockaddr_in)) < 0)
{
printf("Failed to bind socket Error: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return -4;
}
opt = 1;
char buf[2048];
DWORD dwBytesRet;
//ioctlsocket(sock, FIONBIO, &opt)
if (WSAIoctl(sock, SIO_ADDRESS_LIST_QUERY,NULL,0, buf,2048, &dwBytesRet,NULL,NULL) == SOCKET_ERROR)
{
printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
return 1;
}
else
{
printf("ioctlsocket() is OK!\n");
}
return sock;
}

Does libevent support netlink socket

I use netlink to receive an interrupt number from kernel. The application in user space uses libevent to handle TCP/IP request and netlink message. Does libevent support Linux netlink socket? I will appreciate for a simple example.
Yes, libevent supports netlink socket.
There is https://github.com/libevent/libevent/blob/master/sample/hello-world.c, it is modified below to listen to netlink socket.
The basic example listens to Linux network interface creation/deletion and can be executed with sudo to gain privilege needed. It listens to same events as ip monitor link.
Another example of listening to RAW sockets with libevent is here https://github.com/bodgit/libevent-natpmp/blob/master/natpmp.c.
static void link_recvmsg(int fd, short event, void *arg)
{
char buf[NLMSG_SPACE(BUF_SIZE)] = {0};
socklen_t socklen;
struct iovec iov = {.iov_base = buf, .iov_len = sizeof(buf)};
struct sockaddr addr;
memset(&addr, 0, sizeof(struct sockaddr));
if (!fd || -1 == fd)
return;
int status = getsockname(fd, &addr, &socklen);
if(-1 == status)
return;
struct msghdr mh = {.msg_name = NULL, .msg_namelen = 0, .msg_iov = &iov, .msg_iovlen = 1,
.msg_flags = 0, .msg_name = &addr, .msg_namelen = sizeof(struct sockaddr)};
status = recvmsg(fd, &mh, 0);
if ((-1 == status) && ((EINTR == errno) || (EAGAIN == errno)))
return;
if(-1 == status)
return;
if ((mh.msg_flags & MSG_TRUNC) == MSG_TRUNC)
return;
if ((mh.msg_flags & MSG_CTRUNC) == MSG_CTRUNC)
return;
for (const struct nlmsghdr *h = (struct nlmsghdr *)buf; NLMSG_OK(h, status); h = NLMSG_NEXT(h, status)) {
switch (h->nlmsg_type) {
case RTM_NEWLINK:
fprintf(stderr, "got RTM_NEWLINK\n");
break;
case RTM_DELLINK:
fprintf(stderr, "got RTM_DELLINK\n");
break;
default:
fprintf(stderr, "unexpected case in swtch statement\n");
break;
}
}
}
int main(int argc, char **argv)
{
/* some init code here */
/* NETLINK socket */
int status;
int buf_size = BUF_SIZE;
struct sockaddr_nl src_addr;
int socket_nl = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
if(-1 == socket_nl) return -1;
memset(&src_addr, 0, sizeof(struct sockaddr_nl));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
src_addr.nl_groups |= RTNLGRP_LINK;
status = setsockopt(socket_nl, SOL_SOCKET, SO_RCVBUF,
&buf_size, sizeof(buf_size));
if(-1 == status) return -1;
status = bind(socket_nl, (struct sockaddr *)&src_addr, sizeof(struct sockaddr_nl));
if(status < 0) return -1;
static struct event nl_ev;
event_set(&nl_ev, socket_nl, EV_READ|EV_PERSIST, link_recvmsg,
NULL);
if (base) {
event_base_set(base, &nl_ev);
}
event_add(&nl_ev, NULL);
/* some other code, dispatch event and deinit */
}

posix multithread.With Multiple threas using one socket to receive data , when will the data be taken away from recv buffer?

I use multuple thread to receive data from one socket. they all can receive the same data. I want to know when the data will be taken away from recv buffer? Why does not one thread receive the next data when former thread read former data.
pthread_create(&(ntid[i]), NULL, find_host, (void *)&start_addr);
int find_host(void * arg)
{
int sockfd;
unsigned long ip ;
tv.tv_sec = 0;
tv.tv_usec = 100000;
struct sockaddr_in from;
char sendpacket[PACKET_SIZE];
char recvpacket[PACKET_SIZE];
ip = *(unsigned long *)arg;
struct sockaddr_in present_addr;
if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0)
{
perror("socket error");
exit(1);
}
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size) );
if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))<0){
printf("socket option SO_RCVTIMEO not support\n");
return;
}
bzero(&present_addr,sizeof(present_addr));
present_addr.sin_family=AF_INET;
present_addr.sin_addr.s_addr = htonl(ip);
pthread_mutex_unlock(&lock);
printf("PING (%s): %d bytes data in ICMP packets.\n",
inet_ntoa(present_addr.sin_addr),ICMP_DATA_LEN);
send_packet(sockfd, sendpacket, present_addr);
recv_packet(sockfd, recvpacket, from);
close(sockfd);
}
void recv_packet(int sockfd, char * recvpacket, struct sockaddr_in from)
{ int n,from_len;
extern int errno;
int nreceived = 0;
struct timeval recv_time;
from_len = sizeof(from);
while (nreceived < MAX_SEND_TIMES)
{
if((n=recvfrom(sockfd,recvpacket, PACKET_SIZE, 0,
(struct sockaddr *)&from,&from_len)) <0)
{
if(errno == EWOULDBLOCK || errno== EAGAIN )
{
printf("recvfrom Timeout!!!!\n");
pthread_exit(NULL);
}
}
gettimeofday(&recv_time,NULL);
if (1 == unpack(recv_time, recvpacket, n, from))
{
printf(" find %u\n", (unsigned short)pthread_self());
nreceived++;
}
else
printf(" not find\n");
}
}

how to read/write from/to a SOCK_SEQPACKET socket?

I try to use a SOCK_SEQPACKET socket with this:
int rc, len;
int worker_sd, pass_sd;
char buffer[80];
struct iovec iov[1];
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
memset(iov, 0, sizeof(iov));
iov[0].iov_base = buffer;
iov[0].iov_len = sizeof(buffer);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
if((socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0)
{
perror("server: socket");
exit -1;
}
memset(&server_address, 0, sizeof(server_address));
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "/mysocket");
unlink("/mysocket");
if(bind(socket_fd, (const struct sockaddr *) &server_address, sizeof(server_address)) < 0)
{
close(socket_fd);
perror("server: bind error");
return 1;
}
while(1)
{
printf("wait for message\n");
bytes_received = recvmsg(socket_fd, &msg, MSG_WAITALL);
printf("%d bytes\n", bytes_received);
}
The problem is that the process does not wait but receives -1 from recvmsg and loops forever. Nowhere in the manpages is there any reference what functions shall be used with SOCK_SEQPACKET-style sockets, for example I am not really sure whether recvmsg is even the correct function.
SOCK_SEQPACKET is connection-orientated so you must first accept a connection then do your IO on the accepted client socket.
recvmsg() returns -1 when an error has occured - errno will be set to the error number.
Read here: http://pubs.opengroup.org/onlinepubs/009695399/functions/recvmsg.html

Resources