|
|
1.1 root 1: /* $Id: ethernet.c,v 1.1 2003/05/02 17:10:50 fredette Exp $ */
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>
37: _TME_RCSID("$Id: ethernet.c,v 1.1 2003/05/02 17:10:50 fredette Exp $");
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;
175: chunk_size_dst = chunk_src->tme_ethernet_frame_chunk_bytes_count;
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.