OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [orpmon/] [services/] [net.c] - Blame information for rev 828

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 809 simons
/*
2
 *      Copied from Linux Monitor (LiMon) - Networking.
3
 *
4
 *      Copyright 1994 - 2000 Neil Russell.
5
 *      (See License)
6
 *      Copyright 2000 Roland Borde
7
 *      Copyright 2000 Paolo Scaffardi
8
 *      Copyright 2000, 2001 Wolfgang Denk
9
 */
10
 
11
/*
12
 * General Desription:
13
 *
14
 * The user interface supports commands for BOOTP, RARP, and TFTP.
15
 * Also, we support ARP internally. Depending on available data,
16
 * these interact as follows:
17
 *
18
 * BOOTP:
19
 *
20
 *      Prerequisites:  - own ethernet address
21
 *      We want:        - own IP address
22
 *                      - TFTP server IP address
23
 *                      - name of bootfile
24
 *      Next step:      ARP
25
 *
26
 * RARP:
27
 *
28
 *      Prerequisites:  - own ethernet address
29
 *      We want:        - own IP address
30
 *                      - TFTP server IP address
31
 *      Next step:      ARP
32
 *
33
 * ARP:
34
 *
35
 *      Prerequisites:  - own ethernet address
36
 *                      - own IP address
37
 *                      - TFTP server IP address
38
 *      We want:        - TFTP server ethernet address
39
 *      Next step:      TFTP
40
 *
41
 * DHCP:
42
 *
43
 *     Prerequisites:   - own ethernet address
44
 *     We want:         - IP, Netmask, ServerIP, Gateway IP
45
 *                      - bootfilename, lease time
46
 *     Next step:       - TFTP
47
 *
48
 * TFTP:
49
 *
50
 *      Prerequisites:  - own ethernet address
51
 *                      - own IP address
52
 *                      - TFTP server IP address
53
 *                      - TFTP server ethernet address
54
 *                      - name of bootfile (if unknown, we use a default name
55
 *                        derived from our own IP address)
56
 *      We want:        - load the boot file
57
 *      Next step:      none
58
 */
59
 
60
 
61
#include "common.h"
62
#include "support.h"
63
#include "net.h"
64
#include "bootp.h"
65
#include "tftp.h"
66
#include "rarp.h"
67
#include "arp.h"
68
#include "eth.h"
69
 
70
#if 0
71
#define ET_DEBUG
72
#endif
73
 
74
/** BOOTP EXTENTIONS **/
75
 
76
IPaddr_t        NetOurSubnetMask=0;              /* Our subnet mask (0=unknown)  */
77
IPaddr_t        NetOurGatewayIP=0;               /* Our gateways IP address      */
78
IPaddr_t        NetOurDNSIP=0;                   /* Our DNS IP address           */
79
char            NetOurNISDomain[32]={0,};        /* Our NIS domain               */
80
char            NetOurHostName[32]={0,}; /* Our hostname                 */
81
char            NetOurRootPath[64]={0,}; /* Our bootpath                 */
82
unsigned short          NetBootFileSize=0;               /* Our bootfile size in blocks  */
83
 
84
/** END OF BOOTP EXTENTIONS **/
85
 
86
unsigned long           NetBootFileXferSize;    /* The actual transferred size of the bootfile (in bytes) */
87
unsigned char           NetOurEther[6];         /* Our ethernet address                 */
88
unsigned char           NetServerEther[6] =     /* Boot server enet address             */
89
                        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
90
IPaddr_t        NetOurIP;               /* Our IP addr (0 = unknown)            */
91
IPaddr_t        NetServerIP;            /* Our IP addr (0 = unknown)            */
92
volatile unsigned char *NetRxPkt;               /* Current receive packet               */
93
int             NetRxPktLen;            /* Current rx packet length             */
94
unsigned        NetIPID;                /* IP packet ID                         */
95
unsigned char           NetBcastAddr[6] =       /* Ethernet bcast address               */
96
                        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
97
int             NetState;               /* Network loop state                   */
98
 
99
char            BootFile[128];          /* Boot File name                       */
100
 
101
volatile unsigned char  PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
102
 
103
volatile unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets                     */
104
 
105
static rxhand_f *packetHandler;         /* Current RX packet handler            */
106
static thand_f *timeHandler;            /* Current timeout handler              */
107
static unsigned long    timeValue;              /* Current timeout value                */
108
volatile unsigned char *NetTxPacket = 0; /* THE transmit packet                  */
109
 
110
static int net_check_prereq (proto_t protocol);
111
 
112
/**********************************************************************/
113
/*
114
 *      Main network processing loop.
115
 */
116
int
117
NetLoop(proto_t protocol)
118
{
119
#if 1
120
        if (!NetTxPacket) {
121
                int     i;
122
 
123
                /*
124
                 *      Setup packet buffers, aligned correctly.
125
                 */
126 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
127 828 markom
printf("   NetTxPacket %.8lx\n", (unsigned long)NetTxPacket);
128 809 simons
                NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
129
                NetTxPacket -= (unsigned long)NetTxPacket % PKTALIGN;
130
                for (i = 0; i < PKTBUFSRX; i++) {
131
                        NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
132
                }
133
        }
134
 
135
        eth_halt();
136
        eth_init(NetReceive);
137
 
138
restart:
139
        NetCopyEther(NetOurEther, global.eth_add);
140
 
141
        NetState = NETLOOP_CONTINUE;
142
 
143
        /*
144
         *      Start the ball rolling with the given start function.  From
145
         *      here on, this code is a state machine driven by received
146
         *      packets and timer events.
147
         */
148
 
149
        if (protocol == TFTP) {                 /* TFTP */
150
                NetOurIP        = global.ip;
151 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
152
printf("   global.srv_ip = %.8lx\n", global.srv_ip);
153 809 simons
                NetServerIP     = global.srv_ip;
154
                NetOurGatewayIP = global.gw_ip;
155
                NetOurSubnetMask= global.mask;
156
 
157
                if (net_check_prereq (protocol) != 0) {
158
                        return 0;
159
                }
160
 
161
                /* always use ARP to get server ethernet address */
162
                ArpTry = 0;
163
                ArpRequest ();
164
 
165
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
166
        } else if (protocol == DHCP) {
167
                if (net_check_prereq (protocol) != 0) {
168
                        return 0;
169
                }
170
 
171
                /* Start with a clean slate... */
172
                NetOurIP = 0;
173
                NetServerIP = 0;
174
                DhcpRequest();          /* Basically same as BOOTP */
175
 
176
#endif  /* CFG_CMD_DHCP */
177
 
178
        } else {                                /* BOOTP or RARP */
179
 
180
                /*
181
                 * initialize our IP addr to 0 in order to accept ANY
182
                 * IP addr assigned to us by the BOOTP / RARP server
183
                 */
184
                NetOurIP = 0;
185
                NetServerIP = 0;
186
 
187
                if (net_check_prereq (protocol) != 0) {
188
                        return 0;
189
                }
190
#ifdef BOOTP
191
                if (protocol == BOOTP) {
192
                        BootpTry = 0;
193
                        BootpRequest ();
194
                }
195
#endif
196
#ifdef RARP
197
    if {
198
                        RarpTry  = 0;
199
                        RarpRequest ();
200
                }
201
#endif
202
        }
203
 
204
        NetBootFileXferSize = 0;
205
 
206
        /*
207
         *      Main packet reception loop.  Loop receiving packets until
208
         *      someone sets `NetQuit'.
209
         */
210
        for (;;) {
211
//              WATCHDOG_RESET();
212
                /*
213
                 *      Check the ethernet for a new packet.  The ethernet
214
                 *      receive routine will process it.
215
                 */
216 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
217 809 simons
                        eth_rx();
218
 
219
                /*
220
                 *      Abort if ctrl-c was pressed.
221
                 */
222 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
223 809 simons
                if (ctrlc()) {
224
                    eth_halt();
225
                        printf("\nAbort\n");
226
                        return 0;
227
                }
228
 
229
 
230
                /*
231
                 *      Check for a timeout, and run the timeout handler
232
                 *      if we have one.
233
                 */
234 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
235 809 simons
                if (timeHandler && (get_timer(0) > timeValue)) {
236
                        thand_f *x;
237
 
238 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
239 809 simons
                        x = timeHandler;
240
                        timeHandler = (thand_f *)0;
241
                        (*x)();
242
                }
243
 
244
 
245
                switch (NetState) {
246
 
247
                case NETLOOP_RESTART:
248 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
249 809 simons
                        goto restart;
250
 
251
                case NETLOOP_SUCCESS:
252 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
253 809 simons
                        if (NetBootFileXferSize > 0) {
254
                                printf("Bytes transferred = %ld (%lx hex)\n",
255
                                        NetBootFileXferSize,
256
                                        NetBootFileXferSize);
257
                        }
258
                        eth_halt();
259
                        return NetBootFileXferSize;
260
 
261
                case NETLOOP_FAIL:
262 816 markom
printf("%s - %s: %d\n", __FILE__, __FUNCTION__, __LINE__);
263 809 simons
                        return 0;
264
                }
265
        }
266
#endif
267
}
268
 
269
/**********************************************************************/
270
 
271
 
272
#if 1
273
void
274
NetStartAgain(void)
275
{
276
        NetState = NETLOOP_RESTART;
277
}
278
 
279
/**********************************************************************/
280
/*
281
 *      Miscelaneous bits.
282
 */
283
 
284
void
285
NetSetHandler(rxhand_f * f)
286
{
287
        packetHandler = f;
288
}
289
 
290
 
291
void
292
NetSetTimeout(int iv, thand_f * f)
293
{
294
        if (iv == 0) {
295
                timeHandler = (thand_f *)0;
296
        } else {
297
                timeHandler = f;
298
                timeValue = get_timer(0) + iv;
299
        }
300
}
301
 
302
 
303
void
304
NetSendPacket(volatile unsigned char * pkt, int len)
305
{
306
  unsigned char *p;
307
 
308
  p = eth_get_tx_buf();
309
  memcpy(p, (void *)pkt, len);
310
  eth_send(p, len);
311
}
312
 
313
 
314
 
315
void
316
NetReceive(volatile unsigned char * pkt, int len)
317
{
318
        Ethernet_t *et;
319
        IP_t    *ip;
320
        ARP_t   *arp;
321
        int     x;
322
 
323
 
324
        NetRxPkt = pkt;
325
        NetRxPktLen = len;
326
        et = (Ethernet_t *)pkt;
327
 
328
        x = SWAP16(et->et_protlen);
329
 
330
        if (x < 1514) {
331
                /*
332
                 *      Got a 802 packet.  Check the other protocol field.
333
                 */
334
                x = SWAP16(et->et_prot);
335
                ip = (IP_t *)(pkt + E802_HDR_SIZE);
336
                len -= E802_HDR_SIZE;
337
        } else {
338
                ip = (IP_t *)(pkt + ETHER_HDR_SIZE);
339
                len -= ETHER_HDR_SIZE;
340
        }
341
 
342
#ifdef ET_DEBUG
343
        printf("Receive from protocol 0x%x\n", x);
344
#endif
345
 
346
        switch (x) {
347
 
348
        case PROT_ARP:
349
                /*
350
                 * We have to deal with two types of ARP packets:
351
                 * - REQUEST packets will be answered by sending  our
352
                 *   IP address - if we know it.
353
                 * - REPLY packates are expected only after we asked
354
                 *   for the TFTP server's or the gateway's ethernet
355
                 *   address; so if we receive such a packet, we set
356
                 *   the server ethernet address
357
                 */
358
#ifdef ET_DEBUG
359
                printf("Got ARP\n");
360
#endif
361
                arp = (ARP_t *)ip;
362
                if (len < ARP_HDR_SIZE) {
363
                        printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
364
                        return;
365
                }
366
                if (SWAP16(arp->ar_hrd) != ARP_ETHER) {
367
                        return;
368
                }
369
                if (SWAP16(arp->ar_pro) != PROT_IP) {
370
                        return;
371
                }
372
                if (arp->ar_hln != 6) {
373
                        return;
374
                }
375
                if (arp->ar_pln != 4) {
376
                        return;
377
                }
378
 
379
                if (NetOurIP == 0 ||
380
                    *((IPaddr_t *)&arp->ar_data[16]) != NetOurIP) {
381
                        return;
382
                }
383
 
384
                switch (SWAP16(arp->ar_op)) {
385
                case ARPOP_REQUEST:             /* reply with our IP address    */
386
#ifdef ET_DEBUG
387
                        printf("Got ARP REQUEST, return our IP\n");
388
#endif
389
                        NetSetEther((unsigned char *)et, et->et_src, PROT_ARP);
390
                        arp->ar_op = SWAP16(ARPOP_REPLY);
391
                        NetCopyEther(&arp->ar_data[10], &arp->ar_data[0]);
392
                        NetCopyEther(&arp->ar_data[0], NetOurEther);
393
                        *(IPaddr_t *)(&arp->ar_data[16]) =
394
                                                *(IPaddr_t *)(&arp->ar_data[6]);
395
                        *(IPaddr_t *)(&arp->ar_data[6]) = NetOurIP;
396
                        NetSendPacket((unsigned char *)et,((unsigned char *)arp-pkt)+ARP_HDR_SIZE);
397
                        return;
398
                case ARPOP_REPLY:               /* set TFTP server eth addr     */
399
#ifdef ET_DEBUG
400
                        printf("Got ARP REPLY, set server/gtwy eth addr\n");
401
#endif
402
                        NetCopyEther(NetServerEther, &arp->ar_data[0]);
403
                        (*packetHandler)(0,0,0,0);  /* start TFTP */
404
                        return;
405
                default:
406
#ifdef ET_DEBUG
407
                        printf("Unexpected ARP opcode 0x%x\n", SWAP16(arp->ar_op));
408
#endif
409
                        return;
410
                }
411
 
412
        case PROT_RARP:
413
#ifdef ET_DEBUG
414
                printf("Got RARP\n");
415
#endif
416
                arp = (ARP_t *)ip;
417
                if (len < ARP_HDR_SIZE) {
418
                        printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
419
                        return;
420
                }
421
 
422
                if ((SWAP16(arp->ar_op) != RARPOP_REPLY) ||
423
                        (SWAP16(arp->ar_hrd) != ARP_ETHER)   ||
424
                        (SWAP16(arp->ar_pro) != PROT_IP)     ||
425
                        (arp->ar_hln != 6) || (arp->ar_pln != 4)) {
426
 
427
                        printf("invalid RARP header\n");
428
                } else {
429
                        NetOurIP = *((IPaddr_t *)&arp->ar_data[16]);
430
                        NetServerIP = *((IPaddr_t *)&arp->ar_data[6]);
431
                        NetCopyEther(NetServerEther, &arp->ar_data[0]);
432
 
433
                        (*packetHandler)(0,0,0,0);
434
                }
435
                break;
436
 
437
        case PROT_IP:
438
#ifdef ET_DEBUG
439
                printf("Got IP\n");
440
#endif
441
                if (len < IP_HDR_SIZE) {
442
                        debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
443
                        return;
444
                }
445
                if (len < SWAP16(ip->ip_len)) {
446
                        printf("len bad %d < %d\n", len, SWAP16(ip->ip_len));
447
                        return;
448
                }
449
                len = SWAP16(ip->ip_len);
450
#ifdef ET_DEBUG
451
                printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
452
#endif
453
                if ((ip->ip_hl_v & 0xf0) != 0x40) {
454
                        return;
455
                }
456
                if (ip->ip_off & SWAP16c(0x1fff)) { /* Can't deal w/ fragments */
457
                        return;
458
                }
459
                if (!NetCksumOk((unsigned char *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
460
                        printf("checksum bad\n");
461
                        return;
462
                }
463
                if (NetOurIP &&
464
                    ip->ip_dst != NetOurIP &&
465
                    ip->ip_dst != 0xFFFFFFFF) {
466
                        return;
467
                }
468
                /*
469
                 * watch for ICMP host redirects
470
                 *
471
                 * There is no real handler code (yet). We just watch
472
                 * for ICMP host redirect messages. In case anybody
473
                 * sees these messages: please contact me
474
                 * (wd@denx.de), or - even better - send me the
475
                 * necessary fixes :-)
476
                 *
477
                 * Note: in all cases where I have seen this so far
478
                 * it was a problem with the router configuration,
479
                 * for instance when a router was configured in the
480
                 * BOOTP reply, but the TFTP server was on the same
481
                 * subnet. So this is probably a warning that your
482
                 * configuration might be wrong. But I'm not really
483
                 * sure if there aren't any other situations.
484
                 */
485
                if (ip->ip_p == IPPROTO_ICMP) {
486
                        ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
487
 
488
                        if (icmph->type != ICMP_REDIRECT)
489
                                return;
490
                        if (icmph->code != ICMP_REDIR_HOST)
491
                                return;
492
                        printf (" ICMP Host Redirect to ");
493
                        print_IPaddr(icmph->un.gateway);
494
                        putc(' ');
495
                } else if (ip->ip_p != IPPROTO_UDP) {   /* Only UDP packets */
496
                        return;
497
                }
498
 
499
                /*
500
                 *      IP header OK.  Pass the packet to the current handler.
501
                 */
502
                (*packetHandler)((unsigned char *)ip +IP_HDR_SIZE,
503
                                                SWAP16(ip->udp_dst),
504
                                                SWAP16(ip->udp_src),
505
                                                SWAP16(ip->udp_len) - 8);
506
 
507
                break;
508
        }
509
}
510
 
511
 
512
/**********************************************************************/
513
 
514
static int net_check_prereq (proto_t protocol)
515
{
516
        switch (protocol) {
517
        case ARP:       /* nothing to do */
518
                        break;
519
 
520
        case TFTP:
521
                        if (NetServerIP == 0) {
522
                          printf         ("*** ERROR: `serverip' not set\n");
523
                                return (1);
524
                        }
525
 
526
                        if (NetOurIP == 0) {
527
                                printf ("*** ERROR: `ipaddr' not set\n");
528
                                return (1);
529
                        }
530
                        /* Fall through */
531
 
532
        case DHCP:
533
        case RARP:
534
        case BOOTP:
535
                        if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
536
                                printf ("*** ERROR: `ethaddr' not set\n");
537
                                return (1);
538
                        }
539
                        /* Fall through */
540
        }
541
        return (0);      /* OK */
542
}
543
/**********************************************************************/
544
 
545
int
546
NetCksumOk(unsigned char * ptr, int len)
547
{
548
        return !((NetCksum(ptr, len) + 1) & 0xfffe);
549
}
550
 
551
 
552
unsigned
553
NetCksum(unsigned char * ptr, int len)
554
{
555
        unsigned long   xsum;
556
 
557
        xsum = 0;
558
        while (len-- > 0)
559
                xsum += *((unsigned short *)ptr)++;
560
        xsum = (xsum & 0xffff) + (xsum >> 16);
561
        xsum = (xsum & 0xffff) + (xsum >> 16);
562
        return (xsum & 0xffff);
563
}
564
 
565
 
566
void
567
NetCopyEther(volatile unsigned char * to, unsigned char * from)
568
{
569
        int     i;
570
 
571
        for (i = 0; i < 6; i++)
572
                *to++ = *from++;
573
}
574
 
575
 
576
void
577
NetSetEther(volatile unsigned char * xet, unsigned char * addr, unsigned long prot)
578
{
579
        volatile Ethernet_t *et = (Ethernet_t *)xet;
580
 
581
        NetCopyEther(et->et_dest, addr);
582
        NetCopyEther(et->et_src, NetOurEther);
583
        et->et_protlen = SWAP16(prot);
584
}
585
 
586
 
587
void
588
NetSetIP(volatile unsigned char * xip, IPaddr_t dest, int dport, int sport, int len)
589
{
590
        volatile IP_t *ip = (IP_t *)xip;
591
 
592
        /*
593
         *      If the data is an odd number of bytes, zero the
594
         *      byte after the last byte so that the checksum
595
         *      will work.
596
         */
597
        if (len & 1)
598
                xip[IP_HDR_SIZE + len] = 0;
599
 
600
        /*
601
         *      Construct an IP and UDP header.
602
                        (need to set no fragment bit - XXX)
603
         */
604
        ip->ip_hl_v  = 0x45;            /* IP_HDR_SIZE / 4 (not including UDP) */
605
        ip->ip_tos   = 0;
606
        ip->ip_len   = SWAP16(IP_HDR_SIZE + len);
607
        ip->ip_id    = SWAP16(NetIPID++);
608
        ip->ip_off   = SWAP16c(0x4000); /* No fragmentation */
609
        ip->ip_ttl   = 255;
610
        ip->ip_p     = 17;              /* UDP */
611
        ip->ip_sum   = 0;
612
        ip->ip_src   = NetOurIP;
613
        ip->ip_dst   = dest;
614
        ip->udp_src  = SWAP16(sport);
615
        ip->udp_dst  = SWAP16(dport);
616
        ip->udp_len  = SWAP16(8 + len);
617
        ip->udp_xsum = 0;
618
        ip->ip_sum   = ~NetCksum((unsigned char *)ip, IP_HDR_SIZE_NO_UDP / 2);
619
}
620
 
621
void copy_filename (unsigned char *dst, unsigned char *src, int size)
622
{
623
        if (*src && (*src == '"')) {
624
                ++src;
625
                --size;
626
        }
627
 
628
        while ((--size > 0) && *src && (*src != '"')) {
629
                *dst++ = *src++;
630
        }
631
        *dst = '\0';
632
}
633
 
634
void ip_to_string (IPaddr_t x, char *s)
635
{
636
    char num[] = "0123456789ABCDEF";
637
    int i;
638
 
639
    x = SWAP32(x);
640
 
641
    for(i = 28; i >= 0; i -= 4)
642
      *s++ = num[((x >> i) & 0x0f)];
643
    *s = 0;
644
}
645
 
646
void print_IPaddr (IPaddr_t x)
647
{
648
    char tmp[12];
649
 
650
    ip_to_string(x, tmp);
651
 
652
    printf(tmp);
653
}
654
 
655
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.