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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [common/] [v2_0/] [src/] [network_support.c] - Blame information for rev 578

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

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

powered by: WebSVN 2.1.0

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