These changes are the raw update to qemu-2.6.
[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 set_mac_address(const uint8_t * _own_mac)
68 {
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 *get_mac_address(void)
81 {
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 is_multicast_mac(uint8_t * mac)
92 {
93
94         uint16_t mc = 0x3333;
95         if (memcmp(mac, &mc, 2) == 0)
96                return 1;
97
98         return 0;
99 }
100
101 /**
102  * Ethernet: Receives an ethernet-packet and handles it according to
103  *      Receive-handle diagram.
104  *
105  * @param  fd        socket fd
106  * @return  ZERO - packet was handled or no packets received;
107  *          NON ZERO - error condition occurs.
108  */
109 int32_t receive_ether(int fd)
110 {
111         int32_t bytes_received;
112         struct ethhdr * ethh;
113
114         memset(ether_packet, 0, ETH_MTU_SIZE);
115         bytes_received = recv(fd, ether_packet, ETH_MTU_SIZE, 0);
116
117         if (!bytes_received) // No messages
118                 return 0;
119
120         if (bytes_received < 0)
121                 return -1; /* recv() failed */
122
123         if ((size_t) bytes_received < sizeof(struct ethhdr))
124                 return -1; // packet is too small
125
126         ethh = (struct ethhdr *) ether_packet;
127
128         if(memcmp(ethh->dest_mac, broadcast_mac, 6) != 0
129         && memcmp(ethh->dest_mac, multicast_mac, 3) != 0
130         && memcmp(ethh->dest_mac, own_mac, 6      ) != 0
131         && !is_multicast_mac(ethh->dest_mac))
132                 return -1; // packet is too small
133
134         switch (htons(ethh -> type)) {
135         case ETHERTYPE_IP:
136                 return handle_ipv4(fd, (uint8_t*) (ethh + 1),
137                                    bytes_received - sizeof(struct ethhdr));
138
139         case ETHERTYPE_IPv6:
140                 return handle_ipv6(fd, ether_packet + sizeof(struct ethhdr),
141                                 bytes_received - sizeof(struct ethhdr));
142
143         case ETHERTYPE_ARP:
144                 return handle_arp(fd, (uint8_t*) (ethh + 1),
145                            bytes_received - sizeof(struct ethhdr));
146         default:
147                 break;
148         }
149         return -1; // unknown protocol
150 }
151
152 /**
153  * Ethernet: Sends an ethernet frame via the initialized file descriptor.
154  *
155  * @return number of transmitted bytes
156  */
157 int
158 send_ether(int fd, void* buffer, int len)
159 {
160         return send(fd, buffer, len, 0);
161 }
162
163 /**
164  * Ethernet: Creates Ethernet-packet. Places Ethernet-header in a packet and
165  *           fills it with corresponding information.
166  *           <p>
167  *           Use this function with similar functions for other network layers
168  *           (fill_arphdr, fill_iphdr, fill_udphdr, fill_dnshdr, fill_btphdr).
169  *
170  * @param  packet      Points to the place where eth-header must be placed.
171  * @param  eth_type    Type of the next level protocol (e.g. IP or ARP).
172  * @param  src_mac     Sender MAC address
173  * @param  dest_mac    Receiver MAC address
174  * @see                ethhdr
175  * @see                fill_arphdr
176  * @see                fill_iphdr
177  * @see                fill_udphdr
178  * @see                fill_dnshdr
179  * @see                fill_btphdr
180  */
181 void fill_ethhdr(uint8_t * packet, uint16_t eth_type,
182                  const uint8_t * src_mac, const uint8_t * dest_mac)
183 {
184         struct ethhdr * ethh = (struct ethhdr *) packet;
185
186         ethh -> type = htons(eth_type);
187         memcpy(ethh -> src_mac, src_mac, 6);
188         memcpy(ethh -> dest_mac, dest_mac, 6);
189 }