Skip to content
This repository was archived by the owner on Dec 25, 2018. It is now read-only.

Commit 0a97a1e

Browse files
committed
add hw4
1 parent 7f8a9f9 commit 0a97a1e

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

hw4/Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CC=gcc
2+
CFLAGS=-Os -Wall
3+
4+
all: source.c
5+
${CC} ${CFLAGS} source.c -o lanchat
6+
strip lanchat
7+
8+
.PHONY: format
9+
format:
10+
clang-format -style=Google -i source.c
11+
12+
.PHONY: clean
13+
clean:
14+
rm -f lanchat

hw4/README

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Chat in LAN
2+
3+
## Usage
4+
5+
`make` builds a binary `lanchat`
6+
7+
## Note
8+
9+
- the source interface is chosen by the last available interface (UP)
10+
- the registered protocol is 0x801 (ETH_P_IP + 1)

hw4/source.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#include <arpa/inet.h>
2+
#include <ifaddrs.h>
3+
#include <linux/if_packet.h>
4+
#include <net/ethernet.h>
5+
#include <net/if.h>
6+
#include <netinet/in.h>
7+
#include <signal.h>
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <string.h>
11+
#include <sys/ioctl.h>
12+
#include <sys/socket.h>
13+
#include <sys/types.h>
14+
#include <time.h>
15+
#include <unistd.h>
16+
17+
int main(void) {
18+
printf("Enumerated network interfaces:\n");
19+
struct ifaddrs *ifap, *it;
20+
getifaddrs(&ifap);
21+
// MAC address
22+
char MAC[12][18];
23+
int index = 0;
24+
for (it = ifap; it; it = it->ifa_next) {
25+
unsigned char *mac = ((struct sockaddr_ll *)it->ifa_addr)->sll_addr;
26+
if (it->ifa_addr->sa_family == AF_INET && (it->ifa_flags & IFF_UP) == 1)
27+
index = if_nametoindex(it->ifa_name);
28+
if (it->ifa_addr->sa_family == AF_PACKET)
29+
sprintf(MAC[if_nametoindex(it->ifa_name)],
30+
"%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3],
31+
mac[4], mac[5]);
32+
}
33+
// Network address
34+
for (it = ifap; it; it = it->ifa_next) {
35+
if (it->ifa_addr->sa_family == AF_INET) {
36+
char inet_addr[INET_ADDRSTRLEN], netmask_addr[INET_ADDRSTRLEN],
37+
masked_addr[INET_ADDRSTRLEN];
38+
struct in_addr *it_addr = &((struct sockaddr_in *)it->ifa_addr)->sin_addr,
39+
*it_netmask =
40+
&((struct sockaddr_in *)it->ifa_netmask)->sin_addr,
41+
masked_in;
42+
inet_ntop(AF_INET, it_addr, inet_addr, INET_ADDRSTRLEN);
43+
inet_ntop(AF_INET, it_netmask, netmask_addr, INET_ADDRSTRLEN);
44+
masked_in.s_addr = it_addr->s_addr | (~it_netmask->s_addr);
45+
inet_ntop(AF_INET, &masked_in, masked_addr, INET_ADDRSTRLEN);
46+
unsigned int idx = if_nametoindex(it->ifa_name);
47+
printf("%u - %-8s %16s %#x (%s) %s\n", idx, it->ifa_name, inet_addr,
48+
ntohl(it_netmask->s_addr), masked_addr, MAC[idx]);
49+
}
50+
}
51+
freeifaddrs(ifap);
52+
// username
53+
srand(time(NULL));
54+
char username[48] = "[";
55+
sprintf(username, "%05d%05d[", rand() % 100000, rand() % 100000);
56+
printf("Enter your name: ");
57+
scanf("%s", username + 11);
58+
printf("Welcome, '%s'!\n", username + 11);
59+
struct ether_header *hdr;
60+
const size_t len_ether_header = sizeof(struct ether_header),
61+
user_len = strlen(username);
62+
const unsigned short protocol = htons(ETH_P_IP + 1);
63+
// child receive message
64+
unsigned int pid;
65+
if ((pid = fork()) == 0) {
66+
char recv_msg[4096];
67+
int recv_sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
68+
while (1) {
69+
recv(recv_sock, recv_msg, 4096, 0);
70+
hdr = (struct ether_header *)recv_msg;
71+
if (hdr->ether_type == protocol &&
72+
strncmp(username, recv_msg + len_ether_header, user_len) != 0) {
73+
unsigned char *mac = hdr->ether_shost;
74+
printf(">>> <%02x:%02x:%02x:%02x:%02x:%02x> %s", mac[0], mac[1], mac[2],
75+
mac[3], mac[4], mac[5], recv_msg + len_ether_header + 10);
76+
}
77+
}
78+
return 0;
79+
}
80+
// link layer address
81+
struct sockaddr_ll addr;
82+
addr.sll_family = AF_PACKET;
83+
addr.sll_protocol = ETH_P_IP + 1;
84+
addr.sll_halen = ETH_ALEN;
85+
addr.sll_ifindex = index;
86+
for (size_t i = 0; i < 6; ++i) addr.sll_addr[i] = 0xff;
87+
// ethernet header
88+
char send_msg[4096] = {};
89+
hdr = (struct ether_header *)send_msg;
90+
for (size_t i = 0; i < 6; ++i) {
91+
char m1 = MAC[index][i * 3], m2 = MAC[index][i * 3 + 1];
92+
int d1 = m1 >= '0' && m1 <= '9' ? m1 - '0' : m1 - 'a' + 10,
93+
d2 = m2 >= '0' && m2 <= '9' ? m2 - '0' : m2 - 'a' + 10;
94+
hdr->ether_shost[i] = d1 * 16 + d2;
95+
hdr->ether_dhost[i] = 0xff;
96+
}
97+
hdr->ether_type = htons(ETH_P_IP + 1);
98+
// send message
99+
size_t len = len_ether_header, msg_len = 0;
100+
for (size_t i = 0; i < user_len; ++i) send_msg[len++] = username[i];
101+
send_msg[len++] = ']';
102+
send_msg[len++] = ':';
103+
send_msg[len++] = ' ';
104+
int send_sock = socket(AF_PACKET, SOCK_RAW, protocol);
105+
while (fgets(send_msg + len, 4000, stdin)) {
106+
msg_len = strlen(send_msg + len) + 1;
107+
if (msg_len == 2) continue;
108+
send_msg[len + msg_len] = '\0';
109+
sendto(send_sock, send_msg, len + msg_len, 0, (struct sockaddr *)&addr,
110+
sizeof(struct sockaddr_ll));
111+
}
112+
kill(pid, SIGTERM);
113+
return 0;
114+
}

0 commit comments

Comments
 (0)