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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ALGORITHMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
/** \file netbase.c <pre>
* *********************** Receive-handle diagram *************************
*
* Note: Every layer calls out required upper layer
*
* lower
* | MAC/LLC Receive packet (receive_ether)
* | |
* | NETWORK +-----------+---------+
* | | |
* | IPv4 (handle_ipv4) IPv6 (handle_ipv4)
* | ARP (handle_arp) ICMP & NDP
* | ICMP |
* | | |
* | +---------+---------+
* | |
* | TRANSPORT +---------+---------+
* | | |
* | TCP (handle_tcp) UDP (handle_udp)
* | |
* | APPLICATION +----------------+-----------+
* V | |
* upper DNS (handle_dns) BootP / DHCP (handle_bootp_client)
*
* ************************************************************************
* </pre> */
/*>>>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<*/
#include <ethernet.h>
#include <string.h>
#include <sys/socket.h>
#include <ipv4.h>
#include <ipv6.h>
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<*/
static uint8_t ether_packet[ETH_MTU_SIZE];
static uint8_t own_mac[6] = {0, 0, 0, 0, 0, 0};
static uint8_t multicast_mac[] = {0x01, 0x00, 0x5E};
static const uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<*/
/**
* Ethernet: Set the own MAC address to initializes ethernet layer.
*
* @param own_mac own hardware-address (MAC)
*/
void
set_mac_address(const uint8_t * _own_mac) {
if (_own_mac)
memcpy(own_mac, _own_mac, 6);
else
memset(own_mac, 0, 6);
}
/**
* Ethernet: Set the own MAC address to initializes ethernet layer.
*
* @return own hardware-address (MAC)
*/
const uint8_t *
get_mac_address(void) {
return own_mac;
}
/**
* Ethernet: Check if given multicast address is a multicast MAC address
* starting with 0x3333
*
* @return true or false
*/
static uint8_t
is_multicast_mac(uint8_t * mac) {
uint16_t mc = 0x3333;
if (memcmp(mac, &mc, 2) == 0)
return 1;
return 0;
}
/**
* Ethernet: Receives an ethernet-packet and handles it according to
* Receive-handle diagram.
*
* @param fd socket fd
* @return ZERO - packet was handled or no packets received;
* NON ZERO - error condition occurs.
*/
int32_t
receive_ether(int fd) {
int32_t bytes_received;
struct ethhdr * ethh;
memset(ether_packet, 0, ETH_MTU_SIZE);
bytes_received = recv(fd, ether_packet, ETH_MTU_SIZE, 0);
if (!bytes_received) // No messages
return 0;
if (bytes_received < sizeof(struct ethhdr))
return -1; // packet is too small
ethh = (struct ethhdr *) ether_packet;
if(memcmp(ethh->dest_mac, broadcast_mac, 6) != 0
&& memcmp(ethh->dest_mac, multicast_mac, 3) != 0
&& memcmp(ethh->dest_mac, own_mac, 6 ) != 0
&& !is_multicast_mac(ethh->dest_mac))
return -1; // packet is too small
switch (htons(ethh -> type)) {
case ETHERTYPE_IP:
return handle_ipv4(fd, (uint8_t*) (ethh + 1),
bytes_received - sizeof(struct ethhdr));
case ETHERTYPE_IPv6:
return handle_ipv6(fd, ether_packet + sizeof(struct ethhdr),
bytes_received - sizeof(struct ethhdr));
case ETHERTYPE_ARP:
return handle_arp(fd, (uint8_t*) (ethh + 1),
bytes_received - sizeof(struct ethhdr));
default:
break;
}
return -1; // unknown protocol
}
/**
* Ethernet: Sends an ethernet frame via the initialized file descriptor.
*
* @return number of transmitted bytes
*/
int
send_ether(int fd, void* buffer, int len)
{
return send(fd, buffer, len, 0);
}
/**
* Ethernet: Creates Ethernet-packet. Places Ethernet-header in a packet and
* fills it with corresponding information.
* <p>
* Use this function with similar functions for other network layers
* (fill_arphdr, fill_iphdr, fill_udphdr, fill_dnshdr, fill_btphdr).
*
* @param packet Points to the place where eth-header must be placed.
* @param eth_type Type of the next level protocol (e.g. IP or ARP).
* @param src_mac Sender MAC address
* @param dest_mac Receiver MAC address
* @see ethhdr
* @see fill_arphdr
* @see fill_iphdr
* @see fill_udphdr
* @see fill_dnshdr
* @see fill_btphdr
*/
void
fill_ethhdr(uint8_t * packet, uint16_t eth_type,
const uint8_t * src_mac, const uint8_t * dest_mac) {
struct ethhdr * ethh = (struct ethhdr *) packet;
ethh -> type = htons(eth_type);
memcpy(ethh -> src_mac, src_mac, 6);
memcpy(ethh -> dest_mac, dest_mac, 6);
}
|