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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [orpmon/] [services/] [net.c] - Blame information for rev 1773

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

powered by: WebSVN 2.1.0

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