add initial support for the crisarchitecture used on foxboards to openwrt
[openwrt/staging/lynxis/omap.git] / target / linux / etrax-2.6 / image / e100boot / src / sbl / win32 / network.c
1 /*!***************************************************************************
2 *!
3 *! FILE NAME : network.c
4 *!
5 *! DESCRIPTION: Network boot stuff for e100boot.
6 *!
7 *! ---------------------------------------------------------------------------
8 *! HISTORY
9 *!
10 *! DATE NAME CHANGES
11 *! ---- ---- -------
12 *! 1996 Ronny Raneup Initial version
13 *! 2002 05 02 Ronny Ranerup Moved it into this file
14 *! ---------------------------------------------------------------------------
15 *! (C) Copyright 1999, 2000, 2001, 2002 Axis Communications AB, LUND, SWEDEN
16 *!***************************************************************************/
17
18 /************************** Include files ********************************/
19
20 #include <stdio.h>
21 #define WIN32_LEAN_AND_MEAN
22 #include <windows.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <sys/timeb.h>
27 #include <winsock2.h>
28
29 #include <pcap.h>
30 #include <Packet32.h>
31 #include <Ntddndis.h>
32
33 #include <e100boot.h>
34 #include <common.h>
35 #include <network.h>
36
37 /************************** Constants and macros *************************/
38
39 #define CRC_LEN 4
40
41 /************************** Type definitions *****************************/
42
43 /************************** Global variables *****************************/
44
45 udword highest_ack_received;
46 udword last_ack_received = -1;
47 int new_ack = FALSE;
48 int got_new_packet = FALSE;
49
50 unsigned char dst_addr_of_device[] = { 0x01, 0x40, 0x8c, 0x00, 0x01, 0x00 };
51 unsigned char src_addr_of_device[] = { 0x02, 0x40, 0x8c, 0x00, 0x01, 0x00 };
52 unsigned char eth_addr_local[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
53
54 struct sockaddr sock_addr;
55 int pPacket = 0;
56 pcap_t *pd;
57
58 pcap_handler handler;
59
60 struct packet_buf first_rec_packet;
61 struct packet_buf *last_rec_packet = &first_rec_packet;
62
63 int promisc = 1; /* promiscuous mode */
64 int all_ids = TRUE;
65
66 int both_addresses = FALSE;
67 int p_packet_bpl = 8;
68 int printPacketType = CHAR;
69
70 unsigned int id;
71 int one_id_only = TRUE;
72
73 unsigned char buf[16000]; /* pcap buffer */
74
75 const struct pcap_pkthdr *hdrG;
76
77 char host1[MAX_STRING_LEN]; /* name of ethernet host */
78 char host2[MAX_STRING_LEN]; /* name of ethernet host */
79
80 /************************** Function prototypes **************************/
81
82 int gettimeofday (struct timeval *tv, void*);
83 int timeout (struct timeval *tvThen, int ms);
84 int highest_seq_received (void);
85 struct packet_buf* ack_on_seq (int seq);
86 struct packet_buf* packet_with_seq (int seq);
87 struct timeval timeval_subtract (struct timeval *x, struct timeval *y);
88 void GetNextPacket (void);
89 void PrintPacket (const unsigned char *p, int size, int type);
90
91 /****************************************************************************
92 *#
93 *# FUNCTION NAME: net_init
94 *#
95 *# DESCRIPTION:
96 *#
97 *#---------------------------------------------------------------------------
98 *# HISTORY
99 *#
100 *# DATE NAME CHANGES
101 *# ---- ---- -------
102 *# 2002 05 02 ronny Initial version
103 *#
104 *#***************************************************************************/
105 void
106 net_init(void)
107 {
108 pcap_if_t* alldevs;
109 pcap_if_t* d;
110 char errbuf[PCAP_ERRBUF_SIZE];
111 LPADAPTER pAdapter;
112 char pOidDataBuf[sizeof(PACKET_OID_DATA)-1+sizeof(eth_addr_local)];
113 PPACKET_OID_DATA pOidData;
114
115 if (strlen(device) == 0) {
116 /* Retrieve the device list */
117 if (pcap_findalldevs(&alldevs, errbuf) == -1) {
118 fprintf(stderr,"Error finding devices: %s\n", errbuf);
119 exit(EXIT_FAILURE);
120 }
121
122 if (alldevs == NULL) {
123 printf("\nNo network adapters found!\n");
124 exit(EXIT_FAILURE);
125 }
126
127 /* Use first device/interface */
128 d = alldevs;
129 if (db1) printf("Using device %s (%s)\n", d->name,
130 (d->description ? d->description :
131 "No description available"));
132 strcpy(device, d->name);
133 pcap_freealldevs(alldevs);
134 }
135
136 if ((pd = pcap_open_live(device, 200, promisc, -1, errbuf)) == NULL) {
137 printf("Error opening device %s\n", errbuf);
138 exit(EXIT_FAILURE);
139 }
140
141 /* Determine Ethernet address */
142 if ((pAdapter = PacketOpenAdapter(device)) == NULL) {
143 printf("Error opening packet adapter!\n");
144 exit(EXIT_FAILURE);
145 }
146
147 pOidData = &pOidDataBuf[0];
148 pOidData->Oid = OID_802_3_CURRENT_ADDRESS;
149 pOidData->Length = sizeof(eth_addr_local);
150 if (!PacketRequest(pAdapter, FALSE, pOidData)) {
151 printf("Error obtaining adapter Ethernet address!\n");
152 exit(EXIT_FAILURE);
153 }
154
155 PacketCloseAdapter(pAdapter);
156 pAdapter = NULL;
157
158 memcpy(eth_addr_local, pOidData->Data, sizeof(eth_addr_local));
159 if (db1) printf("Ethernet adress for device is %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
160 eth_addr_local[0],
161 eth_addr_local[1],
162 eth_addr_local[2],
163 eth_addr_local[3],
164 eth_addr_local[4],
165 eth_addr_local[5]);
166
167 handler = (pcap_handler) Handler;
168 }
169
170 /****************************************************************************
171 *#
172 *# FUNCTION NAME: NetBoot
173 *#
174 *# DESCRIPTION: The main network boot routine.
175 *#
176 *#---------------------------------------------------------------------------
177 *# HISTORY
178 *#
179 *# DATE NAME CHANGES
180 *# ---- ---- -------
181 *# 2000 01 07 ronny Initial version
182 *# 2002 05 02 ronny Fixed segv bug
183 *#
184 *#***************************************************************************/
185
186 void
187 NetBoot(void)
188 {
189 struct packet_buf *p;
190 struct timeval tv;
191
192 gettimeofday(&tv, NULL);
193
194 p = create_packet(0);
195 SendToDevice(p->data, p->size);
196
197 while(1) {
198 static int all_trans = FALSE;
199
200 if (got_new_packet) {
201 got_new_packet = FALSE;
202
203 if (new_ack && first_packet) {
204 if (db4) {
205 printf("* got ACK %d.\n", last_ack_received);
206 printf("* ACK wanted %d.\n", first_packet->seq);
207 }
208 if (last_ack_received == first_packet->seq) {
209 if (!(p = create_packet(first_packet->seq+1))) {
210 //break;
211 }
212 first_packet = free_packet(first_packet);
213 }
214 }
215 }
216
217 if (new_ack || timeout(&tv, 500)) {
218 if (p) {
219 SendToDevice(p->data, p->size);
220 }
221 new_ack = FALSE;
222 gettimeofday(&tv, NULL);
223 }
224
225 GetNextPacket();
226 }
227 }
228
229 /****************************************************************************
230 *#
231 *# FUNCTION NAME: GetNextPacket
232 *#
233 *# DESCRIPTION:
234 *#
235 *#---------------------------------------------------------------------------
236 *# HISTORY
237 *#
238 *# DATE NAME CHANGES
239 *# ---- ---- -------
240 *# 961022 ronny Initial version
241 *#
242 *#***************************************************************************/
243
244 void
245 GetNextPacket(void)
246 {
247 int ret;
248
249 if (db2) printf("> GetNextPacket\n");
250
251 /* got_new_packet = FALSE;*/
252 if ((ret = pcap_dispatch(pd, 1, handler, buf)) == -1) {
253 pcap_perror(pd, "Error in pcap_dispatch");
254 exit(EXIT_FAILURE);
255 }
256
257 if (db2) printf("< GetNextPacket\n");
258 }
259
260 /****************************************************************************
261 *#
262 *# FUNCTION NAME: Handler
263 *#
264 *# PARAMETERS:
265 *#
266 *# DESCRIPTION:
267 *#
268 *#---------------------------------------------------------------------------
269 *# HISTORY
270 *#
271 *# DATE NAME CHANGES
272 *# ---- ---- -------
273 *# 961022 ronny Initial version
274 *#
275 *#***************************************************************************/
276
277 void
278 Handler(unsigned char *buf, const struct pcap_pkthdr *hdr,
279 const unsigned char *p)
280 {
281 const unsigned char *src = &p[6];
282 const unsigned char *dst = &p[0];
283 struct packet_header_T *h = (struct packet_header_T*)p;
284
285 if (db2) printf("> Handler\n");
286 got_new_packet = TRUE;
287 if ((!memcmp(src, eth_addr_local, 6) && !memcmp(dst, dst_addr_of_device, 6))
288 || (!memcmp(src, src_addr_of_device, 6) && !memcmp(dst, eth_addr_local, 6))) {
289 if (db1) printf("#RX######################################################\n");
290 if (db1) printf("Length: %u(0x%x)\n", (udword)hdr->len, (udword)hdr->len);
291 if (pPacket) PrintPacket(p, hdr->caplen, printPacketType);
292 DecodeSvintoBoot(p);
293 /* should clean up this... */
294 if ((ntohl(h->type) == ACK)) {
295 if (all_ids || (ntohl(h->id) == id)) {
296 if (all_ids && one_id_only) {
297 if (ntohl(h->id) == 0) {
298 all_ids = FALSE;
299 id = ntohl(h->id);
300 printf("Booting device with random id %8.8x.\n", id);
301 }
302 }
303 }
304 else {
305 printf("Got ACK from a new id, %8.8lx. Ignoring.\n",
306 (unsigned long)ntohl(h->id));
307 return;
308 }
309 new_ack = TRUE;
310 last_ack_received = ntohl(h->seq);
311 if (last_ack_received > highest_ack_received) {
312 highest_ack_received = last_ack_received;
313 }
314 }
315
316 if (db1) printf("#########################################################\n");
317
318 }
319 if (db2) printf("< Handler\n");
320 }
321
322 /****************************************************************************
323 *#
324 *# FUNCTION NAME: ack_on_seq
325 *#
326 *# PARAMETERS:
327 *#
328 *# DESCRIPTION:
329 *#
330 *#---------------------------------------------------------------------------
331 *# HISTORY
332 *#
333 *# DATE NAME CHANGES
334 *# ---- ---- -------
335 *# 980817 ronny Initial version
336 *#
337 *#***************************************************************************/
338
339 struct packet_buf *
340 packet_with_seq(int seq)
341 {
342 static int last_seq = 0;
343 struct packet_buf *p = first_packet;
344 struct packet_header_T *h;
345
346 if (seq < last_seq) {
347 p = first_packet;
348 }
349
350 while(p) {
351 h = (struct packet_header_T*)p->data;
352 if (ntohl(h->seq) == seq) {
353 return(p);
354 }
355 p = p->next;
356 }
357 return(NULL);
358 }
359
360 struct packet_buf *
361 ack_on_seq(int seq)
362 {
363 struct packet_buf *p = &first_rec_packet;
364 struct packet_header_T *h;
365
366 if (db1) printf("***> ack_on_seq: %d.\n", seq);
367
368 while (p) {
369 /* printf("\nPacket at %x.\n", p);*/
370 /* DecodeSvintoBoot(p->data);*/
371 h = (struct packet_header_T*)p->data;
372 if ( (ntohl(h->type) == ACK) && (ntohl(h->seq) == seq) ) {
373 if (all_ids || ntohl(h->id) == id) {
374 printf("***< ack_on_seq %d, ok.\n", seq);
375 return(p);
376 }
377 }
378 p = p->next;
379 }
380 if (db1) printf("***< ack_on_seq, no.\n");
381 return(NULL);
382 }
383
384 int
385 highest_seq_received(void)
386 {
387 struct packet_buf *p = &first_rec_packet;
388 struct packet_header_T *h;
389 int highest_seq = -1;
390
391 if (db1) printf("***> highest_seq_received\n");
392
393 while (p) {
394 /* printf("\nPacket at %x.\n", p);*/
395 /* DecodeSvintoBoot(p->data);*/
396 h = (struct packet_header_T*)p->data;
397 if ((ntohl(h->type) == ACK) && (all_ids || (ntohl(h->id) == id))) {
398 if ((int)ntohl(h->seq) > highest_seq) {
399 highest_seq = ntohl(h->seq);
400 if (db4) printf("Highest seq: %d\n", highest_seq);
401 }
402 }
403 p = p->next;
404 }
405
406 if (db1) printf("***< highest_seq_received: %d\n", highest_seq);
407 return(highest_seq);
408 }
409
410 /****************************************************************************
411 *#
412 *# FUNCTION NAME: PrintPacket
413 *#
414 *# PARAMETERS:
415 *#
416 *# DESCRIPTION:
417 *#
418 *#---------------------------------------------------------------------------
419 *# HISTORY
420 *#
421 *# DATE NAME CHANGES
422 *# ---- ---- -------
423 *# 961022 ronny Initial version
424 *#
425 *#***************************************************************************/
426
427 void
428 PrintPacket(const unsigned char *p, int size, int type)
429 {
430 int i;
431
432 /* printf("size %d\n", size);*/
433 for (i = 0; i != size; i++) {
434 if (i % p_packet_bpl == 0)
435 printf("\n%-4.4d: ", i);
436 if (type == UDEC)
437 printf("%-3d ", p[i]);
438 else if (type == HEX)
439 printf("%-2.2x ", p[i]);
440 else if (type == CHAR) {
441 if (isprint(p[i]))
442 printf("%-3c ", p[i]);
443 else
444 printf("%-3d ", p[i]);
445 }
446 else if (type == ASCII) {
447 if (isprint(p[i]))
448 printf("%c", p[i]);
449 else
450 printf(".");
451 }
452 }
453 printf("\n");
454 }
455
456 /****************************************************************************
457 *#
458 *# FUNCTION NAME: DecodeSvintoBoot
459 *#
460 *# PARAMETERS:
461 *#
462 *# DESCRIPTION: Decodes packets that follow the e100boot protocol.
463 *#
464 *#---------------------------------------------------------------------------
465 *# HISTORY
466 *#
467 *# DATE NAME CHANGES
468 *# ---- ---- -------
469 *# 961022 ronny Initial version
470 *#
471 *#***************************************************************************/
472
473 void
474 DecodeSvintoBoot(const unsigned char *p)
475 {
476 char *str;
477 volatile struct packet_header_T *ph = (struct packet_header_T*)p;
478
479 /* printf("size %d \n", sizeof(struct packet_header_T));*/
480
481 if (db4) printf("\n>DecodeSvintoBoot. Packet at 0x%x\n", (unsigned int)p);
482 if (db1) {
483 printf("%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x -> ", p[6],p[7],p[8],p[9],p[10], p[11]);
484 printf("%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n", p[0],p[1],p[2],p[3],p[4], p[5]);
485
486 printf("length : %4.4lx\n", (long)ntohs(ph->length));
487 printf("snap1 : %8.8lx\n", (long)ntohl(ph->snap1));
488 printf("snap2 : %8.8lx\n", (long)ntohl(ph->snap2));
489
490 switch (ntohl(ph->tag)) {
491 case 0xffffffff:
492 str = "(host > ETRAX)";
493 break;
494 case 0xfffffffe:
495 str = "(host < ETRAX)";
496 break;
497 default:
498 str = "(unknown)";
499 break;
500 }
501 printf("tag : %8.8lx %s\n", (unsigned long)ntohl(ph->tag), str);
502 printf("seq : %8.8lx\n", (unsigned long)ntohl(ph->seq));
503 }
504
505 switch (ntohl(ph->type)) {
506
507 case STRING:
508 str = "(STRING)";
509 fprintf(stderr, "%s", &p[sizeof(struct packet_header_T)]);
510 find_string((char*)&p[sizeof(struct packet_header_T)]);
511 break;
512
513 case NET_INT: {
514 char search_str[20];
515
516 str = "(NET_INT)";
517 sprintf(search_str, "0x%8.8lx", ntohl(*(udword*)&p[sizeof(struct packet_header_T)]));
518 fprintf(stderr, search_str);
519 find_string(search_str);
520 break;
521 }
522
523 case NET_INT_NL: {
524 char search_str[20];
525
526 str = "(NET_INT_NL)";
527 sprintf(search_str, "0x%8.8lx\n", ntohl(*(udword*)&p[sizeof(struct packet_header_T)]));
528 fprintf(stderr, search_str);
529 find_string(search_str);
530 break;
531 }
532
533 case ACK:
534 str = "(ACK)";
535 break;
536
537 case BOOT_PACKET:
538 str = "(bootpacket)";
539 break;
540
541 case BOOT_CMDS:
542 str = "(bootcmds)";
543 break;
544
545 default:
546 str = "(unknown)";
547 break;
548 }
549
550 if (db1) {
551 printf("(type : %8.8lx %s)\n", (unsigned long)ntohl(ph->type), str);
552 printf("(id : %8.8lx)\n", (unsigned long)ntohl(ph->id));
553 id = ntohl(ph->id);
554 }
555 }
556
557 /****************************************************************************
558 *#
559 *# FUNCTION NAME: SendToDevice
560 *#
561 *# PARAMETERS:
562 *#
563 *# DESCRIPTION:
564 *#
565 *#---------------------------------------------------------------------------
566 *# DATE NAME CHANGES
567 *# ---- ---- -------
568 *# 980818 ronny Initial version
569 *#
570 *#***************************************************************************/
571
572 void
573 SendToDevice(unsigned char *data, int data_len)
574 {
575 char fName[MAX_STRING_LEN];
576 FILE *fd;
577 struct packet_header_T *h = (struct packet_header_T*) data;
578
579 if (db1) printf("***> SendToDevice\n");
580
581 if (db2) printf("Sending %d bytes at 0x%x to %s.\n", data_len, (unsigned int)data, device);
582 if (db1) printf("#TX######################################################\n");
583 if (db1) DecodeSvintoBoot(data);
584
585 if (db1) printf("#########################################################\n");
586 if (toFiles || cmdsOnly) {
587 if (cmdsOnly) { /* use a simpler name */
588 sprintf(fName, "e100boot.cmds");
589 }
590 else {
591 sprintf(fName, "e100boot.seq%lu", (unsigned long)ntohl(h->seq));
592 }
593 if (db2) printf("Writing packet to file '%s'.\n", fName);
594 if ((fd = fopen(fName, "w+")) == NULL) {
595 printf("Cannot open/create '%s'. %s.\n", fName, strerror(errno));
596 exit(EXIT_FAILURE);
597 }
598 fwrite(data, data_len, 1, fd);
599 fclose(fd);
600 }
601 else if (pcap_sendpacket(pd, data, data_len) < 0) {
602 perror("pcap_sendpacket failed!\n");
603 exit(EXIT_FAILURE);
604 }
605
606 if (db1) printf("<*** SendToDevice\n");
607 }
608
609 /****************************************************************************
610 *#
611 *# FUNCTION NAME: timeout
612 *#
613 *# PARAMETERS:
614 *#
615 *# DESCRIPTION:
616 *#
617 *#---------------------------------------------------------------------------
618 *# HISTORY
619 *#
620 *# DATE NAME CHANGES
621 *# ---- ---- -------
622 *# 980817 ronny Initial version
623 *#
624 *#***************************************************************************/
625
626 int
627 timeout(struct timeval *tvThen, int ms)
628 {
629 struct timeval tvNow;
630 struct timeval tvDiff;
631
632 (void) gettimeofday(&tvNow, NULL);
633 tvDiff = timeval_subtract(&tvNow, tvThen);
634 if (db4) printf("sec %d.%d\n", (int)tvDiff.tv_sec, (int)tvDiff.tv_usec);
635 if (ms * 1000 < (tvDiff.tv_sec * 1000000 + tvDiff.tv_usec)) {
636 if (db4) printf("TIMEOUT\n");
637 return(TRUE);
638 }
639
640 return(FALSE);
641 }
642
643 /****************************************************************************
644 *#
645 *# FUNCTION NAME: timeval_subtract
646 *#
647 *# PARAMETERS:
648 *#
649 *# DESCRIPTION: Subtract x-y, and return result.
650 *#
651 *# DATE NAME CHANGES
652 *# ---- ---- -------
653 *# 970128 ronny Initial version
654 *#
655 *#***************************************************************************/
656
657 struct timeval
658 timeval_subtract(struct timeval *x, struct timeval *y)
659 {
660 struct timeval diff;
661
662 diff.tv_sec = x->tv_sec - y->tv_sec;
663 diff.tv_usec = x->tv_usec - y->tv_usec;
664
665 if (diff.tv_usec < 0) {
666 diff.tv_sec--;
667 diff.tv_usec = 1000000 + diff.tv_usec;
668 }
669
670 return diff;
671 }
672
673 int
674 gettimeofday(struct timeval *tv, void* tz_void)
675 {
676 struct _timeb tb;
677 _ftime(&tb);
678 tv->tv_sec = tb.time;
679 tv->tv_usec = tb.millitm * 1000;
680 return 0;
681 }