How to find the interface used by a connected socket.So that i can set status codes for different interfaces.I used the below code.But I didnt get it.
I've tried two different approaches in the test code below, but both fail. The first one connects to a remote server, and uses ioctl with SIOCGIFNAME, but this fails with 'no such device'. The second one instead uses getsockopt with SO_BINDTODEVICE, but this again fails (it sets the name length to 0).
Any ideas on why these are failing, or how to get the I/F name? after compiling, run the test code as test "a.b.c.d", where a.b.c.d is any IPV4 address which is listening on port 80. Note that I've compiled this on Centos 7, which doesn't appear to have IFNAMSZ in <net/if.h>, so you may have to comment out the #define IFNAMSZ line to get this to compile on other systems.
Thanks.
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
int main(int argc, char **argv) {
int sock;
struct sockaddr_in dst_sin;
struct in_addr haddr;
if(argc != 2)
return 1;
if(inet_aton(argv[1], &haddr) == 0) {
printf("'%s' is not a valid IP address\n", argv[1]);
return 1;
}
dst_sin.sin_family = AF_INET;
dst_sin.sin_port = htons(80);
dst_sin.sin_addr = haddr;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
if(connect(sock, (struct sockaddr*)&dst_sin, sizeof(dst_sin)) < 0) {
perror("connect");
return 1;
}
printf("connected to %s:%d\n",
inet_ntoa(dst_sin.sin_addr), ntohs(dst_sin.sin_port));
#if 0 // ioctl fails with 'no such device'
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
// get the socket's interface index into ifreq.ifr_ifindex
if(ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1;
}
// get the I/F name for ifreq.ifr_ifindex
if(ioctl(sock, SIOCGIFNAME, &ifr) < 0) {
perror("SIOCGIFNAME");
return 1;
}
printf("I/F is on '%s'\n", ifr.ifr_name);
#else // only works on Linux 3.8+
#define IFNAMSZ IFNAMSIZ // Centos7 bug in if.h??
char optval[IFNAMSZ] = {0};
socklen_t optlen = IFNAMSZ;
if(getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &optval, &optlen) < 0) {
perror("getsockopt");
return 1;
}
if(!optlen) {
printf("invalid optlen\n");
return 1;
}
printf("I/F is on '%s'\n", optval);
#endif
close(sock);
return 0;
Idea based on another post
Create socket
Connect
Get interface address
Get interface id and name from interface address
$ gcc -std=gnu11 -Wall so_q_63899229.c
$ ./a.out 93.184.216.34 # example.org
interface index : 2
interface name : wlp2s0
interface address : 192.168.1.223
remote address : 93.184.216.34
so_q_63899229.c
#include <arpa/inet.h>
#include <assert.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
int sockfd=-1;
void connect2(const char *const dst){
sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd>=3);
struct sockaddr_in sin={
.sin_family=AF_INET,
.sin_port=htons(80),
.sin_addr={}
};
assert(1==inet_pton(AF_INET,dst,&(sin.sin_addr)));
assert(0==connect(sockfd,(struct sockaddr*)(&sin),sizeof(struct sockaddr_in)));
}
void getsockname2(struct sockaddr_in *const sin){
socklen_t addrlen=sizeof(struct sockaddr_in);
assert(0==getsockname(sockfd,(struct sockaddr*)sin,&addrlen));
assert(addrlen==sizeof(struct sockaddr_in));
}
void disconnect(){
close(sockfd);
sockfd=-1;
}
void addr2iface_ifconf(const struct in_addr *const sin_addr,int *const index,char *const name){
struct ifconf ifc={
.ifc_len=0,
.ifc_req=NULL
};
int ioctlfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
assert(ioctlfd>=3);
assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
const int sz=ifc.ifc_len;
assert(sz%sizeof(struct ifreq)==0);
const int n=sz/sizeof(struct ifreq);
char buf[sz];
bzero(buf,sz);
ifc.ifc_buf=buf;
assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
assert(
ifc.ifc_len==sz &&
(char*)ifc.ifc_req==buf
);
for(int i=0;i<n;++i)if(0==memcmp(
&(((struct sockaddr_in*)(&(ifc.ifc_req[i].ifr_addr)))->sin_addr),
sin_addr,
sizeof(struct in_addr)
)){
*index=ifc.ifc_req[i].ifr_ifindex;
assert(name==strncpy(name,ifc.ifc_req[i].ifr_name,IFNAMSIZ));
return;
}
assert(0);
}
int main(int argc,const char *argv[]){
assert(argc==2);
assert(argv[1]&&strlen(argv[1]));
const char *const remoteaddr_s=argv[1];
// const char *const remoteaddr_s="93.184.216.34";
connect2(remoteaddr_s);
struct sockaddr_in ifaddr={};
getsockname2(&ifaddr);
disconnect();
int index=0;
char ifname[IFNAMSIZ]={};
addr2iface_ifconf(&(ifaddr.sin_addr),&index,ifname);
char ifaddr_s[INET_ADDRSTRLEN]={};
assert(ifaddr_s==inet_ntop(AF_INET,&(ifaddr.sin_addr),ifaddr_s,INET_ADDRSTRLEN));
printf("interface index : %d\n",index);
printf("interface name : %s\n",ifname);
printf("interface address : %s\n",ifaddr_s);
printf("remote address : %s\n",remoteaddr_s);
// printf("#%d %s %s -> %s\n",
// index,
// ifname,
// ifaddr_s,
// remoteaddr_s
// );
return 0;
}
Also there doesn't seem to be an identifier named IFNAMSZ. IFNAMSIZ defined in <net/if.h> should be the maxinum legth (including '\0') allowed for the name of any interface IMHO.
Related
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define PORT 8080
#define SHM_SIZE 1024*(512+4)+100*((4*2)+(1024*2))+(4*4)
//---modes-----//
#define NOAUTO "NOAUTO"
#define AUTO "AUTO"
//---commands---//
#define SEND "SEND"
#define FETCH "FETCH"
#define FETCHIF "FETCHIF"
#define QUIT "QUIT"
#define EOF2 "EOF"
typedef char message[512];
typedef struct {
bool is_active;
int start_index;
int end_index;
bool indices[1024];
}circular_queue;
typedef struct {
message message_list[1024];
int last_index;
circular_queue connections[100];
int last_conn_index;
int remained_read[1024];
int num_conn;
int queue_start;
}multicast_queue;
int main(int argc, char const *argv[])
{
//-------------------connect to server-----------------//
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char shmid_s[512] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
read( sock , shmid_s, 512); //-----read shared memory information over socket-----//
int shmid = atoi(shmid_s);
printf("%d\n",shmid );
//---------------------attach to shared memory---------------------------//
if(shmid == -1)
{
perror("shmget");
exit(1);
}
multicast_queue *multicast_queue = shmat(shmid, (void*)0, 0);
if(multicast_queue == (void*)(-1))
{
perror("shmat");
exit(1);
}
int conn_no=multicast_queue->last_conn_index;
int read_index=multicast_queue->queue_start;
char *mode = NOAUTO;
printf("%s\n",mode);
char command[7];
memset(command,0,7);
message messagebody;
while(scanf("%s",command))
{
if(!strcmp(command,SEND))
{
printf("Enter the message to send: ");
scanf("%s", messagebody);
printf("%s %s\n", command, messagebody);
}
else if(!strcmp(command,FETCH))
{
message f_message;
memcpy(f_message, multicast_queue->message_list[read_index],512);
multicast_queue->remained_read[read_index]--;
if(multicast_queue->remained_read[read_index] == 0)
{
multicast_queue->queue_start = (multicast_queue->queue_start+1)%1024;
multicast_queue->connections[conn_no].start_index = (multicast_queue->connections[conn_no].start_index+1)%1024;
}
read_index++;
printf("%s\n", f_message);
}
}
return 0;
}
This is a client code piece of a UNIX domain stream socket project. The shared memory is created by the server code and shmid is send through the socket. Then, to use the shared memory, a pointer of the same type with the constructed data structure over the shared memory is set. Using this pointer the shared memory is attached to this client process. I get a segmentation error whenever i try to access a member of the multicast_queue which is attached to the shared memory (int conn_no=multicast_queue->last_conn_index;). I run this program on a virtual machine Ubuntu. I don't know what the reason behind getting this error is. I also increased the memory size for Ubuntu but it didn't work.
When i try to get client IP,I always get 0.0.0.0 when program running in CentOS,But when the some code running in Ubuntu,It will get the right IP :127.0.0.1
I don't understand that's why.
Please pardon My English.
Here is the code one:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//#include <netinet/ip.h> /* superset of previous */
#define BUF_LEN 1024
int main(int argc, char const *argv[])
{
int sockfd=0;
int bind_ret=0;
int listen_ret=0;
int accept_ret=0;
int read_ret=0;
int write_ret=0;
socklen_t addr_len=0;
char buf[BUF_LEN+1]={0};
struct sockaddr_in client_addr;
struct sockaddr_in ser_addr ={
.sin_family= AF_INET,/* address family: AF_INET */
.sin_port=htons(8888), /* port in network byte order */
.sin_addr.s_addr=inet_addr("127.0.0.1"), /* internet address */
};
//////////////////socket//////////////////////////////////
sockfd=socket(AF_INET ,SOCK_STREAM,0);
if (0>sockfd){
perror("socket");
return -1;
}
////////////////////bind/////////////////////////////////
bind_ret=bind(sockfd, (const struct sockaddr *)&ser_addr,sizeof(ser_addr));
if(0>bind_ret){
perror("bind");
return -1;
}
//////////////////listen//////////////////////////////////
listen_ret=listen(sockfd,10);
if(0>listen_ret){
perror("listen");
return -1;
}
//////////////////accept//////////////////////////////////
accept_ret=accept(sockfd,(struct sockaddr *)&client_addr,&addr_len);
if(0>accept_ret){
perror("accept");
return -1;
}
//////////////////operation_data///////////////////////////////
while(read_ret=read(accept_ret,buf,1024)){ //read data,until no data or error
if(read_ret<0) {
perror("Socket read failed");
return -5;
}
printf("receive:%s\n", buf);
write_ret=write(accept_ret,buf,read_ret);
if(write_ret!=read_ret){
perror("write");
return -1;
}
}
//char *inet_ntoa(client_addr.sin_addr);
char * ip_add =inet_ntoa(client_addr.sin_addr);
int port=client_addr.sin_port;
printf("IP:%s PORT:%d\n", ip_add,port);
close(client_addr);
close(sockfd);
return 0;
}
And code two:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUF_LEN 1024
int main(int argc,char const **argv){
int sockfd=0;
int all_ret=0;
socklen_t addr_len=0;
char buf[BUF_LEN+1]={0};
struct sockaddr_in addr={
.sin_family=AF_INET,/* address family: AF_INET */
.sin_port=htons(8888), /* port in network byte order */
.sin_addr.s_addr=inet_addr("127.0.0.1"), /* internet address */
};
char * ip_add =inet_ntoa(addr.sin_addr);
printf("IP:%s \n", ip_add);
//////////////////socket//////////////////////////////////
sockfd=socket(AF_INET ,SOCK_STREAM,0);
if (0>sockfd){
perror("socket");
return -1;
}
//////////////////connection//////////////////////////////////
// int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
addr_len=sizeof(addr);
all_ret=connect(sockfd, (const struct sockaddr *)&addr,addr_len);
if (0>all_ret){
perror("connect");
return -1;
}
//////////////////data send//////////////////////////////////
all_ret=write(sockfd,"test_by_kevin",14);
if (0>all_ret){
perror("write");
return -1;
}
printf("write:%d\n",all_ret );
//////////////////data receive//////////////////////////////////
all_ret=read(sockfd,buf,1024);
if(all_ret<0){
perror("Socket read failed");
return -1;
}
printf("%s\n",buf);
close(sockfd);
}
The server misses to set addr_len to the size of client_addr before the call to accept().
To fix this add
addr_len = sizeof client_addr;
before calling accept().
I have the following server code
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#define HELLO_PORT 12345
#define HELLO_GROUP "255.0.0.37"
main(int argc, char *argv[])
{
struct sockaddr_in addr;
struct sockaddr_in client,server;
int s,n;
char index;
int f;
char b1[100];
int fd, cnt,i=0;;
struct ip_mreq mreq;
//char *message="Hello, World!";
char *message=NULL;
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
perror("socket");
exit(1);
}
s=socket(AF_INET,SOCK_DGRAM,0);
server.sin_family=AF_INET;
server.sin_port=2000;
server.sin_addr.s_addr=inet_addr("10.42.0.47");
bind(s,(struct sockaddr *)&server,sizeof(server));
printf("\nServer ready,waiting for client....\n");
n=sizeof(client);
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
addr.sin_port=htons(HELLO_PORT);
/* now just sendto() our destination! */
while (1)
{
recvfrom(s,b1,sizeof(b1),0,(struct sockaddr *) &client,&n);
printf("client : %s\n",b1);
//sleep(5);
index=b1[0];
f=b1[0];
//printf("b1[1] is %c\n",index);
//printf("b1[0] is %c\n",f);
f=32;
b1[0]=f;
//printf("new b1[0] is %c\n",b1[0]);
//printf("%s\n",b1);
if(index!='C')
{
if (sendto(fd,b1,sizeof(b1),0,(struct sockaddr *) &addr,sizeof(addr)) < 0)
{
perror("sendto");
exit(1);
}
//i++;
/*if(i>=4)
{
i=0;
}*/
sleep(1);
}
}
}
And the following client code which runs on a different system
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdio.h>
#include <mysql.h>
#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.37"
#define MSGBUFSIZE 1024
main(int argc, char *argv[])
{
MYSQL mysql;
MYSQL_ROW row;
MYSQL_RES *result;
unsigned int num_fields;
unsigned int i;
mysql_init(&mysql);
struct sockaddr_in server;
int s,n;
char b1[100],b2[100],a[100];
char re[100]={0};
char g=" ";
printf("%c\n",re);
strcpy(b2,"1");
char message[20],ch='n';
struct sockaddr_in addr;
int fd, nbytes,addrlen,j=0;
struct ip_mreq mreq;
char msgbuf[MSGBUFSIZE];
u_int yes=1; /*** MODIFICATION TO ORIGINAL */
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
perror("socket");
exit(1);
}
s=socket(AF_INET,SOCK_DGRAM,0);
server.sin_family=AF_INET;
server.sin_port=2000;
server.sin_addr.s_addr=inet_addr("10.42.0.1");
printf("\nClient ready....\n");
n=sizeof(server);
if (!mysql_real_connect(&mysql,"localhost","root","nidhi","project",0,NULL,0))
{
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(&mysql));
}
/**** MODIFICATION TO ORIGINAL */
/* allow multiple sockets to use the same PORT number */
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
exit(1);
}
/*** END OF MODIFICATION TO ORIGINAL */
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
addr.sin_port=htons(HELLO_PORT);
/* bind to receive address */
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0)
{
perror("bind");
exit(1);
}
/* use setsockopt() to request that the kernel join a multicast group */
mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0)
{
perror("setsockopt");
exit(1);
}
/* now just enter a read-print loop */
while (1)
{
/*if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0)
{
perror("recvfrom");
exit(1);
}
printf("the server says: %s\n",msgbuf);*/
printf("would you like to send?(y/n)\n");
scanf("%c",&ch);
fflush(stdin);
if(ch=='y')
{
printf("\nClient:");
gets(a);
printf("%c\n",a);
strcat(b2,a);
printf("%s\n",b2);
sendto(s,b2,sizeof(b2),0,(struct sockaddr *) &server,n);
b2[100]=NULL;
strcpy(b2,"1");
}
addrlen=sizeof(addr);
if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0)
{
perror("recvfrom");
exit(1);
}
printf("the server says: %s\n",msgbuf);
if(mysql_query(&mysql,msgbuf));
else
{
strcpy(re,"Client 1: ");
sendto(s,re,sizeof(re),0,(struct sockaddr *) &server,n);
//printf("inside else case\n");
result=mysql_store_result(&mysql);
//printf("\n after getting the result...\n");
num_fields = mysql_num_fields(result);
//printf("\n after getting numfields...\n");
while ((row = mysql_fetch_row(result)))
{
unsigned long *lengths;
//printf("\n inside while....\n");
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("[%.*s] \t", (int) lengths[i], row[i] ? row[i] : "NULL");
strcat(re,row[i]);
j++;
//printf("%d\n",j);
if(j==4)
{
//printf("the result is .....%s\n",re);
sendto(s,re,sizeof(re),0,(struct sockaddr *) &server,n);
memset(re,0,100);
strcpy(re,"Client 1: ");
j=0;
}
}
printf("\n");
}
}
}
}
I created an adhoc network and it assigned two ip address to the server and the client.
10.42.0.1/24 to the server and 10.42.0.47/24 to client
however the unicast operation from the client to the server is not functioning correctly neither is the multicast from the server to client.
secondly how do i determine whether both the programs are part of the same multicast group. The error on the client is either
setsockopt:invalid argument
or
setsockopt:no such device
Any help on the same is greatly appreciated..!!
There are a lot of potential bugs in your code:
Server:
1.You are not checking if the 's' socket was successfully created. However, your example will work without it since there is enough memory for socket creation.
2.You are not checking the return code from bind(), maybe you can't bind the socket to the port and that's why you get 'invalid argument' error
3.You are not checking the return code from recvfrom() ....
4.The IP 255.0.0.37 is reserved for future use, I am not sure it is valid, why not use a valid ip range?
5.For multicasting you have to use ip addresses in range: 224.0.0.0/4, not 10.0.0.0/8 since it is reserved for local networks.
And regarding the client, you should first make working udp protocol code, and then add mysql to it. You also have to tell us at which line you have the error, otherwise it is difficult to analyse the problem.
I have a C function to check a host and its port, when I use FQDN host name, the function return error like: connect() failed: connect time out, but if I use IP address instead, it seems ok, how to fix this?
Thanks.
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int is_network_up(char *chkhost, unsigned short chkport) {
int sock;
struct sockaddr_in chksock;
struct hostent *host = NULL;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
syslog(LOG_ERR, "socket() creation error: %s", strerror(errno));
return 0;
}
memset(&chksock, 0, sizeof(chksock));
chksock.sin_family = AF_INET;
chksock.sin_port = htons(chkport);
/* get the server address */
if (inet_pton(AF_INET, chkhost, &(chksock.sin_addr.s_addr)) <= 0) {
if ((host = gethostbyname(chkhost)) == NULL) {
syslog(LOG_ERR, "%s", hstrerror(h_errno));
return 0;
}
memcpy(&(chksock.sin_addr.s_addr), &(host->h_addr_list[0]),
sizeof(struct in_addr));
}
/* try to connect */
if (connect(sock, (struct sockaddr *) &chksock, sizeof(chksock)) < 0) {
syslog(LOG_ERR, "connect() failed: %s", strerror(errno));
return 0;
}
close(sock);
return 1;
}
inet_pton() is the wrong task for that. It only accepts numerical addresses.
In former times, people used to use gethostbyname() for name resolution.
But as we have 2012 meanwhile, this method is outdated for several years now, as it is still restricted to AF_INET.
With the program below, you should achieve about the same and stay future compatible.
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
int is_network_up(char *chkhost, unsigned short chkport) {
int sock = -1;
struct addrinfo * res, *rp;
int ret = 0;
char sport[10];
snprintf(sport, sizeof sport, "%d", chkport);
struct addrinfo hints = { .ai_socktype=SOCK_STREAM };
if (getaddrinfo(chkhost, sport, &hints, &res)) {
perror("gai");
return 0;
}
for (rp = res; rp && !ret; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sock == -1) continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) {
char node[200], service[100];
getnameinfo(res->ai_addr, res->ai_addrlen, node, sizeof node, service, sizeof
service, NI_NUMERICHOST);
printf("Success on %s, %s\n", node, service);
ret = 1; /* Success */
}
close(sock);
}
freeaddrinfo(res);
return ret;
}
int main(int argc, char** argv) {
if (argc > 1) {
printf("%s: %d\n", argv[1], is_network_up(argv[1], 22));
}
}
Make sure name resolution is working. See if you can ping the machine by name from the exact same environment in which your code runs.
If ping works, try telnet <machinename> <portnumber> -- If both of those work it is likely a problem with your code (which I did not look at in depth, too sleepy:).
Make sure you're converting anything returned by the OS as an ip address from network order to host order. IIRC, gethostbyname returns binary ip addresses in network order.
ntohl can be used on chksock.sin_addr.s_addr after the memcpy to achieve this.
How do I get the IP address of the local machine using C code?
If there are multiple Interfaces then I should be able to display the IP address of each interface.
NOTE: Do not use any commands like ifconfig within C code to retrieve the IP address.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
int main()
{
int fd;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
snprintf(ifr.ifr_name, IFNAMSIZ, "eth0");
ioctl(fd, SIOCGIFADDR, &ifr);
/* and more importantly */
printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
close(fd);
}
If you want to enumerate all the interfaces, have a look at the getifaddrs() function - if you're on Linux.
With the inputs from Michael Foukarakis I am able to show the IP address for various interfaces on the same machine:
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
struct ifaddrs *ifaddr, *ifa;
int family, s;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
family = ifa->ifa_addr->sa_family;
if (family == AF_INET) {
s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in),
host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (s != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
printf("<Interface>: %s \t <Address> %s\n", ifa->ifa_name, host);
}
}
return 0;
}
Get known all interfaces from "/proc/net/dev". Note: it cannot get all interfaces using ioctl only.
#define PROC_NETDEV "/proc/net/dev"
fp = fopen(PROC_NETDEV, "r");
while (NULL != fgets(buf, sizeof buf, fp)) {
s = strchr(buf, ':');
*s = '\0';
s = buf;
// Filter all space ' ' here
got one interface name here, continue for others
}
fclose(fp);
Then get the address using ioctl():
struct ifreq ifr;
struct ifreq ifr_copy;
struct sockaddr_in *sin;
for each interface name {
strncpy(ifr.ifr_name, ifi->name, sizeof(ifr.ifr_name) - 1);
ifr_copy = ifr;
ioctl(fd, SIOCGIFFLAGS, &ifr_copy);
ifi->flags = ifr_copy.ifr_flags;
ioctl(fd, SIOCGIFADDR, &ifr_copy);
sin = (struct sockaddr_in*)&ifr_copy.ifr_addr;
ifi->addr = allocating address memory here
bzero(ifi->addr, sizeof *ifi->addr);
*(struct sockaddr_in*)ifi->addr = *sin;
/* Here also you could get netmask and hwaddr. */
}