ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I want to send Received UDP Packets to neighbor MAC Address.
Anyone can guide me to how to do it?
I can received UDP packets and then forward to unicast address as follow:
How can i modify this codes (Maybe Last Line) to send the received packets to destination MAC Address instead of destination IPv6 Address?
Code:
int main(int argc, char ** argv)
{
int s,s1;
struct sockaddr_in6 a,a1;
if (argc != 4) {
fprintf(stderr, "USAGE: unicast_recv udp_port MAC_Add Forward_MAC_Port\n");
exit(-1);
}
memset(&a, 0, sizeof(a));
a.sin6_addr = in6addr_any;
a.sin6_port = htons(atoi(argv[1]));
s = socket(AF_INET6, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
exit(-1);
}
if (bind(s, (struct sockaddr*)&a, sizeof(a)) < 0)
{
perror("bind");
exit(-1);
}
//Open New Port for Sending Packets to MAC Address
s1 = socket (AF_INET6, SOCK_DGRAM, 0);
if (s1<0) {
perror("socket");
exit(-1);
}
memset (&a1, 0, sizeof(a1));
a1.sin6_port = htons (atoi(argv[3]));
if (inet_pton (AF_INET6, argv[2], &a1.sin6_addr) <= 0)
{
perror ("inet_pton");
exit(-1);
}
a1.sin6_family = AF_INET6;
// End of Opening New Port
while (1) {
unsigned char buffer[2000], pkt_flg[100];
int i;
struct timeval now;
struct sockaddr_in6 mcast_addr;
int addr_len = sizeof(struct sockaddr_in6);
gettimeofday(&now, NULL);
i = recvfrom(s, buffer, 2000, 0, (struct sockaddr_in6*)&mcast_addr, &addr_len);
if (sendto(s1, buffer, 1400, 0, (struct sockaddr_in6*)&a1, sizeof(a1)) == -1)
perror("sendto");
}
}
If you are trying to use the MAC as the destination, you can send raw packets, and format them as UDP yourself. If you can't use root privileges required to send raw packets, then you will have to lookup the IP by MAC, and send UDP packets. You would then have to use some hackery to determine the IP of the host by reverse lookup of the IP from the MAC. arp will list all of the IPs & MACs already known to your IP stack, however the target IP isn't guaranteed to exist in the arp table at any given time. You can use a brute force method to get MACs into the arp table by doing something like a ping of every IP in the range you think your target host is in, and then checking the arp table to find the target MAC.
Your request seems highly unusual. What are you really trying to accomplish?
If you are trying to use the MAC as the destination, you can send raw packets, and format them as UDP yourself.
I should format them as UDP at destination, right?
I can use root privileges...
If i get somehow the MAC of destination host, how can i forward a received packet as raw packet to that particular MAC address?
Could you please look at the following command where i received a "buffer" from one host? and tell me how to forward this buffer to a destination known MAC address.
Code:
i = recvfrom(s, buffer, 2000, 0, (struct sockaddr_in6*)&mcast_addr, &addr_len);
I should format them as UDP at destination, right?
Not sure exactly what you mean by this. If you want the destination host to receive the packet as a UDP datragram, then you would have to format it as such. That, of course, begs the question of why you wouldn't simply send it as a UDP datagram using the existing IP stack. The whole premise of your objective seems peculiar in this sense.
You use SOCK_RAW type (man socket) to send raw ethernet datagrams. In that case, your destination address is specified as a MAC, as the IP stack is not used to send the data. In use, the raw packet is composed, including the ethernet header containing the source and destination MACs, and all of the other fields required for a valid ethernet frame. The data received in your 'buffer' array would become part of the payload field of the ethernet frame, and would follow any UDP/IP header.
Normally, you would only want to do this to send non-IP ethernet traffic. To send IP traffic this way seems highly redundant. Why would you want to use a MAC as the basis for addressing in an IP network?
Actually i want to receive the multicast packets at access point and unicast them to many MAC addresses of users instead of multicast to many IP addresses of users.
As you said, I have to use SOCK_RAW with the MAC address as destination. Can i send RAW packets to two or three MAC addresses at the same time?
Actually i want to receive the multicast packets at access point and unicast them to many MAC addresses of users instead of multicast to many IP addresses of users.
As theNbomr already said, this is a big waste of throughput. The multicast protocol is done for that, once the peer that need the stream as done the multicast group membership request, it will receive datagram (switches between emitter and receiver will forward datagram), but no forwarding before the membership request...
As theNbomr already said, this is a big waste of throughput.
Thanks jf.argentino for your reply.
Yes you are right. I just want to test some scenario for my research.
So far, I've managed to send UDP packets from server, then received on another PC (say access point) and forward to destination MAC address (receiver).
here is the code to receive and forward to MAC destination on access point:
Code:
int main(int argc, char ** argv)
{
int s;
struct sockaddr_in6 a;
if (argc != 2) {
fprintf(stderr, "usage: recv_fw_mac udp_port\n");
exit(-1);
}
memset(&a, 0, sizeof(a));
a.sin6_addr = in6addr_any;
a.sin6_port = htons(atoi(argv[1]));
s = socket(AF_INET6, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
exit(-1);
}
if (bind(s, (struct sockaddr*)&a, sizeof(a)) < 0) {
perror("bind");
exit(-1);
}
printf("ser_num\trecv_time\t send_t\n");
while (1) {
unsigned char buffer[1400];
int i;
struct timeval now;
struct sockaddr_in6 mcast_addr;
int addr_len = sizeof(struct sockaddr_in6);
gettimeofday(&now, NULL);
i = recvfrom(s, buffer, 1400, 0, (struct sockaddr*)&mcast_addr, &addr_len);
printf("%s\t%d.%d\t%s\n", buffer, now.tv_sec, now.tv_usec, buffer+8);
//New Socket for MAC Forwarding.
int s1;
struct sockaddr_ll dstaddr;
s1 = socket(PF_PACKET,SOCK_DGRAM,ETH_P_IP);
if (s1<0) {
perror("socket");
return 1;
}
/* now fill up the sockaddr_ll to send */
memset(&dstaddr,0,sizeof(struct sockaddr_ll));
dstaddr.sll_protocol=htons(ETH_P_IP);
dstaddr.sll_ifindex=5;
dstaddr.sll_hatype=ARPHRD_ETHER;
dstaddr.sll_pkttype=PACKET_OUTGOING;
dstaddr.sll_halen=ETH_ALEN; /* defined as 6 */
dstaddr.sll_addr[0]=0x00;
dstaddr.sll_addr[1]=0x50; /* the hw addr of the */
dstaddr.sll_addr[2]=0x8D; /* machine i want to */
dstaddr.sll_addr[3]=0x39; /* send it to */
dstaddr.sll_addr[4]=0x5A;
dstaddr.sll_addr[5]=0xF1;
if ( sendto(s1,buffer,sizeof(buffer),0,(struct sockaddr *)&dstaddr,sizeof(struct sockaddr_ll))<0)
{
perror("sendto");
return 1;
}
// End of New Socket
}
}
when i check on receiver with "#tcpdump -i eth0" it shows something is receiving as follow:
What do these mean?
I've tried to receive the RAW packets on receiver with this program but it shows nothing.
Code:
int main()
{
int s;
struct sockaddr_ll a;
memset(&a, 0, sizeof(a));
s = socket(PF_PACKET, SOCK_DGRAM, ETH_P_IP);
if (s < 0) {
perror("socket");
exit(-1);
}
printf("ser_num\trecv_time\t send_t\n");
while (1) {
unsigned char buffer[1400];
int i;
struct timeval now;
gettimeofday(&now, NULL);
i = recvfrom(s, buffer, 1400, 0, NULL, NULL);
printf("%s\t%d.%d\t%s\n", buffer, now.tv_sec, now.tv_usec, buffer+8);
}
}
I want to show the "buffer" on receiver side which is sending from server.
Could someone please help me how to do that?
Is my program to receive the RAW packets correct?
Do I need to get RAW packets from specified port on receiver? if yes, how?
I've realized that to receive the RAW packets, the following steps are needed to be done:
Quote:
1. Create RAW socket.
2. Bind socket to interface.
3. Start Sniffing the packets (recvfrom()).
4. Parse ethernet header.
5. Parse IP header.
6. Parse TCP header.
7. Parse Data.
To access the data, It is necessary to decode the data portion of the packet by removing ethernet-IP-TCP headers which are received in RAW packets.
Please look at my last post, the way i forward the received UDP packet to MAC dest address is correct?
do i need to add ethernet and IP headers before forwarding UDP packets?
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.