/****************************************************************************** * 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
 * *********************** 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)
 *
 * ************************************************************************
 * 
*/ /************************ DEFINITIONS & DECLARATIONS *********************/ #include #include #include #include #include /****************************** 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. *

* 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); }