1 /*!***************************************************************************
3 *! FILE NAME : network.c
5 *! DESCRIPTION: Network boot stuff for e100boot.
7 *! ---------------------------------------------------------------------------
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 *!***************************************************************************/
18 /************************** Include files ********************************/
21 #define WIN32_LEAN_AND_MEAN
26 #include <sys/timeb.h>
37 /************************** Constants and macros *************************/
41 /************************** Type definitions *****************************/
43 /************************** Global variables *****************************/
45 udword highest_ack_received
;
46 udword last_ack_received
= -1;
48 int got_new_packet
= FALSE
;
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 };
54 struct sockaddr sock_addr
;
60 struct packet_buf first_rec_packet
;
61 struct packet_buf
*last_rec_packet
= &first_rec_packet
;
63 int promisc
= 1; /* promiscuous mode */
66 int both_addresses
= FALSE
;
68 int printPacketType
= CHAR
;
71 int one_id_only
= TRUE
;
73 unsigned char buf
[16000]; /* pcap buffer */
75 const struct pcap_pkthdr
*hdrG
;
77 char host1
[MAX_STRING_LEN
]; /* name of ethernet host */
78 char host2
[MAX_STRING_LEN
]; /* name of ethernet host */
80 /************************** Function prototypes **************************/
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
);
91 /****************************************************************************
93 *# FUNCTION NAME: net_init
97 *#---------------------------------------------------------------------------
102 *# 2002 05 02 ronny Initial version
104 *#***************************************************************************/
110 char errbuf
[PCAP_ERRBUF_SIZE
];
112 char pOidDataBuf
[sizeof(PACKET_OID_DATA
)-1+sizeof(eth_addr_local
)];
113 PPACKET_OID_DATA pOidData
;
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
);
122 if (alldevs
== NULL
) {
123 printf("\nNo network adapters found!\n");
127 /* Use first device/interface */
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
);
136 if ((pd
= pcap_open_live(device
, 200, promisc
, -1, errbuf
)) == NULL
) {
137 printf("Error opening device %s\n", errbuf
);
141 /* Determine Ethernet address */
142 if ((pAdapter
= PacketOpenAdapter(device
)) == NULL
) {
143 printf("Error opening packet adapter!\n");
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");
155 PacketCloseAdapter(pAdapter
);
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",
167 handler
= (pcap_handler
) Handler
;
170 /****************************************************************************
172 *# FUNCTION NAME: NetBoot
174 *# DESCRIPTION: The main network boot routine.
176 *#---------------------------------------------------------------------------
181 *# 2000 01 07 ronny Initial version
182 *# 2002 05 02 ronny Fixed segv bug
184 *#***************************************************************************/
189 struct packet_buf
*p
;
192 gettimeofday(&tv
, NULL
);
194 p
= create_packet(0);
195 SendToDevice(p
->data
, p
->size
);
198 static int all_trans
= FALSE
;
200 if (got_new_packet
) {
201 got_new_packet
= FALSE
;
203 if (new_ack
&& first_packet
) {
205 printf("* got ACK %d.\n", last_ack_received
);
206 printf("* ACK wanted %d.\n", first_packet
->seq
);
208 if (last_ack_received
== first_packet
->seq
) {
209 if (!(p
= create_packet(first_packet
->seq
+1))) {
212 first_packet
= free_packet(first_packet
);
217 if (new_ack
|| timeout(&tv
, 500)) {
219 SendToDevice(p
->data
, p
->size
);
222 gettimeofday(&tv
, NULL
);
229 /****************************************************************************
231 *# FUNCTION NAME: GetNextPacket
235 *#---------------------------------------------------------------------------
240 *# 961022 ronny Initial version
242 *#***************************************************************************/
249 if (db2
) printf("> GetNextPacket\n");
251 /* got_new_packet = FALSE;*/
252 if ((ret
= pcap_dispatch(pd
, 1, handler
, buf
)) == -1) {
253 pcap_perror(pd
, "Error in pcap_dispatch");
257 if (db2
) printf("< GetNextPacket\n");
260 /****************************************************************************
262 *# FUNCTION NAME: Handler
268 *#---------------------------------------------------------------------------
273 *# 961022 ronny Initial version
275 *#***************************************************************************/
278 Handler(unsigned char *buf
, const struct pcap_pkthdr
*hdr
,
279 const unsigned char *p
)
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
;
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
);
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) {
300 printf("Booting device with random id %8.8x.\n", id
);
305 printf("Got ACK from a new id, %8.8lx. Ignoring.\n",
306 (unsigned long)ntohl(h
->id
));
310 last_ack_received
= ntohl(h
->seq
);
311 if (last_ack_received
> highest_ack_received
) {
312 highest_ack_received
= last_ack_received
;
316 if (db1
) printf("#########################################################\n");
319 if (db2
) printf("< Handler\n");
322 /****************************************************************************
324 *# FUNCTION NAME: ack_on_seq
330 *#---------------------------------------------------------------------------
335 *# 980817 ronny Initial version
337 *#***************************************************************************/
340 packet_with_seq(int seq
)
342 static int last_seq
= 0;
343 struct packet_buf
*p
= first_packet
;
344 struct packet_header_T
*h
;
346 if (seq
< last_seq
) {
351 h
= (struct packet_header_T
*)p
->data
;
352 if (ntohl(h
->seq
) == seq
) {
363 struct packet_buf
*p
= &first_rec_packet
;
364 struct packet_header_T
*h
;
366 if (db1
) printf("***> ack_on_seq: %d.\n", seq
);
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
);
380 if (db1
) printf("***< ack_on_seq, no.\n");
385 highest_seq_received(void)
387 struct packet_buf
*p
= &first_rec_packet
;
388 struct packet_header_T
*h
;
389 int highest_seq
= -1;
391 if (db1
) printf("***> highest_seq_received\n");
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
);
406 if (db1
) printf("***< highest_seq_received: %d\n", highest_seq
);
410 /****************************************************************************
412 *# FUNCTION NAME: PrintPacket
418 *#---------------------------------------------------------------------------
423 *# 961022 ronny Initial version
425 *#***************************************************************************/
428 PrintPacket(const unsigned char *p
, int size
, int type
)
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
);
437 printf("%-3d ", p
[i
]);
438 else if (type
== HEX
)
439 printf("%-2.2x ", p
[i
]);
440 else if (type
== CHAR
) {
442 printf("%-3c ", p
[i
]);
444 printf("%-3d ", p
[i
]);
446 else if (type
== ASCII
) {
456 /****************************************************************************
458 *# FUNCTION NAME: DecodeSvintoBoot
462 *# DESCRIPTION: Decodes packets that follow the e100boot protocol.
464 *#---------------------------------------------------------------------------
469 *# 961022 ronny Initial version
471 *#***************************************************************************/
474 DecodeSvintoBoot(const unsigned char *p
)
477 volatile struct packet_header_T
*ph
= (struct packet_header_T
*)p
;
479 /* printf("size %d \n", sizeof(struct packet_header_T));*/
481 if (db4
) printf("\n>DecodeSvintoBoot. Packet at 0x%x\n", (unsigned int)p
);
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]);
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
));
490 switch (ntohl(ph
->tag
)) {
492 str
= "(host > ETRAX)";
495 str
= "(host < ETRAX)";
501 printf("tag : %8.8lx %s\n", (unsigned long)ntohl(ph
->tag
), str
);
502 printf("seq : %8.8lx\n", (unsigned long)ntohl(ph
->seq
));
505 switch (ntohl(ph
->type
)) {
509 fprintf(stderr
, "%s", &p
[sizeof(struct packet_header_T
)]);
510 find_string((char*)&p
[sizeof(struct packet_header_T
)]);
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
);
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
);
538 str
= "(bootpacket)";
551 printf("(type : %8.8lx %s)\n", (unsigned long)ntohl(ph
->type
), str
);
552 printf("(id : %8.8lx)\n", (unsigned long)ntohl(ph
->id
));
557 /****************************************************************************
559 *# FUNCTION NAME: SendToDevice
565 *#---------------------------------------------------------------------------
568 *# 980818 ronny Initial version
570 *#***************************************************************************/
573 SendToDevice(unsigned char *data
, int data_len
)
575 char fName
[MAX_STRING_LEN
];
577 struct packet_header_T
*h
= (struct packet_header_T
*) data
;
579 if (db1
) printf("***> SendToDevice\n");
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
);
585 if (db1
) printf("#########################################################\n");
586 if (toFiles
|| cmdsOnly
) {
587 if (cmdsOnly
) { /* use a simpler name */
588 sprintf(fName
, "e100boot.cmds");
591 sprintf(fName
, "e100boot.seq%lu", (unsigned long)ntohl(h
->seq
));
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
));
598 fwrite(data
, data_len
, 1, fd
);
601 else if (pcap_sendpacket(pd
, data
, data_len
) < 0) {
602 perror("pcap_sendpacket failed!\n");
606 if (db1
) printf("<*** SendToDevice\n");
609 /****************************************************************************
611 *# FUNCTION NAME: timeout
617 *#---------------------------------------------------------------------------
622 *# 980817 ronny Initial version
624 *#***************************************************************************/
627 timeout(struct timeval
*tvThen
, int ms
)
629 struct timeval tvNow
;
630 struct timeval tvDiff
;
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");
643 /****************************************************************************
645 *# FUNCTION NAME: timeval_subtract
649 *# DESCRIPTION: Subtract x-y, and return result.
653 *# 970128 ronny Initial version
655 *#***************************************************************************/
658 timeval_subtract(struct timeval
*x
, struct timeval
*y
)
662 diff
.tv_sec
= x
->tv_sec
- y
->tv_sec
;
663 diff
.tv_usec
= x
->tv_usec
- y
->tv_usec
;
665 if (diff
.tv_usec
< 0) {
667 diff
.tv_usec
= 1000000 + diff
.tv_usec
;
674 gettimeofday(struct timeval
*tv
, void* tz_void
)
678 tv
->tv_sec
= tb
.time
;
679 tv
->tv_usec
= tb
.millitm
* 1000;