Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
const uchar *t;
const ushort *ss;
ushort type, tlen;
uchar applid;
ushort vlan, nvlan;
/* minimum size? */
if (len < sizeof(CDP_SNAP_hdr) + 4)
goto pkt_short;
/* check for valid CDP SNAP header */
if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0)
return;
pkt += sizeof(CDP_SNAP_hdr);
len -= sizeof(CDP_SNAP_hdr);
/* Version of CDP protocol must be >= 2 and TTL != 0 */
if (pkt[0] < 0x02 || pkt[1] == 0)
return;
/* if version is greater than 0x02 maybe we'll have a problem; output a warning */
if (pkt[0] != 0x02)
printf("** WARNING: CDP packet received with a protocol version %d > 2\n",
pkt[0] & 0xff);
if (CDP_compute_csum(pkt, len) != 0)
return;
pkt += 4;
len -= 4;
vlan = htons(-1);
nvlan = htons(-1);
while (len > 0) {
if (len < 4)
goto pkt_short;
ss = (const ushort *)pkt;
type = ntohs(ss[0]);
tlen = ntohs(ss[1]);
if (tlen > len) {
goto pkt_short;
}
pkt += tlen;
len -= tlen;
ss += 2; /* point ss to the data of the TLV */
tlen -= 4;
switch (type) {
case CDP_DEVICE_ID_TLV:
break;
case CDP_ADDRESS_TLV:
break;
case CDP_PORT_ID_TLV:
break;
case CDP_CAPABILITIES_TLV:
break;
case CDP_VERSION_TLV:
break;
case CDP_PLATFORM_TLV:
break;
case CDP_NATIVE_VLAN_TLV:
nvlan = *ss;
break;
case CDP_APPLIANCE_VLAN_TLV:
t = (const uchar *)ss;
while (tlen > 0) {
if (tlen < 3)
goto pkt_short;
applid = t[0];
ss = (const ushort *)(t + 1);
#ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE
if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
vlan = *ss;
#else
vlan = ntohs(*ss); /* XXX will this work; dunno */
#endif
t += 3; tlen -= 3;
}
break;
case CDP_TRIGGER_TLV:
break;
case CDP_POWER_CONSUMPTION_TLV:
break;
case CDP_SYSNAME_TLV:
break;
case CDP_SYSOBJECT_TLV:
break;
case CDP_MANAGEMENT_ADDRESS_TLV:
break;
}
}
CDPApplianceVLAN = vlan;
CDPNativeVLAN = nvlan;
CDPOK = 1;
return;
pkt_short:
printf("** CDP packet is too short\n");
return;
}
static void CDPStart(void)
{
#if defined(CONFIG_NET_MULTI)
printf ("Using %s device\n", eth_get_name());
#endif
CDPSeq = 0;
CDPOK = 0;
CDPNativeVLAN = htons(-1);
CDPApplianceVLAN = htons(-1);
NetSetTimeout (CDP_TIMEOUT, CDPTimeout);
NetSetHandler (CDPDummyHandler);
CDPSendTrigger();
}
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
#ifdef CONFIG_IP_DEFRAG
/*
* This function collects fragments in a single packet, according
* to the algorithm in RFC815. It returns NULL or the pointer to
* a complete packet, in static storage
*/
#ifndef CONFIG_NET_MAXDEFRAG
#define CONFIG_NET_MAXDEFRAG 16384
#endif
/*
* MAXDEFRAG, above, is chosen in the config file and is real data
* so we need to add the NFS overhead, which is more than TFTP.
* To use sizeof in the internal unnamed structures, we need a real
* instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately).
* The compiler doesn't complain nor allocates the actual structure
*/
static struct rpc_t rpc_specimen;
#define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply))
#define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE_NO_UDP)
/*
* this is the packet being assembled, either data or frag control.
* Fragments go by 8 bytes, so this union must be 8 bytes long
*/
struct hole {
/* first_byte is address of this structure */
u16 last_byte; /* last byte in this hole + 1 (begin of next hole) */
u16 next_hole; /* index of next (in 8-b blocks), 0 == none */
u16 prev_hole; /* index of prev, 0 == none */
u16 unused;
};
static IP_t *__NetDefragment(IP_t *ip, int *lenp)
{
static uchar pkt_buff[IP_PKTSIZE] __attribute__((aligned(PKTALIGN)));
static u16 first_hole, total_len;
struct hole *payload, *thisfrag, *h, *newh;
IP_t *localip = (IP_t *)pkt_buff;
uchar *indata = (uchar *)ip;
int offset8, start, len, done = 0;
u16 ip_off = ntohs(ip->ip_off);
/* payload starts after IP header, this fragment is in there */
payload = (struct hole *)(pkt_buff + IP_HDR_SIZE_NO_UDP);
offset8 = (ip_off & IP_OFFS);
thisfrag = payload + offset8;
start = offset8 * 8;
len = ntohs(ip->ip_len) - IP_HDR_SIZE_NO_UDP;
if (start + len > IP_MAXUDP) /* fragment extends too far */
return NULL;
if (!total_len || localip->ip_id != ip->ip_id) {
/* new (or different) packet, reset structs */
total_len = 0xffff;
payload[0].last_byte = ~0;
payload[0].next_hole = 0;
payload[0].prev_hole = 0;
first_hole = 0;
/* any IP header will work, copy the first we received */
memcpy(localip, ip, IP_HDR_SIZE_NO_UDP);
}
/*
* What follows is the reassembly algorithm. We use the payload
* array as a linked list of hole descriptors, as each hole starts
* at a multiple of 8 bytes. However, last byte can be whatever value,
* so it is represented as byte count, not as 8-byte blocks.
*/
h = payload + first_hole;
while (h->last_byte < start) {
if (!h->next_hole) {
/* no hole that far away */
return NULL;
}
h = payload + h->next_hole;
}
/* last fragment may be 1..7 bytes, the "+7" forces acceptance */
if (offset8 + ((len + 7) / 8) <= h - payload) {
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
/* no overlap with holes (dup fragment?) */
return NULL;
}
if (!(ip_off & IP_FLAGS_MFRAG)) {
/* no more fragmentss: truncate this (last) hole */
total_len = start + len;
h->last_byte = start + len;
}
/*
* There is some overlap: fix the hole list. This code doesn't
* deal with a fragment that overlaps with two different holes
* (thus being a superset of a previously-received fragment).
*/
if ( (h >= thisfrag) && (h->last_byte <= start + len) ) {
/* complete overlap with hole: remove hole */
if (!h->prev_hole && !h->next_hole) {
/* last remaining hole */
done = 1;
} else if (!h->prev_hole) {
/* first hole */
first_hole = h->next_hole;
payload[h->next_hole].prev_hole = 0;
} else if (!h->next_hole) {
/* last hole */
payload[h->prev_hole].next_hole = 0;
} else {
/* in the middle of the list */
payload[h->next_hole].prev_hole = h->prev_hole;
payload[h->prev_hole].next_hole = h->next_hole;
}
} else if (h->last_byte <= start + len) {
/* overlaps with final part of the hole: shorten this hole */
h->last_byte = start;
} else if (h >= thisfrag) {
/* overlaps with initial part of the hole: move this hole */
newh = thisfrag + (len / 8);
*newh = *h;
h = newh;
if (h->next_hole)
payload[h->next_hole].prev_hole = (h - payload);
if (h->prev_hole)
payload[h->prev_hole].next_hole = (h - payload);
else
first_hole = (h - payload);
} else {
/* fragment sits in the middle: split the hole */
newh = thisfrag + (len / 8);
*newh = *h;
h->last_byte = start;
h->next_hole = (newh - payload);
newh->prev_hole = (h - payload);
if (newh->next_hole)
payload[newh->next_hole].prev_hole = (newh - payload);
}
/* finally copy this fragment and possibly return whole packet */
memcpy((uchar *)thisfrag, indata + IP_HDR_SIZE_NO_UDP, len);
if (!done)
return NULL;
localip->ip_len = htons(total_len);
*lenp = total_len + IP_HDR_SIZE_NO_UDP;
return localip;
}
static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
{
u16 ip_off = ntohs(ip->ip_off);
if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
return ip; /* not a fragment */
return __NetDefragment(ip, lenp);
}
#else /* !CONFIG_IP_DEFRAG */
static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
{
u16 ip_off = ntohs(ip->ip_off);
if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
return ip; /* not a fragment */
return NULL;
}
#endif
NetReceive(volatile uchar * inpkt, int len)
{
Ethernet_t *et;
IP_t *ip;
ARP_t *arp;
IPaddr_t tmp;
int x;
#if defined(CONFIG_CMD_CDP)
int iscdp;
#endif
ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
NetRxPacket = inpkt;
NetRxPacketLen = len;
et = (Ethernet_t *)inpkt;
/* too small packet? */
if (len < ETHER_HDR_SIZE)
return;
#ifdef CONFIG_API
if (push_packet) {
(*push_packet)(inpkt, len);
return;
}
#endif
#if defined(CONFIG_CMD_CDP)
/* keep track if packet is CDP */
iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0;
#endif
myvlanid = ntohs(NetOurVLAN);
if (myvlanid == (ushort)-1)
myvlanid = VLAN_NONE;
mynvlanid = ntohs(NetOurNativeVLAN);
if (mynvlanid == (ushort)-1)
mynvlanid = VLAN_NONE;
if (x < 1514) {
/*
* Got a 802 packet. Check the other protocol field.
*/
x = ntohs(et->et_prot);
ip = (IP_t *)(inpkt + E802_HDR_SIZE);
} else if (x != PROT_VLAN) { /* normal packet */
ip = (IP_t *)(inpkt + ETHER_HDR_SIZE);
} else { /* VLAN packet */
VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et;
/* too small packet? */
if (len < VLAN_ETHER_HDR_SIZE)
return;
/* if no VLAN active */
if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE
#if defined(CONFIG_CMD_CDP)
&& iscdp == 0
#endif
)
return;
cti = ntohs(vet->vet_tag);
vlanid = cti & VLAN_IDMASK;
x = ntohs(vet->vet_type);
ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE);
len -= VLAN_ETHER_HDR_SIZE;
#if defined(CONFIG_CMD_CDP)
if (iscdp) {
CDPHandler((uchar *)ip, len);
return;
}
#endif
if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) {
if (vlanid == VLAN_NONE)
vlanid = (mynvlanid & VLAN_IDMASK);
/* not matched? */
if (vlanid != (myvlanid & VLAN_IDMASK))
return;
}
switch (x) {
case PROT_ARP:
/*
* We have to deal with two types of ARP packets:
* - REQUEST packets will be answered by sending our
* IP address - if we know it.
* - REPLY packates are expected only after we asked
* for the TFTP server's or the gateway's ethernet
* address; so if we receive such a packet, we set
* the server ethernet address
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
arp = (ARP_t *)ip;
if (len < ARP_HDR_SIZE) {
printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
return;
}
if (ntohs(arp->ar_hrd) != ARP_ETHER) {
return;
}
if (ntohs(arp->ar_pro) != PROT_IP) {
return;
}
if (arp->ar_hln != 6) {
return;
}
if (arp->ar_pln != 4) {
return;
}
if (NetOurIP == 0) {
return;
}
if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
return;
}
switch (ntohs(arp->ar_op)) {
case ARPOP_REQUEST: /* reply with our IP address */
pkt = (uchar *)et;
pkt += NetSetEther(pkt, et->et_src, PROT_ARP);
arp->ar_op = htons(ARPOP_REPLY);
memcpy (&arp->ar_data[10], &arp->ar_data[0], 6);
NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
memcpy (&arp->ar_data[ 0], NetOurEther, 6);
NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
(void) eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE);
case ARPOP_REPLY: /* arp reply */
/* are we waiting for a reply */
if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
break;
#ifdef CONFIG_KEEP_SERVERADDR
if (NetServerIP == NetArpWaitPacketIP) {
char buf[20];
sprintf(buf, "%pM", arp->ar_data);
setenv("serveraddr", buf);
}
#endif
debug("Got ARP REPLY, set server/gtwy eth addr (%pM)\n",
arp->ar_data);
tmp = NetReadIP(&arp->ar_data[6]);
/* matched waiting packet's address */
if (tmp == NetArpWaitReplyIP) {
/* save address for later use */
memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
#ifdef CONFIG_NETCONSOLE
(*packetHandler)(0,0,0,0);
#endif
/* modify header, and transmit it */
memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
(void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
/* no arp request pending now */
NetArpWaitPacketIP = 0;
NetArpWaitTxPacketSize = 0;
NetArpWaitPacketMAC = NULL;
}
debug("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
arp = (ARP_t *)ip;
if (len < ARP_HDR_SIZE) {
printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
return;
}
if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
(ntohs(arp->ar_hrd) != ARP_ETHER) ||
(ntohs(arp->ar_pro) != PROT_IP) ||
(arp->ar_hln != 6) || (arp->ar_pln != 4)) {
puts ("invalid RARP header\n");
} else {
NetCopyIP(&NetOurIP, &arp->ar_data[16]);
if (NetServerIP == 0)
NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
memcpy (NetServerEther, &arp->ar_data[ 0], 6);
(*packetHandler)(0,0,0,0);
}
break;
/* Before we start poking the header, make sure it is there */
debug("len bad %d < %lu\n", len, (ulong)IP_HDR_SIZE);
if (len < ntohs(ip->ip_len)) {
printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
return;
}
len = ntohs(ip->ip_len);
debug("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
/* Can't deal with anything except IPv4 */
if ((ip->ip_hl_v & 0xf0) != 0x40) {
return;
}
/* Can't deal with IP options (headers != 20 bytes) */
if ((ip->ip_hl_v & 0x0f) > 0x05) {
return;
}
if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
tmp = NetReadIP(&ip->ip_dst);
if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
/*
* The function returns the unchanged packet if it's not
* a fragment, and either the complete packet or NULL if
* it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
*/
if (!(ip = NetDefragment(ip, &len)))
return;
* There is no real handler code (yet). We just watch
* for ICMP host redirect messages. In case anybody
* sees these messages: please contact me
* (wd@denx.de), or - even better - send me the
* necessary fixes :-)
* Note: in all cases where I have seen this so far
* it was a problem with the router configuration,
* for instance when a router was configured in the
* BOOTP reply, but the TFTP server was on the same
* subnet. So this is probably a warning that your
* configuration might be wrong. But I'm not really
* sure if there aren't any other situations.
*/
if (ip->ip_p == IPPROTO_ICMP) {
ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
switch (icmph->type) {
case ICMP_REDIRECT:
if (icmph->code != ICMP_REDIR_HOST)
return;
printf (" ICMP Host Redirect to %pI4 ", &icmph->un.gateway);
return;
#if defined(CONFIG_CMD_PING)
case ICMP_ECHO_REPLY:
/*
* IP header OK. Pass the packet to the current handler.
*/
/* XXX point to ip packet */
(*packetHandler)((uchar *)ip, 0, 0, 0);
return;
case ICMP_ECHO_REQUEST:
debug("Got ICMP ECHO REQUEST, return %d bytes \n",
ETHER_HDR_SIZE + len);
memcpy (&et->et_dest[0], &et->et_src[0], 6);
memcpy (&et->et_src[ 0], NetOurEther, 6);
ip->ip_sum = 0;
ip->ip_off = 0;
NetCopyIP((void*)&ip->ip_dst, &ip->ip_src);
NetCopyIP((void*)&ip->ip_src, &NetOurIP);
ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP >> 1);
icmph->type = ICMP_ECHO_REPLY;
icmph->checksum = 0;
icmph->checksum = ~NetCksum((uchar *)icmph,
(len - IP_HDR_SIZE_NO_UDP) >> 1);
(void) eth_send((uchar *)et, ETHER_HDR_SIZE + len);
return;
} else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */
return;
}
#ifdef CONFIG_UDP_CHECKSUM
if (ip->udp_xsum != 0) {
ushort *sumptr;
ushort sumlen;
xsum = ip->ip_p;
xsum += (ntohs(ip->udp_len));
xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff;
xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff;
xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff;
xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff;
sumlen = ntohs(ip->udp_len);
sumptr = (ushort *) &(ip->udp_src);
while (sumlen > 1) {
sumdata = *sumptr++;
xsum += ntohs(sumdata);
sumlen -= 2;
}
if (sumlen > 0) {
sumdata = *(unsigned char *) sumptr;
xsum += sumdata;
}
while ((xsum >> 16) != 0) {
xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff);
}
if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) {
printf(" UDP wrong checksum %08lx %08x\n",
xsum, ntohs(ip->udp_xsum));
return;
}
}
#endif
#ifdef CONFIG_NETCONSOLE
nc_input_packet((uchar *)ip +IP_HDR_SIZE,
ntohs(ip->udp_dst),
ntohs(ip->udp_src),
ntohs(ip->udp_len) - 8);
#endif
/*
* IP header OK. Pass the packet to the current handler.
*/
(*packetHandler)((uchar *)ip +IP_HDR_SIZE,
ntohs(ip->udp_dst),
ntohs(ip->udp_src),
ntohs(ip->udp_len) - 8);
break;
}
}
/**********************************************************************/
static int net_check_prereq (proto_t protocol)
{
switch (protocol) {
#if defined(CONFIG_CMD_PING)
if (NetPingIP == 0) {
puts ("*** ERROR: ping address not given\n");
return (1);
}
goto common;
#if defined(CONFIG_CMD_SNTP)
case SNTP:
if (NetNtpServerIP == 0) {
puts ("*** ERROR: NTP server address not given\n");
return (1);
}
goto common;
#endif
#if defined(CONFIG_CMD_DNS)
case DNS:
if (NetOurDNSIP == 0) {
puts("*** ERROR: DNS server address not given\n");
return 1;
}
goto common;
#endif
#if defined(CONFIG_CMD_NFS)
if (NetServerIP == 0) {
puts ("*** ERROR: `serverip' not set\n");
return (1);
}
#if defined(CONFIG_CMD_PING) || defined(CONFIG_CMD_SNTP) || \
defined(CONFIG_CMD_DNS)
if (NetOurIP == 0) {
puts ("*** ERROR: `ipaddr' not set\n");
return (1);
}
/* Fall through */
if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
extern int eth_get_dev_index (void);
int num = eth_get_dev_index ();
puts ("*** ERROR: No ethernet found.\n");
return (1);
puts ("*** ERROR: `ethaddr' not set\n");
return (1);
}
/* Fall through */
default:
return (0);
}
/**********************************************************************/
int
NetCksumOk(uchar * ptr, int len)
{
return !((NetCksum(ptr, len) + 1) & 0xfffe);
}
unsigned
NetCksum(uchar * ptr, int len)
{
ulong xsum;
ushort *p = (ushort *)ptr;
xsum = (xsum & 0xffff) + (xsum >> 16);
xsum = (xsum & 0xffff) + (xsum >> 16);
return (xsum & 0xffff);
}
int
NetEthHdrSize(void)
{
ushort myvlanid;
myvlanid = ntohs(NetOurVLAN);
if (myvlanid == (ushort)-1)
myvlanid = VLAN_NONE;
return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE;
}
int
NetSetEther(volatile uchar * xet, uchar * addr, uint prot)
{
Ethernet_t *et = (Ethernet_t *)xet;
ushort myvlanid;
myvlanid = ntohs(NetOurVLAN);
if (myvlanid == (ushort)-1)
myvlanid = VLAN_NONE;
memcpy (et->et_dest, addr, 6);
memcpy (et->et_src, NetOurEther, 6);
if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) {
return ETHER_HDR_SIZE;
} else {
VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet;
vet->vet_vlan_type = htons(PROT_VLAN);
vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK));
vet->vet_type = htons(prot);
return VLAN_ETHER_HDR_SIZE;
}
}
void
NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
{
/*
* If the data is an odd number of bytes, zero the
* byte after the last byte so that the checksum
* will work.
*/
if (len & 1)
xip[IP_HDR_SIZE + len] = 0;
/*
* Construct an IP and UDP header.
*/
ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
ip->ip_tos = 0;
ip->ip_len = htons(IP_HDR_SIZE + len);
ip->ip_id = htons(NetIPID++);
ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */
ip->ip_ttl = 255;
ip->ip_p = 17; /* UDP */
ip->ip_sum = 0;
NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
ip->udp_src = htons(sport);
ip->udp_dst = htons(dport);
ip->udp_len = htons(8 + len);
ip->udp_xsum = 0;
ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
}
void copy_filename (char *dst, const char *src, int size)
{
if (*src && (*src == '"')) {
++src;
--size;
}
while ((--size > 0) && *src && (*src != '"')) {
*dst++ = *src++;
}
*dst = '\0';
}
#if defined(CONFIG_CMD_NFS) || defined(CONFIG_CMD_SNTP) || defined(CONFIG_CMD_DNS)
/*
* make port a little random (1024-17407)
* This keeps the math somewhat trivial to compute, and seems to work with
* all supported protocols/clients/servers
return 1024 + (get_timer(0) % 0x4000);
x = ntohl (x);
sprintf (s, "%d.%d.%d.%d",
(int) ((x >> 24) & 0xff),
(int) ((x >> 16) & 0xff),
(int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
void VLAN_to_string(ushort x, char *s)
{
x = ntohs(x);
if (x == (ushort)-1)
x = VLAN_NONE;
if (x == VLAN_NONE)
strcpy(s, "none");
else
sprintf(s, "%d", x & VLAN_IDMASK);
}
ushort string_to_VLAN(const char *s)
{
ushort id;
if (s == NULL)
if (*s < '0' || *s > '9')
id = VLAN_NONE;
else
id = (ushort)simple_strtoul(s, NULL, 10);
}
ushort getenv_VLAN(char *var)
{
return (string_to_VLAN(getenv(var)));
}