-
Notifications
You must be signed in to change notification settings - Fork 0
/
mping.c
152 lines (119 loc) · 3.7 KB
/
mping.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <netinet/in.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h> //For standard things
#include <stdlib.h> //malloc
#include <string.h> //strlen
#include <netinet/ip_icmp.h> //Provides declarations for icmp header
#include <netinet/udp.h> //Provides declarations for udp header
#include <netinet/tcp.h> //Provides declarations for tcp header
#include <netinet/ip.h> //Provides declarations for ip header
#include <netinet/if_ether.h> //For ETH_P_ALL
#include <net/ethernet.h> //For ether_header
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/ethernet.h> /* the L2 protocols */
#include <stdio.h>
#include <string.h>
#include "etheraddr.h"
#include "mping.h"
#define ARGV_INDEX_DEV (1)
#define ARGV_INDEX_MACARR (2)
static int _get_iface_index(int socket, const char *iface_name) {
struct ifreq ifr;
// Ugly hard coded, will be changed
memset(&ifr, 0, sizeof(struct ifreq));
strncpy((char *)ifr.ifr_name, iface_name, IFNAMSIZ);
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0){
perror("ioctl: ");
exit(EXIT_FAILURE);
}
return ifr.ifr_ifindex;
// Always success here 2 for eth0, 3 for eth1
} // _get_iface_index()
static int _link_fd(uint16_t ethertype, int broadcastEnable)
{
int err = -1;
int fd = -1;
fd = socket(AF_PACKET, SOCK_DGRAM ,htons(ethertype));
if(fd < 0) {
perror("socket()");
exit(EXIT_FAILURE);
}
if(broadcastEnable != 0)
{
err = setsockopt(fd,
SOL_SOCKET,
SO_BROADCAST,
&broadcastEnable,
sizeof(broadcastEnable));
if(err < 0) {
perror("setsockopt()");
exit(EXIT_FAILURE);
}
}
return fd;
} // _link_fd()
static void _bind_fd(
/* output. it will be filed. */
struct sockaddr_ll *ifaddr,
/* input. sock_raw should be AF_PACKET && SOCKDGRAM */
int sock_raw,
/* input. ex) "eth0" */
const char *iface_name)
{
socklen_t len = sizeof(struct sockaddr_ll);
ifaddr->sll_family = PF_PACKET;
ifaddr->sll_ifindex =_get_iface_index(sock_raw, iface_name);
ifaddr->sll_protocol = 0; // this field will be ignored
// because the socket was created with protocol field.
if((bind(sock_raw, (const struct sockaddr *)ifaddr, sizeof(*ifaddr))) == -1)
{
perror("bind: ");
exit(EXIT_FAILURE);
}
// get mac address which is bound to interface.
getsockname(sock_raw, (struct sockaddr*)ifaddr, &len);
return;
} // _bind_fd()
int main(int argc, char **argv)
{
int broadcastEnable = 0;
int fd = _link_fd(ETHERTYPE_MPING, broadcastEnable);
struct sockaddr_ll addr_src[1];
struct sockaddr_ll addr_dst[1];
ether_addr_t addr;
char buf[1024] = "Hello MPING";
size_t buflen = strlen(buf);
ether_str_to_addr(argv[ARGV_INDEX_MACARR], addr);
_bind_fd(addr_src, fd, argv[ARGV_INDEX_DEV]);
addr_dst->sll_family = AF_PACKET;
addr_dst->sll_protocol = htons(ETHERTYPE_MPING);
addr_dst->sll_ifindex = addr_src->sll_ifindex;
addr_dst->sll_hatype = ARPHRD_ETHER;
addr_dst->sll_pkttype = PACKET_OTHERHOST;
addr_dst->sll_halen = 6;
memcpy(addr_dst->sll_addr, addr, ETHER_ADDR_LEN);
for(int i=1;;i++)
{
int sendbyte = sendto (fd,
buf,
buflen,
0, /* flags */
(struct sockaddr*)addr_dst,
sizeof(addr_dst)
);
printf("#%d(%d bytes)\n", i, sendbyte);
sleep(1);
}
return 0;
}