|
|
1.1.1.3 ! root 1: /* $Id: ethernet.c,v 1.4 2006/11/15 22:17:30 fredette Exp $ */ 1.1 root 2: 3: /* generic/ethernet.c - generic ethernet implementation support: */ 4: 5: /* 6: * Copyright (c) 2003 Matt Fredette 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by Matt Fredette. 20: * 4. The name of the author may not be used to endorse or promote products 21: * derived from this software without specific prior written permission. 22: * 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33: * POSSIBILITY OF SUCH DAMAGE. 34: */ 35: 36: #include <tme/common.h> 1.1.1.3 ! root 37: _TME_RCSID("$Id: ethernet.c,v 1.4 2006/11/15 22:17:30 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include <tme/generic/ethernet.h> 41: #include <stdlib.h> 1.1.1.3 ! root 42: #include <errno.h> 1.1 root 43: 44: /* the Ethernet broadcast address: */ 45: const tme_uint8_t tme_ethernet_addr_broadcast[TME_ETHERNET_ADDR_SIZE] = { 46: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 47: }; 48: 49: /* this scores an Ethernet connection: */ 50: int 51: tme_ethernet_connection_score(struct tme_connection *conn, unsigned int *_score) 52: { 53: /* both sides must be Ethernet connections: */ 54: assert(conn->tme_connection_type == TME_CONNECTION_ETHERNET); 55: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_ETHERNET); 56: 57: /* XXX we don't do any real checking: */ 58: *_score = 1; 59: return (TME_OK); 60: } 61: 62: /* this parses an ethernet address: */ 63: int 64: tme_ethernet_addr_parse(const char *addr_string, tme_uint8_t *addr_bytes) 65: { 66: const char *p1; 67: char *p2; 68: unsigned long byte; 69: int byte_i; 70: 71: /* if we were given a NULL string, the parse fails: */ 72: if (addr_string == NULL) { 73: return (EINVAL); 74: } 75: 76: /* loop converting bytes: */ 77: p1 = addr_string; 78: byte_i = 0; 79: for(;;) { 80: 81: /* convert the next byte: */ 82: byte = strtoul(p1, &p2, 16); 83: 84: /* if some characters were converted: */ 85: if (p2 != p1) { 86: 87: /* if this byte is out of range, the parse fails: */ 88: if (byte > 0xff) { 89: return (EINVAL); 90: } 91: 92: /* if this is one too many bytes for an Ethernet address, the parse fails: */ 93: else if (byte_i == TME_ETHERNET_ADDR_SIZE) { 94: return (EINVAL); 95: } 96: 97: /* store this byte: */ 98: addr_bytes[byte_i++] = byte; 99: } 100: 101: /* if the conversion stopped on a NUL: */ 102: if (*p2 == '\0') { 103: 104: /* if we haven't converted enough bytes, the parse fails, 105: otherwise the parse succeeds: */ 106: return ((byte_i == TME_ETHERNET_ADDR_SIZE) 107: ? TME_OK 108: : EINVAL); 109: } 110: 111: /* if the conversion stopped on a colon, skip the colon and continue: */ 112: else if (*p2 == ':') { 113: p1 = p2 + 1; 114: } 115: 116: /* otherwise, the parse fails: */ 117: else { 118: return (EINVAL); 119: } 120: } 121: /* NOTREACHED */ 122: } 123: 124: /* this copies frame chunks: */ 125: unsigned int 1.1.1.3 ! root 126: tme_ethernet_chunks_copy(const struct tme_ethernet_frame_chunk *chunks_dst, 1.1 root 127: const struct tme_ethernet_frame_chunk *chunks_src) 128: { 1.1.1.3 ! root 129: const struct tme_ethernet_frame_chunk *chunk_dst; 1.1 root 130: const struct tme_ethernet_frame_chunk *chunk_src; 131: tme_uint8_t *chunk_bytes_dst; 132: const tme_uint8_t *chunk_bytes_src; 133: unsigned int chunk_size_dst; 134: unsigned int chunk_size_src; 135: unsigned int chunk_size; 136: unsigned int frame_size_total; 137: 138: chunk_src = chunks_src; 139: chunk_bytes_src = chunk_src->tme_ethernet_frame_chunk_bytes; 140: chunk_size_src = chunk_src->tme_ethernet_frame_chunk_bytes_count; 141: 142: frame_size_total = 0; 143: 144: /* if we have been given a destination: */ 145: if (chunks_dst != NULL) { 146: 147: chunk_dst = chunks_dst; 148: chunk_bytes_dst = chunk_dst->tme_ethernet_frame_chunk_bytes; 149: chunk_size_dst = chunk_dst->tme_ethernet_frame_chunk_bytes_count; 150: 151: /* copy until we run out of source or destination chunks: */ 152: for (; (chunk_dst != NULL 153: && chunk_src != NULL); ) { 154: 155: /* get the amount we can copy now: */ 156: chunk_size = TME_MIN(chunk_size_dst, chunk_size_src); 157: assert(chunk_size > 0); 158: 159: /* copy: */ 160: memcpy(chunk_bytes_dst, chunk_bytes_src, chunk_size); 161: 162: /* update: */ 163: frame_size_total += chunk_size; 164: chunk_bytes_src += chunk_size; 165: chunk_size_src -= chunk_size; 166: if (chunk_size_src == 0 167: && (chunk_src = chunk_src->tme_ethernet_frame_chunk_next) != NULL) { 168: chunk_bytes_src = chunk_src->tme_ethernet_frame_chunk_bytes; 169: chunk_size_src = chunk_src->tme_ethernet_frame_chunk_bytes_count; 170: } 171: chunk_bytes_dst += chunk_size; 172: chunk_size_dst -= chunk_size; 173: if (chunk_size_dst == 0 174: && (chunk_dst = chunk_dst->tme_ethernet_frame_chunk_next) != NULL) { 175: chunk_bytes_dst = chunk_dst->tme_ethernet_frame_chunk_bytes; 1.1.1.2 root 176: chunk_size_dst = chunk_dst->tme_ethernet_frame_chunk_bytes_count; 1.1 root 177: } 178: } 179: } 180: 181: /* count up the uncopied bytes: */ 182: for (; chunk_src != NULL; ) { 183: frame_size_total += chunk_size_src; 184: if ((chunk_src = chunk_src->tme_ethernet_frame_chunk_next) != NULL) { 185: chunk_size_src = chunk_src->tme_ethernet_frame_chunk_bytes_count; 186: } 187: } 188: 189: /* done: */ 190: return (frame_size_total); 191: } 1.1.1.3 ! root 192: ! 193: /* this calculates a little-endian Ethernet CRC. this was cribbed ! 194: from NetBSD's src/sys/net/if_ethersubr.c: */ ! 195: tme_uint32_t ! 196: tme_ethernet_crc32_el(const tme_uint8_t *buf, unsigned int len) ! 197: { ! 198: static const tme_uint32_t crctab[] = { ! 199: 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, ! 200: 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, ! 201: 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, ! 202: 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c ! 203: }; ! 204: tme_uint32_t crc; ! 205: unsigned int i; ! 206: ! 207: crc = ((tme_uint32_t) 0) - 1; /* initial value */ ! 208: ! 209: for (i = 0; i < len; i++) { ! 210: crc ^= buf[i]; ! 211: crc = (crc >> 4) ^ crctab[crc & 0xf]; ! 212: crc = (crc >> 4) ^ crctab[crc & 0xf]; ! 213: } ! 214: ! 215: return (crc); ! 216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.