LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-14-2010, 02:39 AM   #1
nainesh
LQ Newbie
 
Registered: May 2010
Location: Ahmedabad-Gujarat
Distribution: Fedora
Posts: 27

Rep: Reputation: 0
Remote Client Mac Address on socket descriptor


Hi All,
I want to get the connected client MAC Address after accept() call. I can get the IP address of the client but i don't know how to get the client MAC Address in my this programme. Here I am Posting my Code. Any Guide Line or Solution will be appreciated.

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netdb.h>
#include<errno.h>
#include<string.h>
int main()
{
int socket1, socket2;
socket1 = 0;
socket2 = 0;
struct sockaddr_in server, client;
int returnstatus = 0;
socket1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(socket1 == -1)
{
perror("socket()");
}

server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
returnstatus = bind(socket1, (struct sockaddr*)&server, sizeof(server));
if(returnstatus == -1)
{
perror("bind()");
}
returnstatus = listen(socket1, 5);
if(returnstatus == -1)
{
perror("listen()");
}
for(;
{
int buffr[4];
int addrlen;
addrlen = sizeof(client);
socket2 = accept(socket1, (struct sockaddr *)&client, &addrlen);
printf("%s\n",inet_ntoa(client.sin_addr));
printf("%d\n",(int) ntohs(client.sin_port));
if (socket2 == -1)
{
perror("accept()");
}
returnstatus = read(socket2, buffr, sizeof(buffr));

if(returnstatus == -1)
{
perror("read()");
}
int c[2];
int *w;
c[0] = buffr[0] + buffr[1];
w = c;
returnstatus = write(socket2, w, sizeof(c));
if(returnstatus == -1)
{
perror("write()");
}
close(socket2);

}
close(socket1);
return 0;
}

int addition(int x, int y)
{
int z;
z = x + y;
return(z);
}

Thanks For Advance.
 
Old 12-14-2010, 03:12 AM   #2
acid_kewpie
Moderator
 
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,417

Rep: Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985Reputation: 1985
It's technically none of your business what the mac address is. once you have crossed a layer 3 barrier, i.e. a router / firewall the MAC address of the client is not in the tcp/ip headers at all, and You'd only get it in the form of contextual data actually passed from the client of it's own volition.
 
Old 12-15-2010, 12:56 AM   #3
nainesh
LQ Newbie
 
Registered: May 2010
Location: Ahmedabad-Gujarat
Distribution: Fedora
Posts: 27

Original Poster
Rep: Reputation: 0
Dear Acid_Kewpie,
Thanks for reply but i just only learn. you are right for remote connectivity, but i am just asking for local network.
Regards,
Nainesh
 
Old 12-15-2010, 09:28 AM   #4
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
TCP is independent of any MAC level protocols. In practice, when using an ethernet link layer, the TCP stack uses ARP to obtain the MAC of the connected host or router. There is the SIOCGARP ioctl() service which may allow you to query the arp cache. When you've Googled 'linux ioctl SIOCGARP', you will find numerous instances of a code snippet which I was able make work on my RHEL 5 host.

If learning the MAC address of a specified host is your only objective, then the arp tool is probably what you want to use.

--- rod.
 
Old 12-16-2010, 11:46 PM   #5
nainesh
LQ Newbie
 
Registered: May 2010
Location: Ahmedabad-Gujarat
Distribution: Fedora
Posts: 27

Original Poster
Rep: Reputation: 0
Dear rod,
Can i mean that there is no MAC Address in Packet which i will received on socket descriptor which is returned by accept call ? Should i have do the arp query to connected client ? if i getting your point, then please guide me in my code. i have also tried it with ioctl command after googling lots of.

Regards,
Nainesh Prajapati
 
Old 12-17-2010, 12:39 AM   #6
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
You don't get to see the whole ethernet frame, only the payload part of the TCP or UDP packet. TCP works at a level above the datalink layer, and is fully independent of it. TCP could work over any number of datalink layers, some of which may not have a MAC or other distinguishing ID. If you have a currently connected client, and there is a MAC associated with the host, then almost by definition, the host will be fresh in the ARP cache, and you can query it. If the host is beyond a router, you will only see the MAC of the router.
--- rod.
 
Old 12-17-2010, 11:20 PM   #7
nainesh
LQ Newbie
 
Registered: May 2010
Location: Ahmedabad-Gujarat
Distribution: Fedora
Posts: 27

Original Poster
Rep: Reputation: 0
Thanks Dear,
Now i have got your point. means if want to get the mac address of client then i have to make the raw socket and have to learn some about ioctl. i have seen the ioctl with SIOCGARP on google and i have tried it in my programme. but it sill give me error "Protocol Family Not Supported". So, can you give me source code which can fit in my above given source code or any simple server/client source code. It will be help full for me to learn. i am not able to join any academy to learn C programming.

Thanks & Regards,
Nainesh Prajapati
 
Old 12-22-2010, 09:34 AM   #8
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Only my mother ever called me 'Dear'...

Show us what you tried in your program, and maybe we can help to fix it. Please post source code in [CODE ][/CODE] tags to preserve any formatting.

--- rod.
 
Old 12-22-2010, 11:24 PM   #9
nainesh
LQ Newbie
 
Registered: May 2010
Location: Ahmedabad-Gujarat
Distribution: Fedora
Posts: 27

Original Poster
Rep: Reputation: 0
Ok friend,
Please get here code.

Code:
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netdb.h>
#include<errno.h>
#include<string.h>
#include<netinet/if_ether.h>
#include<net/if.h>
#include<linux/sockios.h>
int main()
{
  int socket1, socket2;
  socket1 = 0;
  socket2 = 0;
  struct sockaddr_in server, client;
  int returnstatus = 0;
socket1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(socket1 == -1)
{
  perror("socket()");
}

server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
returnstatus = bind(socket1, (struct sockaddr*)&server, sizeof(server));
if(returnstatus == -1)
{
  perror("bind()");
}
returnstatus = listen(socket1, 5);
if(returnstatus == -1)
{
 perror("listen()");
}
for(;;)
{
  int buffr[4];
  int addrlen, n;
  addrlen = sizeof(client);
  socket2 = accept(socket1, (struct sockaddr *)&client, &addrlen);
	printf("%s\n",inet_ntoa(client.sin_addr));
	printf("%d\n",(int) ntohs(client.sin_port));
struct arpreq arpreq_;
bzero(&arpreq_, sizeof(struct arpreq));

if( ( n = ioctl(socket2, SIOCGARP, &arpreq_) ) < 0 ){
perror("ioctl");
}

unsigned char *ptr = &arpreq_.arp_ha.sa_data[0];
printf("MAC: %x:%x:%x:%x:%x:%x\n", *ptr, *(ptr+1), *(ptr+2), *(ptr+3),
*(ptr+4), *(ptr+5));

if (socket2 == -1)
{
  perror("accept()");
}
returnstatus = read(socket2, buffr, sizeof(buffr));

if(returnstatus == -1)
{
  perror("read()");
}
int c[2]; 
int *w;
c[0] = buffr[0] + buffr[1];
w = c;
returnstatus = write(socket2, w, sizeof(c));
if(returnstatus == -1)
{
 perror("write()");
}
close(socket2);

}
close(socket1);
return 0;
}

int addition(int x, int y)
{
 int z;
 z = x + y;
 return(z);
}
 
Old 01-04-2011, 01:51 PM   #10
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Sorry to have left you for a while. I actually had trouble re-finding the code on the internet, after finding numerous instances on my first search. The version I had tried and tested was on a computer that was unavailable to me for some time. Anyway, here it is, and it works for me. There is a network device name hardcoded into the source code; edit as necessary

Code:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <linux/sockios.h>

static char *ethernet_mactoa(struct sockaddr *addr) { 
static char buff[256]; 
	
	unsigned char *ptr = (unsigned char *) addr->sa_data;

	sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X", 
		(ptr[0] & 0xff), (ptr[1] & 0xff), (ptr[2] & 0xff), 
		(ptr[3] & 0xff), (ptr[4] & 0xff), (ptr[5] & 0xff)); 

return (buff); 

} 


int main(int argc, char *argv[]) {
int                 s;
struct arpreq       areq;
struct sockaddr_in *sin;
struct in_addr      ipaddr;

	if (argc != 2) {
		fprintf(stderr, "-- Usage: %s ipaddress\n", argv[0]);
		exit(1);
	}
	
	/* Get an internet domain socket. 
	*/
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
		perror("socket");
		exit(1);
	}
	
	/* Make the ARP request. 
	*/
	memset(&areq, 0, sizeof(areq));
	sin = (struct sockaddr_in *) &areq.arp_pa;
	sin->sin_family = AF_INET;

	if (inet_aton(argv[1], &ipaddr) == 0) {
		fprintf(stderr, "-- Error: bad dotted-decimal IP '%s'.\n",
				argv[1]);
		exit(1);
	}
	
	sin->sin_addr = ipaddr;
	sin = (struct sockaddr_in *) &areq.arp_ha;
	sin->sin_family = ARPHRD_ETHER;
	
	strncpy(areq.arp_dev, "eth1", 15);
	
	if (ioctl(s, SIOCGARP, (caddr_t) &areq) == -1) {
		perror("-- Error: unable to make ARP request, error");
		exit(1);
	}
	printf("%s (%s) -> %s\n", argv[1], 
			inet_ntoa(&((struct sockaddr_in *) &areq.arp_pa)->sin_addr), 
			ethernet_mactoa(&areq.arp_ha));
	return 0;
}
--- rod.
 
Old 01-04-2011, 11:58 PM   #11
nainesh
LQ Newbie
 
Registered: May 2010
Location: Ahmedabad-Gujarat
Distribution: Fedora
Posts: 27

Original Poster
Rep: Reputation: 0
Thumbs up

Thanks rod,
it is working fine. i will attach it in my code. thank you so much.

Regards,
Nainesh Prajapati
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Find out a remote mac address antken Linux - Networking 5 05-05-2009 03:17 PM
MAC address of remote PC nickraj Linux - Networking 13 01-28-2007 12:53 AM
How to find an IP address from the MAC address of a remote machine ? jitz Linux - General 3 01-03-2006 07:55 AM
fseek on a socket descriptor to discard socket buffer? Thinking Programming 1 12-06-2005 09:15 PM
unable to obtain socket and address of client David@330 Linux - Newbie 5 06-01-2005 09:23 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:09 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration