|
|
1.1.1.2 ! root 1: /* $Id: ethernet.c,v 1.2 2005/05/09 01:53:43 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.2 ! root 37: _TME_RCSID("$Id: ethernet.c,v 1.2 2005/05/09 01:53:43 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include <tme/generic/ethernet.h> 41: #include <stdlib.h> 42: 43: /* the Ethernet broadcast address: */ 44: const tme_uint8_t tme_ethernet_addr_broadcast[TME_ETHERNET_ADDR_SIZE] = { 45: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 46: }; 47: 48: /* this scores an Ethernet connection: */ 49: int 50: tme_ethernet_connection_score(struct tme_connection *conn, unsigned int *_score) 51: { 52: /* both sides must be Ethernet connections: */ 53: assert(conn->tme_connection_type == TME_CONNECTION_ETHERNET); 54: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_ETHERNET); 55: 56: /* XXX we don't do any real checking: */ 57: *_score = 1; 58: return (TME_OK); 59: } 60: 61: /* this parses an ethernet address: */ 62: int 63: tme_ethernet_addr_parse(const char *addr_string, tme_uint8_t *addr_bytes) 64: { 65: const char *p1; 66: char *p2; 67: unsigned long byte; 68: int byte_i; 69: 70: /* if we were given a NULL string, the parse fails: */ 71: if (addr_string == NULL) { 72: return (EINVAL); 73: } 74: 75: /* loop converting bytes: */ 76: p1 = addr_string; 77: byte_i = 0; 78: for(;;) { 79: 80: /* convert the next byte: */ 81: byte = strtoul(p1, &p2, 16); 82: 83: /* if some characters were converted: */ 84: if (p2 != p1) { 85: 86: /* if this byte is out of range, the parse fails: */ 87: if (byte > 0xff) { 88: return (EINVAL); 89: } 90: 91: /* if this is one too many bytes for an Ethernet address, the parse fails: */ 92: else if (byte_i == TME_ETHERNET_ADDR_SIZE) { 93: return (EINVAL); 94: } 95: 96: /* store this byte: */ 97: addr_bytes[byte_i++] = byte; 98: } 99: 100: /* if the conversion stopped on a NUL: */ 101: if (*p2 == '\0') { 102: 103: /* if we haven't converted enough bytes, the parse fails, 104: otherwise the parse succeeds: */ 105: return ((byte_i == TME_ETHERNET_ADDR_SIZE) 106: ? TME_OK 107: : EINVAL); 108: } 109: 110: /* if the conversion stopped on a colon, skip the colon and continue: */ 111: else if (*p2 == ':') { 112: p1 = p2 + 1; 113: } 114: 115: /* otherwise, the parse fails: */ 116: else { 117: return (EINVAL); 118: } 119: } 120: /* NOTREACHED */ 121: } 122: 123: /* this copies frame chunks: */ 124: unsigned int 125: tme_ethernet_chunks_copy(struct tme_ethernet_frame_chunk *chunks_dst, 126: const struct tme_ethernet_frame_chunk *chunks_src) 127: { 128: struct tme_ethernet_frame_chunk *chunk_dst; 129: const struct tme_ethernet_frame_chunk *chunk_src; 130: tme_uint8_t *chunk_bytes_dst; 131: const tme_uint8_t *chunk_bytes_src; 132: unsigned int chunk_size_dst; 133: unsigned int chunk_size_src; 134: unsigned int chunk_size; 135: unsigned int frame_size_total; 136: 137: chunk_src = chunks_src; 138: chunk_bytes_src = chunk_src->tme_ethernet_frame_chunk_bytes; 139: chunk_size_src = chunk_src->tme_ethernet_frame_chunk_bytes_count; 140: 141: frame_size_total = 0; 142: 143: /* if we have been given a destination: */ 144: if (chunks_dst != NULL) { 145: 146: chunk_dst = chunks_dst; 147: chunk_bytes_dst = chunk_dst->tme_ethernet_frame_chunk_bytes; 148: chunk_size_dst = chunk_dst->tme_ethernet_frame_chunk_bytes_count; 149: 150: /* copy until we run out of source or destination chunks: */ 151: for (; (chunk_dst != NULL 152: && chunk_src != NULL); ) { 153: 154: /* get the amount we can copy now: */ 155: chunk_size = TME_MIN(chunk_size_dst, chunk_size_src); 156: assert(chunk_size > 0); 157: 158: /* copy: */ 159: memcpy(chunk_bytes_dst, chunk_bytes_src, chunk_size); 160: 161: /* update: */ 162: frame_size_total += chunk_size; 163: chunk_bytes_src += chunk_size; 164: chunk_size_src -= chunk_size; 165: if (chunk_size_src == 0 166: && (chunk_src = chunk_src->tme_ethernet_frame_chunk_next) != NULL) { 167: chunk_bytes_src = chunk_src->tme_ethernet_frame_chunk_bytes; 168: chunk_size_src = chunk_src->tme_ethernet_frame_chunk_bytes_count; 169: } 170: chunk_bytes_dst += chunk_size; 171: chunk_size_dst -= chunk_size; 172: if (chunk_size_dst == 0 173: && (chunk_dst = chunk_dst->tme_ethernet_frame_chunk_next) != NULL) { 174: chunk_bytes_dst = chunk_dst->tme_ethernet_frame_chunk_bytes; 1.1.1.2 ! root 175: chunk_size_dst = chunk_dst->tme_ethernet_frame_chunk_bytes_count; 1.1 root 176: } 177: } 178: } 179: 180: /* count up the uncopied bytes: */ 181: for (; chunk_src != NULL; ) { 182: frame_size_total += chunk_size_src; 183: if ((chunk_src = chunk_src->tme_ethernet_frame_chunk_next) != NULL) { 184: chunk_size_src = chunk_src->tme_ethernet_frame_chunk_bytes_count; 185: } 186: } 187: 188: /* done: */ 189: return (frame_size_total); 190: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.