1 /******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
4 * This program and the accompanying materials
5 * are made available under the terms of the BSD License
6 * which accompanies this distribution, and is available at
7 * http://www.opensource.org/licenses/bsd-license.php
10 * IBM Corporation - initial implementation
11 *****************************************************************************/
14 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ALGORITHMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
16 /** \file netbase.c <pre>
17 * *********************** Receive-handle diagram *************************
19 * Note: Every layer calls out required upper layer
22 * | MAC/LLC Receive packet (receive_ether)
24 * | NETWORK +-----------+---------+
26 * | IPv4 (handle_ipv4) IPv6 (handle_ipv4)
27 * | ARP (handle_arp) ICMP & NDP
30 * | +---------+---------+
32 * | TRANSPORT +---------+---------+
34 * | TCP (handle_tcp) UDP (handle_udp)
36 * | APPLICATION +----------------+-----------+
38 * upper DNS (handle_dns) BootP / DHCP (handle_bootp_client)
40 * ************************************************************************
44 /*>>>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<*/
48 #include <sys/socket.h>
53 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<*/
55 static uint8_t ether_packet[ETH_MTU_SIZE];
56 static uint8_t own_mac[6] = {0, 0, 0, 0, 0, 0};
57 static uint8_t multicast_mac[] = {0x01, 0x00, 0x5E};
58 static const uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
60 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<*/
63 * Ethernet: Set the own MAC address to initializes ethernet layer.
65 * @param own_mac own hardware-address (MAC)
68 set_mac_address(const uint8_t * _own_mac) {
70 memcpy(own_mac, _own_mac, 6);
72 memset(own_mac, 0, 6);
76 * Ethernet: Set the own MAC address to initializes ethernet layer.
78 * @return own hardware-address (MAC)
81 get_mac_address(void) {
86 * Ethernet: Check if given multicast address is a multicast MAC address
87 * starting with 0x3333
89 * @return true or false
92 is_multicast_mac(uint8_t * mac) {
95 if (memcmp(mac, &mc, 2) == 0)
103 * Ethernet: Receives an ethernet-packet and handles it according to
104 * Receive-handle diagram.
106 * @param fd socket fd
107 * @return ZERO - packet was handled or no packets received;
108 * NON ZERO - error condition occurs.
111 receive_ether(int fd) {
112 int32_t bytes_received;
113 struct ethhdr * ethh;
115 memset(ether_packet, 0, ETH_MTU_SIZE);
116 bytes_received = recv(fd, ether_packet, ETH_MTU_SIZE, 0);
118 if (!bytes_received) // No messages
121 if (bytes_received < sizeof(struct ethhdr))
122 return -1; // packet is too small
124 ethh = (struct ethhdr *) ether_packet;
126 if(memcmp(ethh->dest_mac, broadcast_mac, 6) != 0
127 && memcmp(ethh->dest_mac, multicast_mac, 3) != 0
128 && memcmp(ethh->dest_mac, own_mac, 6 ) != 0
129 && !is_multicast_mac(ethh->dest_mac))
130 return -1; // packet is too small
132 switch (htons(ethh -> type)) {
134 return handle_ipv4(fd, (uint8_t*) (ethh + 1),
135 bytes_received - sizeof(struct ethhdr));
138 return handle_ipv6(fd, ether_packet + sizeof(struct ethhdr),
139 bytes_received - sizeof(struct ethhdr));
142 return handle_arp(fd, (uint8_t*) (ethh + 1),
143 bytes_received - sizeof(struct ethhdr));
147 return -1; // unknown protocol
151 * Ethernet: Sends an ethernet frame via the initialized file descriptor.
153 * @return number of transmitted bytes
156 send_ether(int fd, void* buffer, int len)
158 return send(fd, buffer, len, 0);
162 * Ethernet: Creates Ethernet-packet. Places Ethernet-header in a packet and
163 * fills it with corresponding information.
165 * Use this function with similar functions for other network layers
166 * (fill_arphdr, fill_iphdr, fill_udphdr, fill_dnshdr, fill_btphdr).
168 * @param packet Points to the place where eth-header must be placed.
169 * @param eth_type Type of the next level protocol (e.g. IP or ARP).
170 * @param src_mac Sender MAC address
171 * @param dest_mac Receiver MAC address
180 fill_ethhdr(uint8_t * packet, uint16_t eth_type,
181 const uint8_t * src_mac, const uint8_t * dest_mac) {
182 struct ethhdr * ethh = (struct ethhdr *) packet;
184 ethh -> type = htons(eth_type);
185 memcpy(ethh -> src_mac, src_mac, 6);
186 memcpy(ethh -> dest_mac, dest_mac, 6);