Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: eth.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | /* | |
24 | * "eth.h" | |
25 | * | |
26 | * structs & functions to access ethernet packet fields... | |
27 | * | |
28 | * Note, for when ip.verlen = 0x45, ie standard 5-word (20-uchar) ip-header, | |
29 | * and when tcp.?? = ??, ie standard 20-uchar tcp header: | |
30 | * | |
31 | * min eth-pkt = 64 uchars | |
32 | * -14 (eth-header) | |
33 | * -4 (eth-tailer CRC) = 46 min eth-data | |
34 | * -20 (ip-header) = 26 min padding for "empty" ip-pkt | |
35 | * -20 (tcp-header) = 6 min padding for "empty" tcp-pkt | |
36 | * | |
37 | * max eth-pkt = 1518 uchars | |
38 | * - 14 (eth-header) | |
39 | * - 4 (eth-trailer CRC) = 1500 max eth-data-MTU | |
40 | * - 20 (ip-header) = 1480 max ip-data-MTU | |
41 | * - 20 (tcp-header) = 1460 max tcp-data-MTU | |
42 | * | |
43 | * | |
44 | * all of the "word" sized fields are UN-aligned, Argh!!!... | |
45 | * | |
46 | * @@@ Danger Will Robinson, Danger: | |
47 | * -1 and -2 seem to be valid ip addresses ??? | |
48 | */ | |
49 | #ifndef _ETH_H | |
50 | #define _ETH_H | |
51 | ||
52 | typedef unsigned char uchar; | |
53 | typedef unsigned short ushort; | |
54 | typedef unsigned int uword; | |
55 | ||
56 | ||
57 | #define ETH_MAX 1518 /* the whole thing, including header and CRC */ | |
58 | #define ETH_BUF_MAX 1514 /* without the CRC */ | |
59 | #define ETH_DATA_MAX 1500 /* without the CRC or the header, aka `MTU' */ | |
60 | ||
61 | #define ETHHDRSZ 14 /* ethernet packet header size */ | |
62 | ||
63 | #define ETH_MIN 64 /* the whole thing, including header and CRC */ | |
64 | ||
65 | #define IP_DATA_MAX 1480 /* eth minus the 20-uchar ip header */ | |
66 | #define TCP_DATA_MAX 1460 /* ip minus the 20-uchar tcp header */ | |
67 | ||
68 | ||
69 | /* Ethernet Types */ | |
70 | #define ET_IPv4 0x0800 | |
71 | #define ET_ARP 0x0806 | |
72 | #define ET_RARP 0x0835 | |
73 | ||
74 | ||
75 | /* (some) IP Types */ | |
76 | #define IP_ICMP 0x01 /* Inet Control Message Prot <--- */ | |
77 | #define IP_IGMP 0x02 /* Inet Gateway Message Prot <--- */ | |
78 | #define IP_GGP 0x03 /* Gateway-to-Gateway Prot */ | |
79 | #define IP_IP 0x04 /* IP-in-IP-encapsulation Prot */ | |
80 | #define IP_ST 0x05 /* Stream Prot */ | |
81 | #define IP_TCP 0x06 /* Transmission Control Prot <--- */ | |
82 | #define IP_EGP 0x08 /* Exterior-Gateway Prot */ | |
83 | #define IP_IGP 0x09 /* Interior-Gateway Prot */ | |
84 | #define IP_UDP 0x11 /* User Datagram Prot <--- */ | |
85 | ||
86 | /* (some) ICMP message Types */ | |
87 | #define ICMP_ECHOREPLY 0 | |
88 | #define ICMP_UNREACHABLE 3 | |
89 | #define ICMP_SRCQUENCH 4 | |
90 | #define ICMP_REDIRECT 5 | |
91 | #define ICMP_ECHO 8 | |
92 | #define ICMP_ROUTERREPLY 9 | |
93 | #define ICMP_ROUTERREQST 10 | |
94 | #define ICMP_TIMEOUT 11 | |
95 | #define ICMP_INVARG 12 | |
96 | #define ICMP_TIMESTAMP 13 | |
97 | #define ICMP_TSTAMPREPLY 14 | |
98 | #define ICMP_INFO 15 | |
99 | #define ICMP_INFOREPLY 16 | |
100 | #define ICMP_MASK 17 | |
101 | #define ICMP_MASKREPLY 18 | |
102 | #define ICMP_DOMNAMREQST 37 | |
103 | #define ICMP_DOMNAMREPLY 38 | |
104 | ||
105 | ||
106 | /* (a few) TCP Types */ | |
107 | #define TCP_ECHO 7 | |
108 | #define TCP_FTPDATA 20 | |
109 | #define TCP_FTP 21 | |
110 | #define TCP_SSH 22 | |
111 | #define TCP_TELNET 23 | |
112 | #define TCP_TIME 37 | |
113 | #define TCP_DNS 53 | |
114 | #define TCP_HTTP 80 | |
115 | #define TCP_HTTPS 443 | |
116 | #define TCP_SUNRPC 111 | |
117 | #define TCP_LDAP 389 | |
118 | #define TCP_REXEC 512 | |
119 | #define TCP_RLOGIN 513 | |
120 | #define TCP_RSHELL 514 | |
121 | ||
122 | ||
123 | ||
124 | ||
125 | typedef struct { | |
126 | uchar dstMAC[6]; /* all 1's for a broadcast Request 0*/ | |
127 | uchar srcMAC[6]; /* 3*/ | |
128 | ushort frametype; /* 0x0800 => ET_IPv4 6*/ | |
129 | /* 0x0806 => ARP, 0x0835 => RARP */ | |
130 | union { | |
131 | ||
132 | char eth_data[ ETH_DATA_MAX ]; | |
133 | ||
134 | struct arp_s { | |
135 | ushort hardtype; /* 1 => Ethernet 7*/ | |
136 | ushort prottype; /* 0x0800 => IP 8*/ | |
137 | uchar hardsize; /* 6, mac size 9*/ | |
138 | uchar protsize; /* 4, ip size */ | |
139 | ushort op; /* 1 => ARP, 2 => reply, | |
140 | 3 => RARP, 4 => reply 10*/ | |
141 | /* ARP-Request ARP-Reply */ | |
142 | uchar srcMAC[6]; /* requestor -----> replyor 11*/ | |
143 | uchar srcIP[4]; /* requestor / ----> replyor 14*/ | |
144 | uchar dstMAC[6]; /* <empty>----- / 16*/ | |
145 | uchar dstIP[4]; /* specified----- 19*/ | |
146 | } arp; | |
147 | ||
148 | struct ip_s { | |
149 | uchar verlen; /* 0x45 -> IPv4 and std 5-word header */ | |
150 | uchar TofS; | |
151 | ushort iplen; /* ipheader + ipdata, NOT incl eth hdr*/ | |
152 | ushort ident; | |
153 | ushort flags; | |
154 | uchar time_to_live; | |
155 | uchar protocol; /* 0x06=>TCP, 0x11=>UDP, 0x01=> ICMP */ | |
156 | ushort hdrchecksum; | |
157 | uchar srcIP[4]; /* 13*/ | |
158 | uchar dstIP[4]; /* 15*/ | |
159 | ||
160 | union { | |
161 | ||
162 | char ip_data [ IP_DATA_MAX ]; | |
163 | ||
164 | struct icmp_s { | |
165 | char type; | |
166 | char code; | |
167 | ushort chksum; | |
168 | } icmp; | |
169 | ||
170 | struct udp_s { | |
171 | ushort srcPORT; | |
172 | ushort dstPORT; | |
173 | ushort udplen; | |
174 | ushort checksum; | |
175 | } udp; | |
176 | ||
177 | struct tcp_s { | |
178 | ushort srcPORT; /* 17*/ | |
179 | ushort dstPORT; /* 18*/ | |
180 | uchar SeqNum[4]; | |
181 | uchar AckNum[4]; | |
182 | ushort flags; | |
183 | ushort win_size; | |
184 | ushort checksum; | |
185 | ushort UrgentPtr; | |
186 | ||
187 | uchar data[6]; /*min padding for "empty" pkt*/ | |
188 | } tcp; | |
189 | ||
190 | } u; | |
191 | ||
192 | } ip; | |
193 | ||
194 | } u; | |
195 | ||
196 | char CRC[4]; | |
197 | char guard[120]; /* protect from buffer overflow... */ | |
198 | } ethpacket_t; | |
199 | ||
200 | ||
201 | /* short*/ | |
202 | typedef struct { /*offset*/ | |
203 | uchar dstMAC[6]; | |
204 | uchar srcMAC[6]; | |
205 | ushort frametype; /* 0x0800 -> ET_IPv4 6*/ | |
206 | struct { | |
207 | uchar verlen; /* 0x45 -> std IP hdr 7*/ | |
208 | uchar TofS; | |
209 | ushort iplen; /* 20 for empty data packet */ | |
210 | ushort ident; | |
211 | ushort flags; | |
212 | uchar time_to_live; | |
213 | uchar protocol; /* 0xff -> netsim connect packet 11*/ | |
214 | ushort hdrchecksum; | |
215 | uchar srcIP[4]; /* 13*/ | |
216 | uchar dstIP[4]; /* 15*/ | |
217 | } ip; | |
218 | } netsim_connect_packet; | |
219 | ||
220 | ||
221 | ||
222 | ||
223 | inline uint16_t eth_short (uchar * x) | |
224 | { return ((unsigned short*)(x))[0]; } | |
225 | ||
226 | inline uint32_t eth_int (uchar * x) | |
227 | { return (((unsigned short*)(x))[0])<<16 | |
228 | | (((unsigned short*)(x))[1]); } | |
229 | ||
230 | inline uint64_t eth_long (uchar * x) | |
231 | { return ((uint64_t)(((unsigned short*)(x))[0])<<32) | |
232 | | ((uint64_t)(((unsigned short*)(x))[1])<<16) | |
233 | | (uint64_t)(((unsigned short*)(x))[2]); } | |
234 | ||
235 | ||
236 | inline bool eth_isbroadcast(ethpacket_t * x) | |
237 | { return eth_short (&x->dstMAC[0]) == 0xffff | |
238 | && eth_short (&x->dstMAC[2]) == 0xffff | |
239 | && eth_short (&x->dstMAC[4]) == 0xffff; } | |
240 | ||
241 | ||
242 | inline int eth_length (ethpacket_t * x) | |
243 | { | |
244 | if (x->frametype == ET_ARP) return 42; | |
245 | else if (x->frametype == ET_IPv4) | |
246 | return ETHHDRSZ + x->u.ip.iplen; | |
247 | else return 0; /* ??? */ | |
248 | } | |
249 | ||
250 | ||
251 | inline unsigned short eth_type (ethpacket_t * x) /* arp, ipv4, ... */ | |
252 | { return x->frametype; } | |
253 | ||
254 | inline unsigned short eth_arpop (ethpacket_t * x) /* reqest, reply, */ | |
255 | { return x->u.arp.op; } | |
256 | ||
257 | inline unsigned char eth_ipproto (ethpacket_t * x) /* tcp, upd, icmp,...*/ | |
258 | { return x->u.ip.protocol; } | |
259 | ||
260 | inline unsigned char eth_ipversion (ethpacket_t * x) | |
261 | { return x->u.ip.verlen >> 4; } | |
262 | ||
263 | inline unsigned char eth_iphdrlen (ethpacket_t * x) | |
264 | { return 4 * (x->u.ip.verlen & 0xf); } | |
265 | ||
266 | inline unsigned char eth_ipverlen (ethpacket_t * x) | |
267 | { return x->u.ip.verlen; } | |
268 | ||
269 | inline unsigned char eth_icmptype (ethpacket_t * x) | |
270 | { return x->u.ip.u.icmp.type; } | |
271 | ||
272 | inline unsigned char eth_icmpcode (ethpacket_t * x) | |
273 | { return x->u.ip.u.icmp.code; } | |
274 | ||
275 | /* | |
276 | inline unsigned char eth_tcptype (ethpacket_t * x) | |
277 | { return x->u.ip.u.tcp.protocol; } | |
278 | * I think we have to look for "known" tcp port numbers... * | |
279 | */ | |
280 | ||
281 | inline bool eth_tcpzlenack (ethpacket_t * x) | |
282 | { return (x->frametype == ET_IPv4) | |
283 | && (x->u.ip.iplen == 40) | |
284 | && (x->u.ip.protocol == IP_TCP) | |
285 | && (x->u.ip.u.tcp.flags & 0x10); } | |
286 | ||
287 | ||
288 | ||
289 | /* fetch MAC addresses */ | |
290 | inline uint64_t eth_srcMAC(ethpacket_t * x) | |
291 | { return eth_long (x->srcMAC); } | |
292 | inline uint64_t eth_dstMAC(ethpacket_t * x) | |
293 | { return eth_long (x->dstMAC); } | |
294 | ||
295 | inline void sprint_MACaddr (char * buf, uint64_t mac) | |
296 | { | |
297 | sprintf (buf, "%02x:%02x:%02x:%02x:%02x:%02x", /* char buf[18] */ | |
298 | (int)(mac>>40)&0xff, (int)(mac>>32)&0xff, (int)(mac>>24)&0xff, | |
299 | (int)(mac>>16)&0xff, (int)(mac>>8)&0xff, (int)(mac>>0)&0xff); | |
300 | } | |
301 | ||
302 | ||
303 | ||
304 | /* fetch IP addresses */ | |
305 | inline uint32_t eth_srcIP(ethpacket_t * x) | |
306 | { | |
307 | if (eth_type (x) == ET_ARP) return eth_int (x->u.arp.srcIP); | |
308 | else if (eth_type (x) == ET_IPv4) | |
309 | return eth_int (x->u.ip.srcIP); | |
310 | else return 0; | |
311 | } | |
312 | inline uint32_t eth_dstIP(ethpacket_t * x) | |
313 | { | |
314 | if (eth_type (x) == ET_ARP) return eth_int (x->u.arp.dstIP); | |
315 | else if (eth_type (x) == ET_IPv4) | |
316 | return eth_int (x->u.ip.dstIP); | |
317 | else return 0; | |
318 | } | |
319 | ||
320 | inline void sprint_IPaddr (char * buf, uint32_t ip) /* char buf[16] */ | |
321 | { | |
322 | sprintf (buf, "%d:%d:%d:%d", | |
323 | (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, (ip>>0)&0xff); | |
324 | } | |
325 | ||
326 | inline uint32_t sscan_IPaddr (char * buf) | |
327 | { | |
328 | unsigned int i1,i2,i3,i4; | |
329 | if (sscanf (buf, "%d:%d:%d:%d", &i1, &i2, &i3, &i4) == 4) { | |
330 | return (i1&0xff)<<24 | (i2&0xff)<<16 | (i3&0xff)<<8 | (i4&0xff)<<0; | |
331 | } else | |
332 | return 0xffffffff; | |
333 | } | |
334 | ||
335 | ||
336 | /* fetch TCP addresses */ | |
337 | inline uint32_t eth_srcPORT(ethpacket_t * x) | |
338 | { | |
339 | if (eth_type (x) == ET_IPv4 | |
340 | && eth_ipverlen (x) == 0x45 | |
341 | && eth_ipproto (x) == IP_TCP) | |
342 | return x->u.ip.u.tcp.srcPORT; | |
343 | else | |
344 | return -1; | |
345 | } | |
346 | inline uint32_t eth_dstPORT(ethpacket_t * x) | |
347 | { | |
348 | if (eth_type (x) == ET_IPv4 | |
349 | && eth_ipverlen (x) == 0x45 | |
350 | && eth_ipproto (x) == IP_TCP) | |
351 | return x->u.ip.u.tcp.dstPORT; | |
352 | else | |
353 | return -1; | |
354 | } | |
355 | ||
356 | ||
357 | #if 1 | |
358 | ||
359 | const char * eth_tcp_string (int tcptype); | |
360 | ||
361 | const char * eth_icmp_string (int icmptype, int icmpcode); | |
362 | ||
363 | ||
364 | #else /*** see "netsim.cc" ***/ | |
365 | ||
366 | char * eth_tcp_string (int tcptype) | |
367 | { | |
368 | static char buf[10]; | |
369 | ||
370 | switch (tcptype) { | |
371 | case TCP_ECHO: return "echo"; | |
372 | case TCP_FTPDATA: return "ftpdata"; | |
373 | case TCP_FTP: return "ftp"; | |
374 | case TCP_SSH: return "ssh"; | |
375 | case TCP_TELNET: return "telnet"; | |
376 | case TCP_TIME: return "time"; | |
377 | case TCP_DNS: return "dns"; | |
378 | case TCP_HTTP: return "http"; | |
379 | case TCP_HTTPS: return "https"; | |
380 | case TCP_SUNRPC: return "sunrpc"; | |
381 | case TCP_LDAP: return "ldap"; | |
382 | case TCP_REXEC: return "rexec"; | |
383 | case TCP_RLOGIN: return "rlogin"; | |
384 | case TCP_RSHELL: return "rshell"; | |
385 | default: | |
386 | sprintf(&buf[0], "%d", tcptype); | |
387 | return &buf[0]; | |
388 | } | |
389 | } | |
390 | ||
391 | char * eth_icmp_string (int icmptype, int icmpcode) | |
392 | { | |
393 | static char buf[10]; | |
394 | ||
395 | switch (icmptype) { | |
396 | case ICMP_ECHOREPLY: return "echo_reply"; | |
397 | case ICMP_UNREACHABLE: | |
398 | switch (icmpcode) { | |
399 | case 0: return "network_unreachable"; | |
400 | case 1: return "host_unreachable"; | |
401 | case 2: return "protocol_unreachable"; | |
402 | case 3: return "port_unreachable"; | |
403 | case 4: return "fragment_unreachable"; | |
404 | case 5: return "route_unreachable"; | |
405 | case 6: return "network_unknown"; | |
406 | case 7: return "host_unknown"; | |
407 | case 8: return "obsolete_unreachable"; | |
408 | case 9: return "network_prohibited"; | |
409 | case 10: return "host_prohibited"; | |
410 | case 11: return "network_tos_unreachable"; | |
411 | case 12: return "host_tos_unreachable"; | |
412 | default: return "unreachable_?"; | |
413 | } | |
414 | case ICMP_SRCQUENCH: return "source_quench"; | |
415 | case ICMP_REDIRECT: | |
416 | switch (icmpcode) { | |
417 | case 0: return "redirect_network"; | |
418 | case 1: return "redirect_host"; | |
419 | case 2: return "redirect_tos_network"; | |
420 | case 3: return "redirect_tos_host"; | |
421 | default: return "redirect_?"; | |
422 | } | |
423 | case ICMP_ECHO: return "echo_request"; | |
424 | case ICMP_ROUTERREPLY: return "router_reply"; | |
425 | case ICMP_ROUTERREQST: return "router_request"; | |
426 | case ICMP_TIMEOUT: return "time_exceeded"; | |
427 | case ICMP_INVARG: return "invalid_parameter"; | |
428 | case ICMP_TIMESTAMP: return "timestamp_request"; | |
429 | case ICMP_TSTAMPREPLY: return "timestamp_reply"; | |
430 | case ICMP_INFO: return "obsolete_request"; | |
431 | case ICMP_INFOREPLY: return "obsolete_reply"; | |
432 | case ICMP_MASK: return "mask_request"; | |
433 | case ICMP_MASKREPLY: return "mask_reply"; | |
434 | default: | |
435 | sprintf(&buf[0], "%d", icmptype); | |
436 | return &buf[0]; | |
437 | } | |
438 | } | |
439 | ||
440 | #endif | |
441 | ||
442 | ||
443 | #if 0 /*** see "netsim.cc"/netsim_dbgpacket() ***/ | |
444 | void eth_print () | |
445 | { | |
446 | int et,ipt; | |
447 | et = eth_type(&buffer.packet); | |
448 | fprintf (stderr, "eth{%02x->%02x,%s", | |
449 | eth_srcMAC(&buffer.packet) & 0xff, | |
450 | eth_dstMAC(&buffer.packet) & 0xff, | |
451 | (et == ET_IPv4 : "ip" ? | |
452 | et == ET_ARP : "arp" ? | |
453 | et == ET_RARP : "rarp" ? "?") ); | |
454 | switch (et) { | |
455 | case ET_IPv4: | |
456 | ipt = eth_ipproto(&buffer.packet); | |
457 | fprintf (stderr, "{%d.%d->%d.%d,%s", | |
458 | eth_srcIP(&buffer.packet) & 0xff, | |
459 | eth_dstIP(&buffer.packet) & 0xff, | |
460 | ipt); | |
461 | break; | |
462 | case ET_ARP: | |
463 | fprintf (stderr, "{ | |
464 | break; | |
465 | case ET_RARP: | |
466 | break; | |
467 | } | |
468 | fprintf (stderr, "}\n"); | |
469 | ||
470 | } | |
471 | #endif | |
472 | ||
473 | ||
474 | #endif /*_ETH_H*/ |