From aae17bb2385f245345f752129bc888a0a9a1031f Mon Sep 17 00:00:00 2001 From: Hanzhang Ma Date: Sat, 23 Nov 2024 18:09:49 +0100 Subject: [PATCH] add 203 codes --- Blatt02/A203/arp_packet.c | 179 +++++++++++++++++++++++++++++++++++ Blatt02/A203/arp_packet.h | 43 +++++++++ Blatt02/A203/arp_packet_st.h | 36 +++++++ Blatt02/A203/tuntap.c | 108 +++++++++++++++++++++ Blatt02/A203/util.c | 46 +++++++++ Blatt02/A203/util.h | 16 ++++ 6 files changed, 428 insertions(+) create mode 100644 Blatt02/A203/arp_packet.c create mode 100644 Blatt02/A203/arp_packet.h create mode 100644 Blatt02/A203/arp_packet_st.h create mode 100644 Blatt02/A203/tuntap.c create mode 100644 Blatt02/A203/util.c create mode 100644 Blatt02/A203/util.h diff --git a/Blatt02/A203/arp_packet.c b/Blatt02/A203/arp_packet.c new file mode 100644 index 0000000..7080b82 --- /dev/null +++ b/Blatt02/A203/arp_packet.c @@ -0,0 +1,179 @@ +#include "arp_packet.h" + +translation_table_entry translation_table[TB_L]; +int entry_length = 0; +int entry_count = 0; + +int search_entry(translation_table_entry * entry, uint32_t ip, int * table_id){ + for(size_t i = 0 ; i < entry_length; i++){ + if(ip == translation_table[i].ar_spa){ + entry->ar_pro = translation_table[i].ar_pro; + entry->ar_spa = translation_table[i].ar_spa; + for(size_t j = 0 ; j < MAC_A_S ; j++){ + entry->ar_sha[j] = translation_table[i].ar_sha[j]; + } + *table_id = i; + translation_table[i].count = entry_count; + entry_count++; + return SUCCESS; + } + } + return FAILED; +} + +int update_entry(int table_id, uint8_t * mac_ares){ + if(table_id >= TB_L) { + perror("table_id wrong"); + return FAILED; + } + for(size_t j = 0 ; j < MAC_A_S ; j++){ + translation_table[table_id].ar_sha[j] = mac_ares[j]; + } + return SUCCESS; +} + +int insert_entry(translation_table_entry * entry){ + int final_id = entry_length; + if(entry_length == TB_L){ + int minn = 1<<31; + int id = -1; + for(size_t i = 0 ; i < entry_length ; i++){ + if(translation_table[i].count < minn){ + minn = translation_table[i].count; + id = i; + } + } + final_id = id; + } + translation_table[final_id].ar_pro = entry->ar_pro; + translation_table[final_id].ar_spa = entry->ar_spa; + for(size_t j = 0 ; j < MAC_A_S ; j++){ + translation_table[final_id].ar_sha[j] = entry->ar_sha[j]; + } + translation_table[final_id].count = entry_count; + entry_count++; + return SUCCESS; +} + +int parse_arp_packet(mac_hdr * hdr, pkt_data * pkt, uint8_t * buf, size_t size){ + size_t offset = 0; + for(size_t i=offset;idest_ares[i-offset]=buf[i]; offset += MAC_A_S; + for(size_t i=offset;isend_ares[i-offset]=buf[i]; offset += MAC_A_S; + hdr->pro_T =combine_uint8(buf[offset], buf[offset+1]); offset += 2; + pkt->ar_hrd=combine_uint8(buf[offset], buf[offset+1]); offset += 2; + pkt->ar_pro=combine_uint8(buf[offset], buf[offset+1]); offset += 2; + pkt->ar_hln=buf[offset]; offset += 1; + pkt->ar_pln=buf[offset]; offset += 1; + pkt->ar_op =combine_uint8(buf[offset], buf[offset+1]); offset += 2; + for(size_t i=offset;iar_sha[i-offset]=buf[i]; offset += MAC_A_S; + pkt->ar_spa = combine_uint8_32(buf+offset); offset+=IP_A_S; + for(size_t i=offset;iar_tha[i-offset]=buf[i]; offset += MAC_A_S; + pkt->ar_tpa = combine_uint8_32(buf+offset); offset+=IP_A_S; +} + +int receive_arp_packet(mac_hdr * hdr, pkt_data * pkt, uint8_t * buf, size_t size, uint8_t * local_ip, uint8_t * local_mac){ + uint32_t local_ip32 = combine_uint8_32(local_ip); + + if(size < 42) { + printf("The packet is too short! This is not an ARP packet!\n"); + return FAILED; + } + parse_arp_packet(hdr, pkt, buf, size); + if(hdr->pro_T != ETHER_T_ARP) { + printf("The packet is not ARP packet!\n"); + return FAILED; + } + if(pkt->ar_hrd != ARES_HRD_ETHERNET){ + printf("The hardware is not Ethernet!\n"); + return FAILED; + } + if(pkt->ar_pro!= ARES_PRO_IP){ + printf("The protocol is not IPv4!\n"); + return FAILED; + } + + int merge_flag = FALSE; + int table_id = -1; + + translation_table_entry entry; + if(search_entry(&entry, pkt->ar_spa, &table_id) == SUCCESS){ + update_entry(table_id, pkt->ar_sha); + merge_flag = TRUE; + } + if(merge_flag == FALSE){ + entry.ar_pro = pkt->ar_pro; + entry.ar_spa = pkt->ar_spa; + for(size_t j = 0 ; j < MAC_A_S ; j++){ + entry.ar_sha[j] = pkt->ar_sha[j]; + } + } + + if(pkt->ar_op==ARES_OP_REQ){ + printf("This is a request packet!\n"); + + uint32_t tmp_ip; + uint8_t tmp_mac[MAC_A_S]; + tmp_ip = pkt->ar_spa; pkt->ar_spa = pkt->ar_tpa; pkt->ar_tpa = tmp_ip; + memcpy(tmp_mac, pkt->ar_sha, MAC_A_S); memcpy(pkt->ar_sha, pkt->ar_tha, MAC_A_S); memcpy(pkt->ar_tha, tmp_mac, MAC_A_S); + + memcpy(pkt->ar_sha, local_mac, MAC_A_S); + pkt->ar_spa = local_ip32; + + pkt->ar_op = ARES_OP_REP; + memcpy(tmp_mac, hdr->dest_ares, MAC_A_S); memcpy(hdr->dest_ares, hdr->send_ares, MAC_A_S); memcpy(hdr->send_ares, tmp_mac, MAC_A_S); + memcpy(hdr->send_ares, local_mac, MAC_A_S); + return SUCCESS; + } + printf("This is a response packet!\n"); + return SUCCESS; +} + +int cv_uint16_to_uint8(uint8_t * tmp, uint16_t number){ + tmp[1] = number & 0x00FF; + tmp[0] = (number >> 8 ) & 0x00FF; + return SUCCESS; +} + +int cv_arp_packet_to_uint8(uint8_t * resp_buffer, const pkt_data* pkt, const mac_hdr *hdr, size_t length){ + if( length < sizeof(pkt_data) + sizeof(mac_hdr) ) return FAILED; + memcpy(resp_buffer, hdr->dest_ares, MAC_A_S); print_hex(resp_buffer, MAC_A_S); resp_buffer += MAC_A_S; + memcpy(resp_buffer, hdr->send_ares, MAC_A_S); print_hex(resp_buffer, MAC_A_S); resp_buffer += MAC_A_S; + uint8_t tmp[2]; + cv_uint16_to_uint8(tmp, hdr->pro_T); + memcpy(resp_buffer, tmp, sizeof(uint16_t)); print_hex(resp_buffer, sizeof(uint16_t)); resp_buffer += sizeof(uint16_t); + + cv_uint16_to_uint8(tmp, pkt->ar_hrd); + memcpy(resp_buffer, tmp, sizeof(uint16_t)); print_hex(resp_buffer, sizeof(uint16_t)); resp_buffer += sizeof(uint16_t); + cv_uint16_to_uint8(tmp, pkt->ar_pro); + memcpy(resp_buffer, tmp, sizeof(uint16_t)); print_hex(resp_buffer, sizeof(uint16_t)); resp_buffer += sizeof(uint16_t); + + uint16_t hln_pln = (pkt->ar_hln << 8) | (pkt->ar_pln); + cv_uint16_to_uint8(tmp, hln_pln); + memcpy(resp_buffer, tmp, sizeof(uint16_t)); print_hex(resp_buffer, sizeof(uint16_t)); resp_buffer += sizeof(uint16_t); + + cv_uint16_to_uint8(tmp, pkt->ar_op); + memcpy(resp_buffer, tmp, sizeof(uint16_t)); print_hex(resp_buffer, sizeof(uint16_t)); resp_buffer += sizeof(uint16_t); + + memcpy(resp_buffer, pkt->ar_sha, MAC_A_S); print_hex(resp_buffer, MAC_A_S); resp_buffer += MAC_A_S; + + uint8_t tmp_ip[4]; + for(size_t i = 0 ; i < 4 ; i++) + tmp_ip[3-i] = ((pkt->ar_spa >> i * 8) & 0xFF); + memcpy(resp_buffer, tmp_ip, IP_A_S); print_hex(resp_buffer, IP_A_S); resp_buffer += IP_A_S; + + memcpy(resp_buffer, pkt->ar_tha, MAC_A_S); print_hex(resp_buffer, MAC_A_S); resp_buffer += MAC_A_S; + + for(size_t i = 0 ; i < 4 ; i++) + tmp_ip[3-i] = ((pkt->ar_tpa >> i * 8) & 0xFF); + memcpy(resp_buffer, tmp_ip, IP_A_S); print_hex(resp_buffer, IP_A_S); resp_buffer += IP_A_S; + + return SUCCESS; +} + +int send_arp_response(int tun_fd, uint8_t * resp_buffer, size_t length, const pkt_data * pkt, const mac_hdr * hdr){ + if(cv_arp_packet_to_uint8(resp_buffer, pkt, hdr, length) == FAILED) return FAILED; + ssize_t nwrite = write(tun_fd, resp_buffer, length); + if(nwrite < 0) return FAILED; + return SUCCESS; +} + diff --git a/Blatt02/A203/arp_packet.h b/Blatt02/A203/arp_packet.h new file mode 100644 index 0000000..2af108e --- /dev/null +++ b/Blatt02/A203/arp_packet.h @@ -0,0 +1,43 @@ +#ifndef ARP_PACKET_H +#define ARP_PACKET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "arp_packet_st.h" +#include "util.h" + +#define IP_A_S 4 +#define OP_A_S 2 + +#define SUCCESS 0 +#define FAILED -1 +#define UNEQUAL 1 + +#define ARES_OP_REQ 0x0001 +#define ARES_OP_REP 0x0002 +#define ARES_HRD_ETHERNET 0x0001 +#define ETHER_T_ARP 0x0806 +#define ARES_PRO_IP 0x0800 + +#define TB_L 100 + + +int parse_arp_packet(mac_hdr * hdr, pkt_data * pkt, uint8_t * buf, size_t size); + +int receive_arp_packet(mac_hdr * hdr, pkt_data * pkt, uint8_t * buf, size_t size, uint8_t * local_ip, uint8_t * local_mac); + +int send_arp_response(int tun_fd, uint8_t * resp_buffer, size_t length, const pkt_data * pkt, const mac_hdr * hdr); + + +#endif diff --git a/Blatt02/A203/arp_packet_st.h b/Blatt02/A203/arp_packet_st.h new file mode 100644 index 0000000..467637f --- /dev/null +++ b/Blatt02/A203/arp_packet_st.h @@ -0,0 +1,36 @@ +#ifndef ARP_PACKET_ST_H +#define ARP_PACKET_ST_H + +#define MAC_A_S 6 + +#include +#include + +typedef struct{ + uint8_t dest_ares[MAC_A_S]; + uint8_t send_ares[MAC_A_S]; + uint16_t pro_T; +}mac_hdr; + +typedef struct{ + uint16_t ar_hrd; + uint16_t ar_pro; + uint8_t ar_hln; + uint8_t ar_pln; + uint16_t ar_op; + uint8_t ar_sha[MAC_A_S]; + uint32_t ar_spa; + uint8_t ar_tha[MAC_A_S]; + uint32_t ar_tpa; +}pkt_data; + +typedef struct{ + uint16_t ar_pro; + uint32_t ar_spa; + uint8_t ar_sha[MAC_A_S]; + int count; +}translation_table_entry; + +#endif + + diff --git a/Blatt02/A203/tuntap.c b/Blatt02/A203/tuntap.c new file mode 100644 index 0000000..ef00bef --- /dev/null +++ b/Blatt02/A203/tuntap.c @@ -0,0 +1,108 @@ +#include "arp_packet.h" + +#define CLEAR(x) memset(&(x), 0x00, sizeof(x)) + +#define IFNAME "tap0" +// #define IFNAME "tun0" + + +#define BUFLEN 1600 + +static int tun_alloc(char *dev) +{ + struct ifreq ifr; + int fd, err; + + if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) { + perror("Cannot open TUN/TAP dev\n" + "Make sure one exists with " + "'$ mknod /dev/net/tun c 10 200'"); + exit(1); + } + + CLEAR(ifr); + + /* Flags: IFF_TUN - TUN device (no Ethernet headers) + * IFF_TAP - TAP device + * + * IFF_NO_PI - Do not provide packet information + */ + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + if( *dev ) { + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + } + + if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ + perror("ERR: Could not ioctl tun"); + close(fd); + return err; + } + + strcpy(dev, ifr.ifr_name); + return fd; +} + +// int check_ip(uint8_t * ip, int length){ + // if(length != TARGET_IP_A_S) return UNEQUAL; + // int8_t pc2[4]={10,5,1,2}; + // for(size_t i = 0 ; i < length ; i++) + // printf("%X, %X \n", ip[i], pc2[i]); +// + // for(size_t i = 0 ; i < length ; i++) + // if(ip[i]!=pc2[i]) return FAILED; + // return SUCCESS; +//} +// +int main (int argc, char *argv[]){ + + char dev[IFNAMSIZ]; + int tun_fd; + + uint8_t local_ip[4] = {10, 5, 1, 10}; + uint8_t local_mac[6] = {0xD6,0x74,0x45,0xDC,0x5A,0xCD}; + + + if (argc > 1) { + assert(strlen(argv[1]) < IFNAMSIZ); + strcpy(dev, argv[1]); + } else { + strcpy(dev, IFNAME); + } + + printf("device name: %s\n", dev); + + tun_fd = tun_alloc(dev); + + int running = 1; + + uint8_t buf[BUFLEN]; + while (running) { + int nread; + + if ((nread = read(tun_fd, buf, BUFLEN)) < 0) { + perror("ERR: Read from tun_fd"); + break; + } + // buf[nread] = '\0'; + printf("buf :"); + print_hex(buf, nread); + + mac_hdr hdr; + pkt_data pkt; + if(parse_arp_packet(&hdr, &pkt, buf, nread) == FAILED){ + perror("ERR: Cannot parse the packet"); + } + if(receive_arp_packet(&hdr, &pkt, buf, nread, local_ip, local_mac) == FAILED){ + perror("ERR: Cannot process the packet"); + } + if(send_arp_response(tun_fd, buf, nread, &pkt, &hdr) == FAILED){ + perror("ERR: Cannot send the response"); + } + + printf("Read %d bytes from device %s\n\n", nread, dev); + } + + close(tun_fd); + + return EXIT_SUCCESS; +} diff --git a/Blatt02/A203/util.c b/Blatt02/A203/util.c new file mode 100644 index 0000000..4508abd --- /dev/null +++ b/Blatt02/A203/util.c @@ -0,0 +1,46 @@ +#include "util.h" +void print_hex(uint8_t * array, size_t size){ + + for (size_t i = 0 ; i < size; i++){ + uint8_t high = (array[i] >> 4) & 0x0F; + uint8_t low = array[i] & 0x0F; + printf("%X", high); + printf("%X ", low); + } + printf("\n"); +} +void print_u16_hex(uint16_t number){ + uint8_t tmp_a[2]; + tmp_a[0] = (number >> 8) & 0x00FF; + tmp_a[1] = number & 0x00FF; + print_hex(tmp_a, 2); + return; +} +void print_u8_hex(uint8_t number){ + printf("%X", (number >> 4) & 0x0F); + printf("%X", number & 0x0F); + printf("\n"); +} + +// void print_packet_info(arp_packet_t * packet){ +// printf("destination: "); print_hex(packet->destination, DST_S); +// printf("source: "); print_hex(packet->source, SRC_S); +// +// printf("hardware type: "); print_u16_hex(packet->hrd_t); +// printf("protocal type: "); print_u16_hex(packet->pro_t); +// printf("hardware size: "); print_u8_hex(packet->hrd_s); +// printf("protocal size: "); print_u8_hex(packet->pro_s); +// printf("op type: "); print_u16_hex(packet->op); +// +// printf("sender mac address: "); print_hex(packet->sender_mac_a, SENDER_MAC_A_S); +// printf("sender ip address: "); print_hex(packet->sender_ip_a, SENDER_IP_A_S); +// printf("target mac address: "); print_hex(packet->target_mac_a, TARGET_MAC_A_S); +// printf("target ip address: "); print_hex(packet->target_ip_a, TARGET_IP_A_S); +// } + +uint16_t combine_uint8(uint8_t high, uint8_t low){ + return (high << 8 ) | low; +} +uint32_t combine_uint8_32(uint8_t * arr){ + return (arr[0] << 24 ) | (arr[1] << 16) | (arr[2] << 8) | (arr[3]); +} diff --git a/Blatt02/A203/util.h b/Blatt02/A203/util.h new file mode 100644 index 0000000..0105b95 --- /dev/null +++ b/Blatt02/A203/util.h @@ -0,0 +1,16 @@ +#ifndef UTIL_H +#define UTIL_H + +#include +#include "arp_packet_st.h" + +#define TRUE 1 +#define FALSE 0 + +void print_hex(uint8_t * array, size_t size); +void print_u16_hex(uint16_t number); +void print_u8_hex(uint8_t number); +uint16_t combine_uint8(uint8_t high, uint8_t low); +uint32_t combine_uint8_32(uint8_t * arr); + +#endif