-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathENET.C
148 lines (133 loc) · 3.57 KB
/
ENET.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* Stuff generic to all Ethernet controllers
* Copyright 1991 Phil Karn, KA9Q
*/
/* Mods by PA0GRI */
#include "global.h"
#if defined PC_EC || defined PACKET
#include "mbuf.h"
#include "iface.h"
#include "arp.h"
#include "ip.h"
#include "enet.h"
char Ether_bdcst[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
/* Convert Ethernet header in host form to network mbuf */
struct mbuf *
htonether(ether,data)
struct ether *ether;
struct mbuf *data;
{
struct mbuf *bp;
register char *cp;
bp = pushdown(data,ETHERLEN);
cp = bp->data;
memcpy(cp,ether->dest,EADDR_LEN);
cp += EADDR_LEN;
memcpy(cp,ether->source,EADDR_LEN);
cp += EADDR_LEN;
put16(cp,ether->type);
return bp;
}
/* Extract Ethernet header */
int
ntohether(ether,bpp)
struct ether *ether;
struct mbuf **bpp;
{
pullup(bpp,ether->dest,EADDR_LEN);
pullup(bpp,ether->source,EADDR_LEN);
ether->type = (int16) pull16(bpp);
return ETHERLEN;
}
/* Format an Ethernet address into a printable ascii string */
char *
pether(out,addr)
char *out,*addr;
{
sprintf(out,"%02x:%02x:%02x:%02x:%02x:%02x",
uchar(addr[0]),uchar(addr[1]),
uchar(addr[2]),uchar(addr[3]),
uchar(addr[4]),uchar(addr[5]));
return out;
}
/* Convert an Ethernet address from Hex/ASCII to binary */
int
gether(out,cp)
register char *out;
register char *cp;
{
register int i;
for(i=6; i!=0; i--){
*out++ = htoi(cp);
if((cp = strchr(cp,':')) == NULLCHAR) /* Find delimiter */
break;
cp++; /* and skip over it */
}
return i;
}
/* Send an IP datagram on Ethernet */
int
enet_send(bp,iface,gateway,prec,del,tput,rel)
struct mbuf *bp; /* Buffer to send */
struct iface *iface; /* Pointer to interface control block */
int32 gateway; /* IP address of next hop */
int prec;
int del;
int tput;
int rel;
{
char *egate;
if(gateway == iface->broadcast) /* This is a broadcast IP datagram */
return (*iface->output)(iface,Ether_bdcst,iface->hwaddr,IP_TYPE,bp);
egate = res_arp(iface,ARP_ETHER,gateway,bp);
if(egate != NULLCHAR)
return (*iface->output)(iface,egate,iface->hwaddr,IP_TYPE,bp);
return 0;
}
/* Send a packet with Ethernet header */
int
enet_output(iface,dest,source,type,data)
struct iface *iface; /* Pointer to interface control block */
char *dest; /* Destination Ethernet address */
char *source; /* Source Ethernet address */
int16 type; /* Type field */
struct mbuf *data; /* Data field */
{
struct ether ep;
struct mbuf *bp;
memcpy(ep.dest,dest,EADDR_LEN);
memcpy(ep.source,source,EADDR_LEN);
ep.type = type;
if((bp = htonether(&ep,data)) == NULLBUF){
free_p(data);
return -1;
}
return (*iface->raw)(iface,bp);
}
/* Process incoming Ethernet packets. Shared by all ethernet drivers. */
void
eproc(iface,bp)
struct iface *iface;
struct mbuf *bp;
{
struct ether hdr;
/* Remove Ethernet header and kick packet upstairs */
ntohether(&hdr,&bp);
if(memcmp(hdr.dest,iface->hwaddr,EADDR_LEN) &&
memcmp(hdr.dest,Ether_bdcst,EADDR_LEN)){
free_p(bp);
return;
}
switch(hdr.type){
case REVARP_TYPE:
case ARP_TYPE:
arp_input(iface,bp);
break;
case IP_TYPE:
ip_route(iface,bp,hdr.dest[0] & 1);
break;
default:
free_p(bp);
break;
}
}
#endif /* PC_EC || PACKET */