Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / clients / net-snk / app / netlib / ethernet.c
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
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
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13
14 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ALGORITHMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
15
16 /** \file netbase.c <pre>
17  * *********************** Receive-handle diagram *************************
18  *
19  * Note: Every layer calls out required upper layer
20  *
21  * lower
22  *  | MAC/LLC     Receive packet (receive_ether)
23  *  |                           |
24  *  | NETWORK       +-----------+---------+
25  *  |               |                     |
26  *  |           IPv4 (handle_ipv4)    IPv6 (handle_ipv4)
27  *  |           ARP  (handle_arp)     ICMP & NDP
28  *  |           ICMP                      |
29  *  |                 |                   |
30  *  |                 +---------+---------+
31  *  |                           |
32  *  | TRANSPORT       +---------+---------+
33  *  |                 |                   |
34  *  |              TCP (handle_tcp)    UDP (handle_udp)
35  *  |                                     |
36  *  | APPLICATION        +----------------+-----------+
37  *  V                    |                            |
38  * upper               DNS (handle_dns)      BootP / DHCP (handle_bootp_client)
39  * 
40  * ************************************************************************
41  * </pre> */
42
43
44 /*>>>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<*/
45
46 #include <ethernet.h>
47 #include <string.h>
48 #include <sys/socket.h>
49 #include <ipv4.h>
50 #include <ipv6.h>
51
52
53 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<*/
54
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};
59
60 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<*/
61
62 /**
63  * Ethernet: Set the own MAC address to initializes ethernet layer.
64  *
65  * @param  own_mac  own hardware-address (MAC)
66  */
67 void
68 set_mac_address(const uint8_t * _own_mac) {
69         if (_own_mac)
70                 memcpy(own_mac, _own_mac, 6);
71         else
72                 memset(own_mac, 0, 6);
73 }
74
75 /**
76  * Ethernet: Set the own MAC address to initializes ethernet layer.
77  *
78  * @return  own hardware-address (MAC)
79  */
80 const uint8_t *
81 get_mac_address(void) {
82         return own_mac;
83 }
84
85 /**
86  * Ethernet: Check if given multicast address is a multicast MAC address
87  *           starting with 0x3333 
88  *
89  * @return  true or false 
90  */
91 static uint8_t
92 is_multicast_mac(uint8_t * mac) {
93
94         uint16_t mc = 0x3333;
95         if (memcmp(mac, &mc, 2) == 0)
96                return 1;
97
98         return 0;
99 }
100
101
102 /**
103  * Ethernet: Receives an ethernet-packet and handles it according to
104  *      Receive-handle diagram.
105  *
106  * @param  fd        socket fd
107  * @return  ZERO - packet was handled or no packets received;
108  *          NON ZERO - error condition occurs.
109  */
110 int32_t
111 receive_ether(int fd) {
112         int32_t bytes_received;
113         struct ethhdr * ethh;
114
115         memset(ether_packet, 0, ETH_MTU_SIZE);
116         bytes_received = recv(fd, ether_packet, ETH_MTU_SIZE, 0);
117
118         if (!bytes_received) // No messages
119                 return 0;
120
121         if (bytes_received < sizeof(struct ethhdr))
122                 return -1; // packet is too small
123
124         ethh = (struct ethhdr *) ether_packet;
125
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
131
132         switch (htons(ethh -> type)) {
133         case ETHERTYPE_IP:
134                 return handle_ipv4(fd, (uint8_t*) (ethh + 1),
135                                    bytes_received - sizeof(struct ethhdr));
136
137         case ETHERTYPE_IPv6:
138                 return handle_ipv6(fd, ether_packet + sizeof(struct ethhdr),
139                                 bytes_received - sizeof(struct ethhdr));
140
141         case ETHERTYPE_ARP:
142                 return handle_arp(fd, (uint8_t*) (ethh + 1),
143                            bytes_received - sizeof(struct ethhdr));
144         default:
145                 break;
146         }
147         return -1; // unknown protocol
148 }
149
150 /**
151  * Ethernet: Sends an ethernet frame via the initialized file descriptor.
152  *
153  * @return number of transmitted bytes
154  */
155 int
156 send_ether(int fd, void* buffer, int len)
157 {
158         return send(fd, buffer, len, 0);
159 }
160
161 /**
162  * Ethernet: Creates Ethernet-packet. Places Ethernet-header in a packet and
163  *           fills it with corresponding information.
164  *           <p>
165  *           Use this function with similar functions for other network layers
166  *           (fill_arphdr, fill_iphdr, fill_udphdr, fill_dnshdr, fill_btphdr).
167  *
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
172  * @see                ethhdr
173  * @see                fill_arphdr
174  * @see                fill_iphdr
175  * @see                fill_udphdr
176  * @see                fill_dnshdr
177  * @see                fill_btphdr
178  */
179 void
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;
183
184         ethh -> type = htons(eth_type);
185         memcpy(ethh -> src_mac, src_mac, 6);
186         memcpy(ethh -> dest_mac, dest_mac, 6);
187 }