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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [common/] [current/] [src/] [network_support.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      network_support.c
4
//
5
//      Misc network support functions
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    gthomas
43
// Contributors: gthomas, sorin@netappi.com ("Sorin Babeanu"), hmt, jlarmour,
44
//               andrew.lunn@ascom.ch
45
// Date:         2000-01-10
46
// Purpose:      
47
// Description:  
48
//              
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
// BOOTP support
55
 
56
#include <pkgconf/net.h>
57
#undef _KERNEL
58
#include <sys/param.h>
59
#include <sys/socket.h>
60
#include <sys/ioctl.h>
61
#include <sys/errno.h>
62
 
63
#include <net/if.h>
64
#include <netinet/in.h>
65
#include <netinet/ip.h>
66
#include <netinet/ip_icmp.h>
67
#include <net/route.h>
68
 
69
#include <cyg/infra/diag.h>
70
#include <cyg/kernel/kapi.h>
71
 
72
#include <stdio.h>    // for 'sprintf()'
73
 
74
#include <bootp.h>
75
#include <network.h>
76
#include <arpa/inet.h>
77
 
78
#ifdef CYGPKG_IO_PCMCIA
79
#include <cyg/io/eth/netdev.h>
80
#endif
81
 
82
#ifdef CYGPKG_NET_DHCP
83
#include <dhcp.h>
84
#endif
85
 
86
#ifdef CYGPKG_NS_DNS
87
#include <pkgconf/ns_dns.h>
88
#endif
89
 
90
#ifdef CYGHWR_NET_DRIVER_ETH0
91
struct bootp eth0_bootp_data;
92
cyg_bool_t   eth0_up = false;
93
const char  *eth0_name = "eth0";
94
#endif
95
#ifdef CYGHWR_NET_DRIVER_ETH1
96
struct bootp eth1_bootp_data;
97
cyg_bool_t   eth1_up = false;
98
const char  *eth1_name = "eth1";
99
#endif
100
 
101
#define _string(s) #s
102
#define string(s) _string(s)
103
 
104
#ifndef CYGPKG_LIBC_STDIO
105
#define perror(s) diag_printf(#s ": %s\n", strerror(errno))
106
#endif
107
 
108
#ifdef CYGPKG_NET_NLOOP
109
#if 0 < CYGPKG_NET_NLOOP
110
//  
111
//   Initialize loopback interface  ----------   Added by sorin@netappi.com 
112
//
113
cyg_bool_t init_loopback_interface(int lo)
114
{
115
    struct sockaddr_in *addrp;
116
    struct ifreq ifr;
117
    int s;
118
    int one = 1;
119
    struct ecos_rtentry route;
120
    struct in_addr netmask, gateway;
121
 
122
    s = socket(AF_INET, SOCK_DGRAM, 0);
123
    if (s < 0) {
124
        perror("socket");
125
        return false;
126
    }
127
    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) {
128
        perror("setsockopt");
129
        close(s);
130
        return false;
131
    }
132
 
133
    addrp = (struct sockaddr_in *) &ifr.ifr_addr;
134
    memset(addrp, 0, sizeof(*addrp));
135
    addrp->sin_family = AF_INET;
136
    addrp->sin_len = sizeof(*addrp);
137
    addrp->sin_port = 0;
138
    // Make an address 127.0.<lo>.1 to manage multiple loopback ifs.
139
    // (There is normally only 1, so it's the standard 127.0.0.1)
140
    addrp->sin_addr.s_addr = htonl((0x100 * lo) + INADDR_LOOPBACK) ;
141
 
142
#if CYGPKG_NET_NLOOP > 1
143
    // Init the one we were told to
144
    sprintf(ifr.ifr_name, "lo%d", lo);
145
#else
146
    strcpy(ifr.ifr_name, "lo0");
147
#endif    
148
 
149
    if (ioctl(s, SIOCSIFADDR, &ifr)) {
150
        perror("SIOCIFADDR");
151
        close(s);
152
        return false;
153
    }
154
 
155
#if 1 < CYGPKG_NET_NLOOP
156
    // We cheat to make different nets for multiple loopback devs
157
    addrp->sin_addr.s_addr = netmask.s_addr = htonl(IN_CLASSC_NET);
158
#else
159
    // 
160
    addrp->sin_addr.s_addr = netmask.s_addr = htonl(IN_CLASSA_NET);
161
#endif
162
    if (ioctl(s, SIOCSIFNETMASK, &ifr)) {
163
        perror("SIOCSIFNETMASK");
164
        return false;
165
    }
166
    ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
167
    if (ioctl(s, SIOCSIFFLAGS, &ifr)) {
168
        perror("SIOCSIFFLAGS");
169
        close(s);
170
        return false;
171
    }
172
 
173
    gateway.s_addr = htonl(INADDR_LOOPBACK);
174
    memset(&route, 0, sizeof(route));
175
    addrp->sin_family = AF_INET;
176
    addrp->sin_len = sizeof(*addrp);
177
    addrp->sin_port = 0;
178
    addrp->sin_addr.s_addr = htonl((0x100 * lo) + INADDR_LOOPBACK) & netmask.s_addr;
179
    memcpy(&route.rt_dst, addrp, sizeof(*addrp));
180
    addrp->sin_addr = netmask;
181
    memcpy(&route.rt_genmask, addrp, sizeof(*addrp));
182
    addrp->sin_addr = gateway;
183
    memcpy(&route.rt_gateway, addrp, sizeof(*addrp));
184
 
185
    route.rt_dev = ifr.ifr_name;
186
    route.rt_flags = RTF_UP|RTF_GATEWAY;
187
    route.rt_metric = 0;
188
 
189
    if (ioctl(s, SIOCADDRT, &route)) {
190
        diag_printf("Route - dst: %s", inet_ntoa(((struct sockaddr_in *)&route.rt_dst)->sin_addr));
191
        diag_printf(", mask: %s", inet_ntoa(((struct sockaddr_in *)&route.rt_genmask)->sin_addr));
192
        diag_printf(", gateway: %s\n", inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
193
        if (errno != EEXIST) {
194
            perror("SIOCADDRT 3");
195
            close(s);
196
            return false;
197
        }
198
    }
199
    close(s);
200
    return true;
201
}
202
#endif
203
#endif
204
 
205
 
206
//
207
// Internal function which builds up a fake BOOTP database for
208
// an interface.
209
//
210
 
211
static unsigned char *
212
add_tag(unsigned char *vp,
213
        unsigned char tag,
214
        void *val,
215
        int len)
216
{
217
    int i;
218
    unsigned char *xp = (unsigned char *)val;
219
    *vp++ = tag;
220
    *vp++ = len;
221
    for (i = 0;  i < len;  i++) {
222
        *vp++ = *xp++;
223
    }
224
    return vp;
225
}
226
 
227
void
228
build_bootp_record(struct bootp *bp,
229
                   const char *if_name,
230
                   const char *addrs_ip,
231
                   const char *addrs_netmask,
232
                   const char *addrs_broadcast,
233
                   const char *addrs_gateway,
234
                   const char *addrs_server)
235
{
236
    int i, s;
237
    in_addr_t addr;
238
    unsigned char *vp;
239
    unsigned char cookie[] = VM_RFC1048;
240
    struct ifreq ifr;
241
 
242
    bzero(bp, sizeof(struct bootp));
243
    bp->bp_op = BOOTREPLY;
244
    bp->bp_htype = HTYPE_ETHERNET;
245
    bp->bp_hlen = 6;
246
 
247
    // Query the hardware address
248
    for (i = 0;  i < bp->bp_hlen;  i++) {
249
        bp->bp_chaddr[i] = 0xFF;  // Unknown
250
    }
251
    s = socket(AF_INET, SOCK_DGRAM, 0);
252
    if (s >= 0) {
253
        strcpy(ifr.ifr_name, if_name);
254
        if (ioctl(s, SIOCGIFHWADDR, &ifr) >= 0) {
255
            bcopy(ifr.ifr_hwaddr.sa_data, bp->bp_chaddr, bp->bp_hlen);
256
        }
257
        close(s);
258
    }
259
 
260
    // Fill in the provided IP addresses
261
    bp->bp_ciaddr.s_addr = inet_addr(addrs_ip);
262
    bp->bp_yiaddr.s_addr = inet_addr(addrs_ip);
263
    bp->bp_siaddr.s_addr = inet_addr(addrs_server);
264
    bp->bp_giaddr.s_addr = inet_addr(addrs_gateway);
265
    vp = &bp->bp_vend[0];
266
    bcopy(&cookie, vp, sizeof(cookie));
267
    vp += sizeof(cookie);
268
    addr = inet_addr(addrs_netmask);
269
    vp = add_tag(vp, TAG_SUBNET_MASK, &addr, sizeof(in_addr_t));
270
    addr = inet_addr(addrs_broadcast);
271
    vp = add_tag(vp, TAG_IP_BROADCAST, &addr, sizeof(in_addr_t));
272
    addr = inet_addr(addrs_gateway);
273
    vp = add_tag(vp, TAG_GATEWAY, &addr, sizeof(in_addr_t));
274
    *vp = TAG_END;
275
}
276
 
277
 
278
//
279
// Initialize network interface[s] using BOOTP/DHCP
280
//
281
void
282
init_all_network_interfaces(void)
283
{
284
    static volatile int in_init_all_network_interfaces = 0;
285
#ifdef CYGPKG_IO_PCMCIA
286
    cyg_netdevtab_entry_t *t;
287
#endif // CYGPKG_IO_PCMCIA
288
#ifdef CYGOPT_NET_IPV6_ROUTING_THREAD
289
    int rs_wait = 40;
290
#endif
291
 
292
    cyg_scheduler_lock();
293
    while ( in_init_all_network_interfaces ) {
294
        // Another thread is doing this...
295
        cyg_scheduler_unlock();
296
        cyg_thread_delay( 10 );
297
        cyg_scheduler_lock();
298
    }
299
    in_init_all_network_interfaces = 1;
300
    cyg_scheduler_unlock();
301
 
302
#ifdef CYGHWR_NET_DRIVER_ETH0
303
    if ( ! eth0_up ) { // Make this call idempotent
304
#ifdef CYGPKG_IO_PCMCIA
305
        if ((t = eth_drv_netdev("eth0")) != (cyg_netdevtab_entry_t *)NULL) {
306
            int tries = 0;
307
            while (t->status != CYG_NETDEVTAB_STATUS_AVAIL) {
308
                if (tries == 0) {
309
                    diag_printf("... Waiting for PCMCIA device 'eth0'\n");
310
                }
311
                if (++tries == 5) {
312
                    diag_printf("... Giving up on PCMCIA device 'eth0'\n");
313
                    goto bail_eth0;
314
                }
315
                cyg_thread_delay(100);
316
            }
317
        }
318
#endif // CYGPKG_IO_PCMCIA
319
#ifdef CYGHWR_NET_DRIVER_ETH0_BOOTP
320
        // Perform a complete initialization, using BOOTP/DHCP
321
        eth0_up = true;
322
#ifdef CYGHWR_NET_DRIVER_ETH0_DHCP
323
        eth0_dhcpstate = 0; // Says that initialization is external to dhcp
324
        if (do_dhcp(eth0_name, &eth0_bootp_data, &eth0_dhcpstate, &eth0_lease))
325
#else
326
#ifdef CYGPKG_NET_DHCP
327
        eth0_dhcpstate = DHCPSTATE_BOOTP_FALLBACK;
328
        // so the dhcp machine does no harm if called
329
#endif
330
        if (do_bootp(eth0_name, &eth0_bootp_data))
331
#endif
332
        {
333
#ifdef CYGHWR_NET_DRIVER_ETH0_BOOTP_SHOW
334
            show_bootp(eth0_name, &eth0_bootp_data);
335
#endif
336
        } else {
337
            diag_printf("BOOTP/DHCP failed on eth0\n");
338
            eth0_up = false;
339
        }
340
#elif defined(CYGHWR_NET_DRIVER_ETH0_ADDRS_IP)
341
        eth0_up = true;
342
        build_bootp_record(&eth0_bootp_data,
343
                           eth0_name,
344
                           string(CYGHWR_NET_DRIVER_ETH0_ADDRS_IP),
345
                           string(CYGHWR_NET_DRIVER_ETH0_ADDRS_NETMASK),
346
                           string(CYGHWR_NET_DRIVER_ETH0_ADDRS_BROADCAST),
347
                           string(CYGHWR_NET_DRIVER_ETH0_ADDRS_GATEWAY),
348
                           string(CYGHWR_NET_DRIVER_ETH0_ADDRS_SERVER));
349
        show_bootp(eth0_name, &eth0_bootp_data);
350
#endif
351
#ifdef CYGPKG_IO_PCMCIA
352
    bail_eth0:
353
#endif
354
    }
355
#endif // CYGHWR_NET_DRIVER_ETH0
356
#ifdef CYGHWR_NET_DRIVER_ETH1
357
    if ( ! eth1_up ) { // Make this call idempotent
358
#ifdef CYGPKG_IO_PCMCIA
359
        if ((t = eth_drv_netdev("eth1")) != (cyg_netdevtab_entry_t *)NULL) {
360
            int tries = 0;
361
            while (t->status != CYG_NETDEVTAB_STATUS_AVAIL) {
362
                if (tries == 0) {
363
                    diag_printf("... Waiting for PCMCIA device 'eth1'\n");
364
                }
365
                if (++tries == 5) {
366
                    diag_printf("... Giving up on PCMCIA device 'eth1'\n");
367
                    goto bail_eth1;
368
                }
369
                cyg_thread_delay(100);
370
            }
371
        }
372
#endif // CYGPKG_IO_PCMCIA
373
#ifdef CYGHWR_NET_DRIVER_ETH1_BOOTP
374
        // Perform a complete initialization, using BOOTP/DHCP
375
        eth1_up = true;
376
#ifdef CYGHWR_NET_DRIVER_ETH1_DHCP
377
        eth1_dhcpstate = 0; // Says that initialization is external to dhcp
378
        if (do_dhcp(eth1_name, &eth1_bootp_data, &eth1_dhcpstate, &eth1_lease))
379
#else
380
#ifdef CYGPKG_NET_DHCP
381
        eth1_dhcpstate = DHCPSTATE_BOOTP_FALLBACK;
382
        // so the dhcp machine does no harm if called
383
#endif
384
        if (do_bootp(eth1_name, &eth1_bootp_data))
385
#endif
386
        {
387
#ifdef CYGHWR_NET_DRIVER_ETH1_BOOTP_SHOW
388
            show_bootp(eth1_name, &eth1_bootp_data);
389
#endif
390
        } else {
391
            diag_printf("BOOTP/DHCP failed on eth1\n");
392
            eth1_up = false;
393
        }
394
#elif defined(CYGHWR_NET_DRIVER_ETH1_ADDRS_IP)
395
        eth1_up = true;
396
        build_bootp_record(&eth1_bootp_data,
397
                           eth1_name,
398
                           string(CYGHWR_NET_DRIVER_ETH1_ADDRS_IP),
399
                           string(CYGHWR_NET_DRIVER_ETH1_ADDRS_NETMASK),
400
                           string(CYGHWR_NET_DRIVER_ETH1_ADDRS_BROADCAST),
401
                           string(CYGHWR_NET_DRIVER_ETH1_ADDRS_GATEWAY),
402
                           string(CYGHWR_NET_DRIVER_ETH1_ADDRS_SERVER));
403
        show_bootp(eth1_name, &eth1_bootp_data);
404
#endif
405
#ifdef CYGPKG_IO_PCMCIA
406
    bail_eth1:
407
#endif
408
    }
409
#endif // CYGHWR_NET_DRIVER_ETH1
410
#ifdef CYGHWR_NET_DRIVER_ETH0
411
#ifndef CYGHWR_NET_DRIVER_ETH0_MANUAL
412
    if (eth0_up) {
413
        if (!init_net(eth0_name, &eth0_bootp_data)) {
414
            diag_printf("Network initialization failed for eth0\n");
415
            eth0_up = false;
416
        }
417
#ifdef CYGHWR_NET_DRIVER_ETH0_IPV6_PREFIX
418
        if (!init_net_IPv6(eth0_name, &eth0_bootp_data,
419
                           string(CYGHWR_NET_DRIVER_ETH0_IPV6_PREFIX))) {
420
            diag_printf("Static IPv6 network initialization failed for eth0\n");
421
            eth0_up = false;  // ???
422
        }
423
#endif
424
    }
425
#endif
426
#endif
427
#ifdef CYGHWR_NET_DRIVER_ETH1
428
#ifndef CYGHWR_NET_DRIVER_ETH1_MANUAL
429
    if (eth1_up) {
430
        if (!init_net(eth1_name, &eth1_bootp_data)) {
431
            diag_printf("Network initialization failed for eth1\n");
432
            eth1_up = false;
433
        }
434
#ifdef CYGHWR_NET_DRIVER_ETH1_IPV6_PREFIX
435
        if (!init_net_IPv6(eth1_name, &eth1_bootp_data,
436
                           string(CYGHWR_NET_DRIVER_ETH1_IPV6_PREFIX))) {
437
            diag_printf("Static IPv6 network initialization failed for eth1\n");
438
            eth1_up = false; // ???
439
        }
440
#endif
441
    }
442
#endif
443
#endif
444
 
445
#ifdef CYGPKG_NET_NLOOP
446
#if 0 < CYGPKG_NET_NLOOP
447
    {
448
        static int loop_init = 0;
449
        int i;
450
        if ( 0 == loop_init++ )
451
            for ( i = 0; i < CYGPKG_NET_NLOOP; i++ )
452
                init_loopback_interface( i );
453
    }
454
#endif
455
#endif
456
 
457
#ifdef CYGOPT_NET_DHCP_DHCP_THREAD
458
    dhcp_start_dhcp_mgt_thread();
459
#endif
460
 
461
#ifdef CYGOPT_NET_IPV6_ROUTING_THREAD
462
    ipv6_start_routing_thread();
463
 
464
    // Wait for router solicit process to happen.
465
    while (rs_wait-- && !cyg_net_get_ipv6_advrouter(NULL)) {
466
      cyg_thread_delay(10);
467
    }
468
    if (rs_wait == 0 ) {
469
      diag_printf("No router solicit received\n");
470
    } else {
471
      // Give Duplicate Address Detection time to work
472
      cyg_thread_delay(200);
473
    }
474
#endif
475
 
476
#ifdef CYGDAT_NS_DNS_DEFAULT_SERVER
477
      cyg_dns_res_start(string(CYGDAT_NS_DNS_DEFAULT_SERVER));
478
#endif
479
 
480
#ifdef CYGDAT_NS_DNS_DOMAINNAME_NAME
481
#define _NAME string(CYGDAT_NS_DNS_DOMAINNAME_NAME)
482
    {
483
      const char buf[] = _NAME;
484
      int len = strlen(_NAME);
485
 
486
      setdomainname(buf,len);
487
    }
488
#endif
489
    // Open the monitor to other threads.
490
    in_init_all_network_interfaces = 0;
491
 
492
}
493
 
494
// EOF network_support.c

powered by: WebSVN 2.1.0

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