source: mainline/uspace/app/pcapcat/eth_parser.c@ 3197b50

Last change on this file since 3197b50 was 3197b50, checked in by Nataliia Korop <n.corop08@…>, 10 months ago

pcapcat utility, without docs and with literals

  • Property mode set to 100644
File size: 6.3 KB
RevLine 
[3197b50]1/*
2 * Copyright (c) 2024 Nataliia Korop
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30#include <stdint.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <time.h>
34#include <stdbool.h>
35#include <errno.h>
36#include <str.h>
37#include <io/log.h>
38#include "pcap.h"
39#include "eth_parser.h"
40
41#define ETH_ADDR_SIZE 6
42#define IPV4_ADDR_SIZE 4
43
44#define ETHER_TYPE_ARP 0x0806
45#define ETHER_TYPE_IP4 0x0800
46#define ETHER_TYPE_IP6 0x86DD
47
48#define BYTE_SIZE 8
49
50#define IP_PROTOCOL_TCP 0x06
51#define IP_PROTOCOL_UDP 0x11
52#define IP_PROTOCOL_ICMP 0x01
53
54#define TCP_TEXT "TCP"
55#define IP_TEXT "IP"
56#define MAC_TEXT "MAC"
57#define ARP_TEXT "ARP"
58#define IPV4_TEXT "IPv4"
59#define IPV6_TEXT "IPv6"
60
61#define PRINT_IP(msg, ip_addr, spaces) printf("%s %s: %d.%d.%d.%d%s", msg, IP_TEXT, ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], spaces)
62#define PRINT_MAC(msg, mac, spaces) printf("%s %s: %02x:%02x:%02x:%02x:%02x:%02x%s", msg, MAC_TEXT, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], spaces)
63#define BIG_END_16(buffer, idx) buffer[idx] << BYTE_SIZE | buffer[idx + 1]
64
65
66static void read_from_buffer(unsigned char *buffer, int start_idx, int count, uint8_t *dst)
67{
68 for (int i = start_idx; i < start_idx + count; ++i) {
69 dst[i - start_idx] = buffer[i];
70 }
71}
72
73static void parse_arp(unsigned char *byte_source, size_t size)
74{
75 uint8_t sender_mac[ETH_ADDR_SIZE];
76 uint8_t sender_ip[IPV4_ADDR_SIZE];
77 uint8_t target_mac[ETH_ADDR_SIZE];
78 uint8_t target_ip[IPV4_ADDR_SIZE];
79
80 read_from_buffer(byte_source, 22, ETH_ADDR_SIZE, sender_mac);
81 read_from_buffer(byte_source, 28, IPV4_ADDR_SIZE, sender_ip);
82 read_from_buffer(byte_source, 32, ETH_ADDR_SIZE, target_mac);
83 read_from_buffer(byte_source, 36, IPV4_ADDR_SIZE, target_ip);
84
85 PRINT_MAC("Sender", sender_mac, ", ");
86 PRINT_IP("Sender", sender_ip, " ");
87 PRINT_MAC("Target", target_mac, ", ");
88 PRINT_IP("Target", target_ip, "\n");
89
90}
91
92static void parse_tcp(unsigned char *byte_source, size_t size)
93{
94 uint16_t src_port = BIG_END_16(byte_source, 34);
95 uint16_t dst_port = BIG_END_16(byte_source, 36);
96 printf(" [%s] source port: %d, destination port: %d\n", TCP_TEXT, src_port, dst_port);
97}
98
99static void parse_ip(unsigned char *byte_source, size_t size, bool verbose)
100{
101 uint16_t total_length;
102 uint8_t header_length;
103 uint16_t payload_length;
104 uint8_t ip_protocol;
105 uint8_t src_ip[IPV4_ADDR_SIZE];
106 uint8_t dst_ip[IPV4_ADDR_SIZE];
107
108 header_length = (byte_source[14] & 0xf) * 4;
109 total_length = BIG_END_16(byte_source, 16);
110 payload_length = total_length - header_length;
111 ip_protocol = byte_source[23];
112
113 read_from_buffer(byte_source, 26, IPV4_ADDR_SIZE, src_ip);
114 read_from_buffer(byte_source, 28, IPV4_ADDR_SIZE, dst_ip);
115
116 printf("%s header: %dB, payload: %dB, protocol: 0x%x, ", IP_TEXT, header_length, payload_length, ip_protocol);
117 PRINT_IP("Source", src_ip, ", ");
118 PRINT_IP("Destination", dst_ip, "\n");
119
120 if (verbose && ip_protocol == IP_PROTOCOL_TCP) {
121 parse_tcp(byte_source, size);
122 }
123}
124
125static void parse_eth_packet(void *data, size_t size, bool verbose_flag)
126{
127 unsigned char* byte_source = (unsigned char*)data;
128
129 uint16_t protocol = BIG_END_16(byte_source, 12);
130
131 switch (protocol){
132 case ETHER_TYPE_ARP:
133 printf("[%s] ", ARP_TEXT);
134 parse_arp(byte_source, size);
135 break;
136 case ETHER_TYPE_IP4:
137 printf("[%s] ", IPV4_TEXT);
138 parse_ip(byte_source, size, verbose_flag);
139 break;
140 case ETHER_TYPE_IP6:
141 printf("[%s]\n", IPV6_TEXT);
142 break;
143 default:
144 printf("[0x%x]\n", protocol);
145 break;
146 }
147}
148
149void eth_parse_header(pcap_file_header_t *hdr)
150{
151 printf("LinkType: %d\n", hdr->additional);
152 printf("Magic number: 0x%x\n", hdr->magic_number);
153}
154
155void eth_parse_packets(FILE *f, int count, bool verbose_flag)
156{
157 pcap_packet_header_t hdr;
158
159 size_t read_bytes = fread(&hdr, 1, sizeof(pcap_packet_header_t), f);
160 int packet_index = 1;
161 while (read_bytes > 0)
162 {
163 if (read_bytes < sizeof(pcap_packet_header_t)) {
164 printf("Error: Could not read enough bytes (read %zu bytes)\n", read_bytes);
165 return;
166 }
167
168 printf("%04d) ", packet_index++);
169
170 void *data = malloc(hdr.captured_length);
171 read_bytes = fread(data, 1, (size_t)hdr.captured_length, f);
172 if (read_bytes < (size_t)hdr.captured_length) {
173 printf("Error: Could not read enough bytes (read %zu bytes)\n", read_bytes);
174 return;
175 }
176 parse_eth_packet(data, (size_t)hdr.captured_length, verbose_flag);
177 free(data);
178
179 //Read first count packets
180 if (count != -1 && count == packet_index - 1) {
181 return;
182 }
183
184 memset(&hdr, 0, sizeof(pcap_packet_header_t));
185 read_bytes = fread(&hdr, 1, sizeof(pcap_packet_header_t), f);
186 }
187
188 fclose(f);
189}
Note: See TracBrowser for help on using the repository browser.