|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2006 Michael Brown <[email protected]>. ! 3: * ! 4: * This program is free software; you can redistribute it and/or ! 5: * modify it under the terms of the GNU General Public License as ! 6: * published by the Free Software Foundation; either version 2 of the ! 7: * License, or any later version. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, but ! 10: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 12: * General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, write to the Free Software ! 16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <stdint.h> ! 22: #include <stdio.h> ! 23: #include <string.h> ! 24: #include <byteswap.h> ! 25: #include <errno.h> ! 26: #include <assert.h> ! 27: #include <ipxe/if_arp.h> ! 28: #include <ipxe/if_ether.h> ! 29: #include <ipxe/in.h> ! 30: #include <ipxe/netdevice.h> ! 31: #include <ipxe/iobuf.h> ! 32: #include <ipxe/ethernet.h> ! 33: ! 34: /** @file ! 35: * ! 36: * Ethernet protocol ! 37: * ! 38: */ ! 39: ! 40: /** Ethernet broadcast MAC address */ ! 41: static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; ! 42: ! 43: /** ! 44: * Add Ethernet link-layer header ! 45: * ! 46: * @v netdev Network device ! 47: * @v iobuf I/O buffer ! 48: * @v ll_dest Link-layer destination address ! 49: * @v ll_source Source link-layer address ! 50: * @v net_proto Network-layer protocol, in network-byte order ! 51: * @ret rc Return status code ! 52: */ ! 53: static int eth_push ( struct net_device *netdev __unused, ! 54: struct io_buffer *iobuf, const void *ll_dest, ! 55: const void *ll_source, uint16_t net_proto ) { ! 56: struct ethhdr *ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) ); ! 57: ! 58: /* Build Ethernet header */ ! 59: memcpy ( ethhdr->h_dest, ll_dest, ETH_ALEN ); ! 60: memcpy ( ethhdr->h_source, ll_source, ETH_ALEN ); ! 61: ethhdr->h_protocol = net_proto; ! 62: ! 63: return 0; ! 64: } ! 65: ! 66: /** ! 67: * Remove Ethernet link-layer header ! 68: * ! 69: * @v netdev Network device ! 70: * @v iobuf I/O buffer ! 71: * @ret ll_dest Link-layer destination address ! 72: * @ret ll_source Source link-layer address ! 73: * @ret net_proto Network-layer protocol, in network-byte order ! 74: * @ret rc Return status code ! 75: */ ! 76: static int eth_pull ( struct net_device *netdev __unused, ! 77: struct io_buffer *iobuf, const void **ll_dest, ! 78: const void **ll_source, uint16_t *net_proto ) { ! 79: struct ethhdr *ethhdr = iobuf->data; ! 80: ! 81: /* Sanity check */ ! 82: if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) { ! 83: DBG ( "Ethernet packet too short (%zd bytes)\n", ! 84: iob_len ( iobuf ) ); ! 85: return -EINVAL; ! 86: } ! 87: ! 88: /* Strip off Ethernet header */ ! 89: iob_pull ( iobuf, sizeof ( *ethhdr ) ); ! 90: ! 91: /* Fill in required fields */ ! 92: *ll_dest = ethhdr->h_dest; ! 93: *ll_source = ethhdr->h_source; ! 94: *net_proto = ethhdr->h_protocol; ! 95: ! 96: return 0; ! 97: } ! 98: ! 99: /** ! 100: * Initialise Ethernet address ! 101: * ! 102: * @v hw_addr Hardware address ! 103: * @v ll_addr Link-layer address ! 104: */ ! 105: void eth_init_addr ( const void *hw_addr, void *ll_addr ) { ! 106: memcpy ( ll_addr, hw_addr, ETH_ALEN ); ! 107: } ! 108: ! 109: /** ! 110: * Transcribe Ethernet address ! 111: * ! 112: * @v ll_addr Link-layer address ! 113: * @ret string Link-layer address in human-readable format ! 114: */ ! 115: const char * eth_ntoa ( const void *ll_addr ) { ! 116: static char buf[18]; /* "00:00:00:00:00:00" */ ! 117: const uint8_t *eth_addr = ll_addr; ! 118: ! 119: sprintf ( buf, "%02x:%02x:%02x:%02x:%02x:%02x", ! 120: eth_addr[0], eth_addr[1], eth_addr[2], ! 121: eth_addr[3], eth_addr[4], eth_addr[5] ); ! 122: return buf; ! 123: } ! 124: ! 125: /** ! 126: * Hash multicast address ! 127: * ! 128: * @v af Address family ! 129: * @v net_addr Network-layer address ! 130: * @v ll_addr Link-layer address to fill in ! 131: * @ret rc Return status code ! 132: */ ! 133: int eth_mc_hash ( unsigned int af, const void *net_addr, void *ll_addr ) { ! 134: const uint8_t *net_addr_bytes = net_addr; ! 135: uint8_t *ll_addr_bytes = ll_addr; ! 136: ! 137: switch ( af ) { ! 138: case AF_INET: ! 139: ll_addr_bytes[0] = 0x01; ! 140: ll_addr_bytes[1] = 0x00; ! 141: ll_addr_bytes[2] = 0x5e; ! 142: ll_addr_bytes[3] = net_addr_bytes[1] & 0x7f; ! 143: ll_addr_bytes[4] = net_addr_bytes[2]; ! 144: ll_addr_bytes[5] = net_addr_bytes[3]; ! 145: return 0; ! 146: default: ! 147: return -ENOTSUP; ! 148: } ! 149: } ! 150: ! 151: /** ! 152: * Generate Ethernet-compatible compressed link-layer address ! 153: * ! 154: * @v ll_addr Link-layer address ! 155: * @v eth_addr Ethernet-compatible address to fill in ! 156: */ ! 157: int eth_eth_addr ( const void *ll_addr, void *eth_addr ) { ! 158: memcpy ( eth_addr, ll_addr, ETH_ALEN ); ! 159: return 0; ! 160: } ! 161: ! 162: /** Ethernet protocol */ ! 163: struct ll_protocol ethernet_protocol __ll_protocol = { ! 164: .name = "Ethernet", ! 165: .ll_proto = htons ( ARPHRD_ETHER ), ! 166: .hw_addr_len = ETH_ALEN, ! 167: .ll_addr_len = ETH_ALEN, ! 168: .ll_header_len = ETH_HLEN, ! 169: .push = eth_push, ! 170: .pull = eth_pull, ! 171: .init_addr = eth_init_addr, ! 172: .ntoa = eth_ntoa, ! 173: .mc_hash = eth_mc_hash, ! 174: .eth_addr = eth_eth_addr, ! 175: }; ! 176: ! 177: /** ! 178: * Allocate Ethernet device ! 179: * ! 180: * @v priv_size Size of driver private data ! 181: * @ret netdev Network device, or NULL ! 182: */ ! 183: struct net_device * alloc_etherdev ( size_t priv_size ) { ! 184: struct net_device *netdev; ! 185: ! 186: netdev = alloc_netdev ( priv_size ); ! 187: if ( netdev ) { ! 188: netdev->ll_protocol = ðernet_protocol; ! 189: netdev->ll_broadcast = eth_broadcast; ! 190: netdev->max_pkt_len = ETH_FRAME_LEN; ! 191: } ! 192: return netdev; ! 193: } ! 194: ! 195: /* Drag in Ethernet slow protocols */ ! 196: REQUIRE_OBJECT ( eth_slow );
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.