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 188 189
|
/******************************************************************************
* 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 < 0)
return -1; /* recv() failed */
if ((size_t) 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);
}
|