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

Subversion Repositories or1k

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

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

powered by: WebSVN 2.1.0

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