Resource temporarily unavailable in gethostbyname() - c

I was writing my first client in C when I reached the point where I have to send a socket to the server. When i try to get its address I get a
Resource temporarily unavailable
and I can't find what is causing this problem.
dadesSoftConfig->ipServer has inside localhost
struct hostent *ent;
ent = gethostbyname(dadesSoftConfig->ipServidor);
if (ent == NULL) {
int errnum = errno;
fprintf(stderr, "Client finalitzat: %s\n", strerror(errnum));
exit(EXIT_FAILURE);
}
I do not send any socket, wait for any data yet when I do this call , this is happening at the very beginning, even before the register phase of my protocol.
As requested, this is a print of the dadesSoftConfig:
DEBUG_INFO: Nom: SW-01
Mac: 89F107457A36
Server: localhost
Server-port: 2019
And this is how I print it:
void print_software_configuration(TDadesSoftConfig *dades) {
char *msg;
msg = (char *) malloc(sizeof(char) * 75);
if (sprintf(msg, "\tNom: %s \t\tMac: %s \t\tServer: %s \t\tServer-port: %d\n",
dades->nom, dades->mac, dades->ipServidor, dades->serverPort) < 0) {
fprintf(stderr, "No s'ha pogut mostrar el contingut llegit\n");
} else {
print_debug_info(msg);
}
free(msg);
}
I tried sending "127.0.0.1" to gethostbyname() function and the code perfectly works, even when I store it to my struct. Any idea why it doesn't work when sending "localhost"?

As pointed by my prints, the data structure was correct, but the data it contained was not. Info should be displayed separated by \t\t not a \n\t\t.
The problem was solved when setting correctly the delimiters to strtok() function which parses the input.

Related

Send a message using D-Bus

I want to send a message using D-Bus but I get an error:
process 30860: arguments to dbus_message_new_signal() were incorrect, assertion "_dbus_check_is_valid_path (path)" failed in file ../../../dbus/dbus-message.c line 1456.
This is normally a bug in some application using the D-Bus library.
Message is null!
My code:
#include <stdio.h>
#include <dbus/dbus.h>
int main(){
DBusConnection *conn;
DBusError err;
dbus_error_init(&err);
conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(!conn){
fprintf(stderr, "DBus error %s: %s\n", err.name, err.message);
return(1);
}
dbus_bus_request_name(conn, "org.test", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "DBus error %s: %s\n", err.name, err.message);
dbus_connection_close(conn);
return(1);
}
DBusMessage *msg;
msg = dbus_message_new_signal("org/test/mon/data", "org.test.mon.data", "Data");
if(msg == NULL){
fprintf(stderr, "Message is null!\n");
return(1);
}
dbus_message_append_args(msg, DBUS_TYPE_STRING, "My message", DBUS_TYPE_INVALID);
if(!dbus_connection_send(conn, msg, NULL)) fprintf(stderr, "Error sending message!\n");
dbus_message_unref(msg);
dbus_connection_flush(conn);
dbus_connection_close(conn);
}
I tried to follow dozens of tutorials and examples but I think I missed something.
I just need to send a message with a text.
In addition to fixing the code as recommended by jku, it’s recommended that you don’t use libdbus for connecting to D-Bus: its design is outdated, and is a pain to use correctly.
It’s easier to use a more modern high-level API, such as GDBus.
The first argument to dbus_message_new_signal() is a D-Bus path and the spec says this about paths:
The path must begin with an ASCII '/' (integer 47) character

Why is pcap_datalink() always returning 1 (Ethernet), even on wireless device?

I'm having an issue where by pcap_datalink() is always returning 1. To my understanding this is LINKTYPE_ETHERNET. But, the device I am using is a wireless card and in my case en0.
This is stopping me from putting the card into monitor mode, and stopping my WLAN filters from working. I've tried to run this on both OSX and Linux with the same results. I also run as root.
Here's the part of my code that's causing the problem. For the example, assume dev is set to en0 (wireless device on Mac).
#include <stdio.h>
#include <pcap.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pcap_t *pcap_h;
char *dev, errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
struct pcap_pkthdr header;
const u_char *packet;
if(argc < 2)
{
printf("Usage: %s device\n", argv[0]);
exit(EXIT_FAILURE);
}
dev = argv[1];
if((pcap_h = pcap_create(dev, errbuf)) == NULL)
{
printf("pcap_create() failed: %s\n", errbuf);
exit(EXIT_FAILURE);
}
if(pcap_can_set_rfmon(pcap_h) == 0)
{
printf("Monitor mode can not be set.\n");
}
if(pcap_set_rfmon(pcap_h, 1) != 0)
{
printf("Failed to set monitor mode.\n");
exit(EXIT_FAILURE);
}
if(pcap_activate(pcap_h) != 0)
{
printf("pcap_activate() failed\n");
exit(EXIT_FAILURE);
}
/*
* Compile a filter to sniff 802.11 probe requests
* Filter: type mgt subtype probe-req
*/
if(pcap_compile(pcap_h, &fp, "type mgt subtype probe-req", 0, PCAP_NETMASK_UNKNOWN) == -1)
{
printf("pcap_compile() failed: %s\n", pcap_geterr(pcap_h));
exit(EXIT_FAILURE);
}
/*
* Set the compiled filter
*/
if(pcap_setfilter(pcap_h, &fp) == -1)
{
printf("pcap_setfilter() failed: %s\n", pcap_geterr(pcap_h));
exit(EXIT_FAILURE);
}
pcap_freecode(&fp);
packet = pcap_next(pcap_h, &header);
printf("Header: %d\n", header.len);
pcap_close(pcap_h);
return 0;
}
Any idea's why pcap_datalink() is always returning 1?
Edit
Updated code, and added pcap_set_rfmon() before the call to pcap_activate(). I get an error:
pcap_compile() failed: 802.11 link-layer types supported only on 802.11
Are you shure this is what's is stopping you from putting the card into monitor mode, and stopping your WLAN filters from working, or do you do this call to pcap_datalink() as a check trying to pinpoint the issue?
Be aware that, from PCAP-LINKTYPE(7):
For a live capture or ``savefile'', libpcap supplies, as the
return value of the pcap_datalink(3PCAP) routine, a value that
indicates the type of link-layer header at the beginning of the
packets it provides. This is not necessarily the type of link-layer
header that the packets being captured have on the network from
which they're being captured; for example, packets from an IEEE 802.11
network might be provided by libpcap with Ethernet headers that
the network adapter or the network adapter driver generates from the
802.11 headers.
So I would not take this LINKTYPE_ETHERNET / DLT_EN10MB return value as the sure indication of a problem here.
EDIT:
Also, pcap_set_rfmon() is supposed to be call before the handle is activated, which is not visible in your code.
pcap is rather touchy about the order things should be done. Have a look at the man pages for pcap_can_set_rfmon and pcap_set_rfmon.
The order should be:
pcap_create
pcap_can_set_rfmon
pcap_set_rfmon (if so far so good)
then and only then, pcap_activate

pcap_loop does just wait

I'm trying to do a little sniffer using pcap in C like explained here
My problem is that pcap_loop absolutly catch no packets and/or does nothing, my callback function is never called. my guess was the time out value but even if i set it to 20 (ms), nothing changes. It hope it s only a simple error i can't see, but i'll let you guys try to figure it out, cause it's been messing my brain too much !!
Thanks
Nikko
Edit : i choose wlan0 as interface and it works with the program given at the link
My main :
int main(int argc, char* argv[]) {
// interface & err buff
char *dev, errbuff[PCAP_ERRBUF_SIZE];
int i = 0,inum= -1;
// it filters out only packet from this machin
char filter_exp[] = "ip host localhost";
struct bpf_program fp; /* compiled filter program (expression) */
/* typedef, no need for struct ... */
bpf_u_int32 mask;
bpf_u_int32 net;
int num_packets = 10;
// 1.0+ API pcap version
pcap_if_t * alldevs;
pcap_if_t * pdev;
pcap_t * handle;
// 1st argument interface
if(argc == 2) {
dev = argv[1];
printf("Chosen interface : %s\n",dev);
}
//+1.0 api version
if(pcap_findalldevs(&alldevs,errbuff)){
fprintf(stderr,"findalldev failed to retrieve interface\n %s",errbuff);
return(2);
}
if(alldevs == NULL){
fprintf(stderr,"Retrieved interface is null\n");
return(2);
}
// select all interfaces
for(pdev = alldevs; pdev != NULL;pdev = pdev->next) {
printf("Device %d : ",++i);
print_pcap_if_t(pdev);
//print_pcap_addr(pdev->addresses);
}
printf("Enter the interface number (1-%d):",i);
scanf("%d", &inum);
if(inum < 1 || inum > i){
fprintf(stderr,"Device %d not in list.\n",i);
return(2);
}
/* Jump to the selected adapter */
for(pdev=alldevs, i=0; i< inum - 1 ;pdev=pdev->next, i++);
printf("\n-------------------------------------------------\n");
//printf("Chosen device : %s",pdev->name);
//print_pcap_if_t(pdev);
/* activate device */
printf("activating\n");
handle = pcap_open_live(pdev->name,SNAP_LEN,1,1000,errbuff);
if(handle == NULL){
fprintf(stderr,"Could not open device for sniffing");
return(2);
}
/* compile filter */
if(pcap_compile(handle,&fp,filter_exp,0,net) == -1) {
fprintf(stderr,"Could not compile filtering rules");
return(EXIT_FAILURE);
}
/* apply filter */
if(pcap_setfilter(handle,&fp) == -1) {
fprintf(stderr,"Could not set filtering rules");
return(EXIT_FAILURE);
}
printf("Waiting for packets to come in your hands");
fflush(stdout);
pcap_loop(handle,num_packets,got_packet,NULL);
pcap_freecode(&fp);
pcap_close(handle);
pcap_freealldevs(alldevs);
return(0);
}
ip host localhost
"localhost" is the name for the IP address 127.0.0.1; it is not the IP address of your machine on the Internet, it's a special IP address used to send IPv4 packets from your machine to itself (e.g., "ftp localhost" if you want to test the FTP server on your machine by connecting to it from a command prompt on your machine).
Traffic to or from other hosts will not come from, or be sent, to, 127.0.0.1.
If your machine has the IP address 10.0.1.2, for example, try "ip host 10.0.1.2".
Ok i found the problem :
my filter "ip host localhost" aws the reason. I changed it to "ip" and there it was =)
I dont really understand though. What i do is i launch the program, and just refresh a web page after that. So my first request is a GET or stg, with source = localhost , no ? And the response will contains my address also in the destination field. According to man page :
host HOST True if either the IPv4/v6 source or destination of the packet is
HOST.
Would it be that it does no translation of "localhost" when setting the filter ?
Anyway , i hope it could help some others...

Can we save C structure in Redis by hiredis ? I can save it but can not get it

I want to know if I could save a C structure in redis. But I do not know how to get it because the example.c in hiredis do not mentioned that.
I save a structure to Redis using binary-safe string. And I got a +OK which means I save that correctly.
The save code is here
...
reply = redisCommand(c, "HMSET %s stat %b", rcvgetattr.pathname, sndgetattr.stbuf, sizeof(struct stat));
printf("Save status %s\n", reply->str);//that shows +OK
freeReplyObject(reply);
And then When I try to get my data back, I use
...
reply = redisCommand(c, "HMGET %s stat", rcvgetattr.pathname);
printf("status %s\n", reply->str);
freeReplyObject(reply);
Because I do not know which part contains my structure, so I use gdb and try to find it out. I use commands like disp (struct stat)reply->str or disp (struct stat)reply->element->str to see if the data is equal to the one I just saved. But I failed.
Does anyone know where it stores its data?
I think the problem you are having is that HMGET returns an array, not a string. Try using reply->element[0]->str.
This sample code may also help
typedef struct mytest {
int myInt;
long myLong;
} mytest;
// ...
mytest t;
t.myInt = 5; t.myLong = 123451;
reply = redisCommand(c, "HMSET %s stat %b", "mykey", &t, sizeof(mytest));
printf("Save status %s\n", reply->str);//that shows +OK
freeReplyObject(reply);
reply = redisCommand(c, "HMGET %s stat", "mykey");
mytest* response = reply->element[0]->str;
printf("status %d %ld\n", response->myInt, response->myLong);
freeReplyObject(reply);

How to create a simple Proxy to access web servers in C

I’m trying to create an small Web Proxy in C. First, I’m trying to get a webpage, sending a GET frame to the server.
I don’t know what I have missed, but I am not receiving any response. I would really appreciate if you can help me to find what is missing in this code.
int main (int argc, char** argv) {
int cache_size, //size of the cache in KiB
port,
port_google = 80,
dir,
mySocket,
socket_google;
char google[] = "www.google.es", ip[16];
struct sockaddr_in socketAddr;
char buffer[10000000];
if (GetParameters(argc,argv,&cache_size,&port) != 0)
return -1;
GetIP (google, ip);
printf("ip2 = %s\n",ip);
dir = inet_addr (ip);
printf("ip3 = %i\n",dir);
/* Creation of a socket with Google */
socket_google = conectClient (port_google, dir, &socketAddr);
if (socket_google < 0) return -1;
else printf("Socket created\n");
sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
if (write(socket_google, (void*)buffer, MESSAGE_LENGTH+1) < 0 )
return 1;
else printf("GET frame sent\n");
strcpy(buffer,"\n");
read(socket_google, buffer, sizeof(buffer));
// strcpy(message,buffer);
printf("%s\n", buffer);
return 0;
}
And this is the code I use to create the socket. I think this part is OK, but I copy it just in case.
int conectClient (int puerto, int direccion, struct sockaddr_in *socketAddr) {
int mySocket;
char error[1000];
if ( (mySocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("Error when creating the socket\n");
return -2;
}
socketAddr->sin_family = AF_INET;
socketAddr->sin_addr.s_addr = direccion;
socketAddr->sin_port = htons(puerto);
if (connect (mySocket, (struct sockaddr *)socketAddr,sizeof (*socketAddr)) == -1) {
snprintf(error, sizeof(error), "Error in %s:%d\n", __FILE__, __LINE__);
perror(error);
printf("%s\n",error);
printf ("-- Error when stablishing a connection\n");
return -1;
}
return mySocket;
}
Thanks!
First, you're not checking how many bytes the write(2) call actually wrote to the socket. The return value of the call tells you that. Same for the read(2). TCP socket is a bi-directional stream, so as a rule always do both in a loop until expected number of bytes is transferred, EOF is read (zero return from read(2)), or an error occurred (which you are not checking for when reading either).
Then HTTP is rather complex protocol. Make yourself familiar with RFC 2616, especially application level connection management and transfer encodings.
Edit 0:
Hmm, there's no such thing as "simple" proxy. You need to manage multiple connections (at least client-to-proxy and proxy-to-server), so it's probably best to look into select(2)/poll(2)/epoll(4)/kqueue(2) family of system call, which allow you to multiplex I/O. This is usually combined with non-blocking sockets. Look into helper libraries like libevent. Look at how this is done in good web-servers/proxies like nginx. Sound like it's a lot for you to discover, but don't worry, it's fun :)
Since you didn't post the GetIP routine, I am not certain that your hostname lookup is correct, as from the looks of it, I am not sure that you are using inet_addr function correctly.
Nikolai has pointed out some very good points (and I fully agree). In fact you GET request is actually broken, and while I was testing it on my own local Apache web server on my system, it didn't work.
sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
if (write(socket_google, (void*)buffer, LONGITUD_MSJ+1) < 0 )
return 1;
else printf("GET frame sent\n");
...
strcpy(buffer,"\n");
read(socket_google, buffer, sizeof(buffer));
should be replaced with
snprintf(buffer, sizeof(buffer),
"GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: TEST 0.1\r\n\r\n",
google);
if (write(socket_google, buffer, strlen(buffer)+1) < 0 ) {
close(socket_google);
return 1;
} else
printf("GET frame sent\n");
...
buffer[0] = '\0';
/* Read message from socket */
bytes_recv = read(socket_google, buffer, sizeof(buffer));
if (bytes_recv < 0) {
fprintf(stderr, "socket read error: %s\n", strerror(errno));
close(socket_google);
exit(10);
}
buffer[bytes_recv] = '\0'; /* NUL character */
/* strcpy(message,buffer); */
printf("%s\n", buffer);
...
You should also close the socket before exiting the program. Enable standard C89/90 or C99 mode of your compiler (e.g. -std=c99 for gcc) and enable warnings (e.g. -Wall for gcc), and read them. And #include the necessary header files (assuming Linux in my case) for function prototypes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> /* for gethostbyname() */
There is some casting of pointers and structs in regards to the hostname / IP address resolving, which can be confusing and easy place to make a mistake, so verify that is working as you expect it is.
in_addr_t ip;
...
GetIP(google, &ip); /* I changed the parameters */
printf("IP address = %x (%s)\n",
ip,
inet_ntoa(*((struct in_addr*)&ip)));
Actually, I've been implementing a small web proxy using my library called rzsocket link to it.
One of the most difficult things I've found when implementing the web proxy, perhaps this might also be your problem, was that, in order to make the proxy work properly, I had to set keep-alive settings false. One way of doing this in FireFox, is accessing about:config address, and setting the value of network.http.proxy.keep-alive to false.

Resources