1 //==========================================================================
5 //==========================================================================
6 //####BSDCOPYRIGHTBEGIN####
8 // -------------------------------------------
10 // Portions of this software may have been derived from OpenBSD,
11 // FreeBSD or other sources, and are covered by the appropriate
12 // copyright disclaimers included herein.
14 // Portions created by Red Hat are
15 // Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
17 // Copyright (C) 2002, 2003 Gary Thomas
18 // Copyright (C) 2003 Andrew Lunn
19 // -------------------------------------------
21 //####BSDCOPYRIGHTEND####
22 //==========================================================================
24 //==========================================================================
28 // eCos wrapper and support functions
30 //==========================================================================
31 //####BSDCOPYRIGHTBEGIN####
33 // -------------------------------------------
35 // Portions of this software may have been derived from OpenBSD or other sources,
36 // and are covered by the appropriate copyright disclaimers included herein.
38 // -------------------------------------------
40 //####BSDCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
44 // Author(s): gthomas, hmt
45 // Contributors: gthomas, hmt, andrew.lunn@ascom.ch
51 //####DESCRIPTIONEND####
53 //==========================================================================
56 // Support routines, etc., used by network code
58 #include <sys/param.h>
59 #include <sys/malloc.h>
61 #include <sys/domain.h>
62 #include <sys/protosw.h>
63 #include <sys/sockio.h>
64 #include <sys/socket.h>
65 #include <sys/socketvar.h>
67 #include <net/netisr.h>
69 #include <cyg/infra/diag.h>
70 #include <cyg/hal/hal_intr.h>
71 #include <cyg/kernel/kapi.h>
72 #include <cyg/hal/hal_if.h>
73 #include <cyg/infra/cyg_ass.h>
75 #ifdef CYGPKG_NET_INET6
76 #include <netinet/in.h>
77 #include <netinet6/in6_var.h>
80 #if !CYGPKG_NET_DRIVER_FRAMEWORK // Interface
81 #error At least one network driver framework must be defined!
83 #include <cyg/io/eth/netdev.h>
85 // Define table boundaries
86 CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
87 CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
88 CYG_HAL_TABLE_BEGIN( __NET_INIT_TAB__, _Net_inits );
89 CYG_HAL_TABLE_END( __NET_INIT_TAB_END__, _Net_inits );
90 extern struct init_tab_entry __NET_INIT_TAB__[], __NET_INIT_TAB_END__;
92 // Used for system-wide "ticks per second"
95 int tick = 10000; // usec per "tick"
96 volatile struct timeval ktime;
97 int proc = 0; // unused
98 struct proc * proc0 = 0; // unused
100 volatile struct timeval mono_time;
102 // Low-level network debugging & logging
103 #ifdef CYGPKG_NET_FREEBSD_LOGGING
104 int cyg_net_log_mask = CYGPKG_NET_FREEBSD_LOGGING;
107 #define STACK_SIZE CYGNUM_NET_THREAD_STACKSIZE
109 static char netint_stack[STACK_SIZE];
110 static cyg_thread netint_thread_data;
111 static cyg_handle_t netint_thread_handle;
113 cyg_flag_t netint_flags;
114 #define NETISR_ANY 0xFFFFFFFF // Any possible bit...
116 extern void cyg_test_exit(void); // TEMP
118 cyg_panic(const char *msg, ...)
122 HAL_DISABLE_INTERRUPTS(old_ints);
123 diag_printf("PANIC: %s\n", msg);
124 cyg_test_exit(); // FIXME
127 #define NET_MEMPOOL_SIZE roundup(CYGPKG_NET_MEMPOOL_SIZE,MSIZE)
128 #define NET_MBUFS_SIZE roundup(CYGPKG_NET_MBUFS_SIZE,MSIZE)
129 #define NET_CLUSTERS_SIZE roundup(CYGPKG_NET_CLUSTERS_SIZE,MCLBYTES)
131 static unsigned char net_mempool_area[NET_MEMPOOL_SIZE];
132 static cyg_mempool_var net_mem_pool;
133 static cyg_handle_t net_mem;
134 static unsigned char net_mbufs_area[NET_MBUFS_SIZE];
135 static cyg_mempool_fix net_mbufs_pool;
136 static cyg_handle_t net_mbufs;
137 static unsigned char net_clusters_area[NET_CLUSTERS_SIZE];
138 static cyg_mempool_fix net_clusters_pool;
139 static cyg_handle_t net_clusters;
140 static char net_clusters_refcnt[(NET_CLUSTERS_SIZE/MCLBYTES)+1];
141 int nmbclusters = (NET_CLUSTERS_SIZE/MCLBYTES);
143 #ifdef CYGDBG_NET_TIMING_STATS
144 static struct net_stats stats_malloc, stats_free,
145 stats_memcpy, stats_memset,
146 stats_mbuf_alloc, stats_mbuf_free, stats_cluster_alloc;
148 // Display a number of ticks as microseconds
149 // Note: for improved calculation significance, values are kept in ticks*1000
150 static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;
151 static long ns_per_system_clock;
154 show_ticks_in_us(cyg_uint32 ticks)
157 ns_per_system_clock = 1000000/rtc_resolution[1];
158 ns = (ns_per_system_clock * ((long long)ticks * 1000)) /
159 CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
160 ns += 5; // for rounding to .01us
161 diag_printf("%7d.%02d", (int)(ns/1000), (int)((ns%1000)/10));
165 show_net_stats(struct net_stats *stats, const char *title)
168 ave = stats->total_time / stats->count;
169 diag_printf("%s:\n", title);
170 diag_printf(" count: %6d", stats->count);
171 diag_printf(", min: ");
172 show_ticks_in_us(stats->min_time);
173 diag_printf(", max: ");
174 show_ticks_in_us(stats->max_time);
175 diag_printf(", total: ");
176 show_ticks_in_us(stats->total_time);
177 diag_printf(", ave: ");
178 show_ticks_in_us(ave);
181 memset(stats, 0, sizeof(*stats));
187 show_net_stats(&stats_malloc, "Net malloc");
188 show_net_stats(&stats_free, "Net free");
189 show_net_stats(&stats_mbuf_alloc, "Mbuf alloc");
190 show_net_stats(&stats_mbuf_free, "Mbuf free");
191 show_net_stats(&stats_cluster_alloc, "Cluster alloc");
192 show_net_stats(&stats_memcpy, "Net memcpy");
193 show_net_stats(&stats_memset, "Net memset");
195 #endif /* CYGDBG_NET_TIMING_STATS */
198 cyg_net_malloc(u_long size, int type, int flags)
203 log(LOG_MDEBUG, "Net malloc[%ld] = ", size);
204 if (flags & M_NOWAIT) {
205 res = cyg_mempool_var_try_alloc(net_mem, size);
207 res = cyg_mempool_var_alloc(net_mem, size);
209 if ((flags & M_ZERO) && res) {
212 FINISH_STATS(stats_malloc);
213 log(LOG_MDEBUG, "%p\n", res);
218 cyg_net_free(caddr_t addr, int type)
221 cyg_mempool_var_free(net_mem, addr);
222 FINISH_STATS(stats_free);
225 #ifdef CYGDBG_NET_SHOW_MBUFS
227 struct mbuf *mbinfo[300];
229 void cyg_net_show_mbufs(void)
232 diag_printf(" MBUF : TYPE FLGS DATA[LEN] NEXT NEXTPKT\n");
233 for( i = 0; i < 300; i++ )
235 struct mbuf *m = mbinfo[i];
237 if( m == 0 ) continue;
239 switch( m->m_hdr.mh_type )
241 case MT_FREE: type="FREE"; break;
242 case MT_DATA: type="DATA"; break;
243 case MT_HEADER: type="HEADER"; break;
244 case MT_SONAME: type="SONAME"; break;
245 case MT_FTABLE: type="FTABLE"; break;
246 case MT_CONTROL: type="CONTROL"; break;
247 case MT_OOBDATA: type="OOBDATA"; break;
248 default: type="UNKNOWN"; break;
251 diag_printf("%p: %s %04x %p[%03d] %p %p\n",
257 m->m_hdr.mh_nextpkt);
259 diag_printf(" MBUF : TYPE FLGS DATA[LEN] NEXT NEXTPKT\n");
265 cyg_net_mbuf_alloc(void)
270 log(LOG_MDEBUG, "Alloc mbuf = ");
271 res = cyg_mempool_fix_try_alloc(net_mbufs);
272 FINISH_STATS(stats_mbuf_alloc);
273 #ifdef CYGDBG_NET_SHOW_MBUFS
276 for( i = 0; i < (sizeof(mbinfo)/sizeof(mbinfo[0])); i++ )
279 mbinfo[i] = (struct mbuf *)res;
284 // Check that this nastiness works OK
285 CYG_ASSERT( dtom(res) == res, "dtom failed, base of mbuf" );
286 CYG_ASSERT( dtom((char *)res + MSIZE/2) == res, "dtom failed, mid mbuf" );
287 log(LOG_MDEBUG, "%p\n", res);
292 cyg_net_cluster_alloc(void)
297 log(LOG_MDEBUG, "Allocate cluster = ");
298 res = cyg_mempool_fix_try_alloc(net_clusters);
299 FINISH_STATS(stats_cluster_alloc);
300 log(LOG_MDEBUG, "%p\n", res);
304 static struct vm_zone *vm_zones = (struct vm_zone *)NULL;
307 zinit(char *name, int size, int nentries, int flags, int zalloc)
310 vm_zone_t zone = (vm_zone_t)0;
313 log(LOG_MDEBUG, "zinit '%s', size: %d, num: %d, flags: %d, alloc: %d\n",
314 name, size, nentries, flags, zalloc);
315 res = cyg_mempool_var_try_alloc(net_mem, sizeof(struct vm_zone));
317 zone = (vm_zone_t)res;
318 res = cyg_mempool_var_try_alloc(net_mem, size*nentries);
321 log(LOG_MDEBUG, "Can't allocate memory for %s\n", name);
322 panic("zinit: Out of memory\n");
325 zone->pool = (elem *)0;
326 zone->elem_size = size;
328 zone->free = zone->total = nentries;
329 zone->next = vm_zones;
330 zone->alloc_tries = zone->alloc_fails = zone->alloc_frees = 0;
332 while (nentries-- > 0) {
333 p->next = zone->pool;
335 p = (elem *)((char *)p + size);
340 log(LOG_MDEBUG, "p: %p, next: %p\n", p, p->next);
348 zalloci(vm_zone_t zone)
355 zone->pool = p->next;
360 log(LOG_MDEBUG, "zalloci from %s => %p\n", zone->name, p);
365 zfreei(vm_zone_t zone, void *item)
367 elem *p = (elem *)item;
369 log(LOG_MDEBUG, "zfreei to %s <= %p\n", zone->name, p);
370 p->next = zone->pool;
380 #ifdef CYGPKG_NET_DEBUG
381 diag_printf("Network stack using %d bytes for misc space\n", NET_MEMPOOL_SIZE);
382 diag_printf(" %d bytes for mbufs\n", NET_MBUFS_SIZE);
383 diag_printf(" %d bytes for mbuf clusters\n", NET_CLUSTERS_SIZE);
385 cyg_mempool_var_create(&net_mempool_area,
389 // Align the mbufs on MSIZE boudaries so that dtom() can work.
390 p = (unsigned char *)(((long)(&net_mbufs_area) + MSIZE - 1) & ~(MSIZE-1));
391 cyg_mempool_fix_create(p,
392 ((&(net_mbufs_area[NET_MBUFS_SIZE])) - p) & ~(MSIZE-1),
396 cyg_mempool_fix_create(&net_clusters_area,
401 mbutl = (struct mbuf *)&net_clusters_area;
402 mclrefcnt = net_clusters_refcnt;
405 void cyg_kmem_print_stats( void )
407 cyg_mempool_info info;
408 struct vm_zone *zone;
410 diag_printf( "Network stack mbuf stats:\n" );
411 diag_printf( " mbufs %ld, clusters %ld, free clusters %ld\n",
412 mbstat.m_mbufs, /* mbufs obtained from page pool */
413 mbstat.m_clusters, /* clusters obtained from page pool */
414 /* mbstat.m_spare, */ /* spare field */
415 mbstat.m_clfree /* free clusters */
417 diag_printf( " Failed to get %ld times\n"
418 " Waited to get %ld times\n"
419 " Drained queues to get %ld times\n",
420 mbstat.m_drops, /* times failed to find space */
421 mbstat.m_wait, /* times waited for space */
422 mbstat.m_drain /* times drained protocols for space */
423 /* mbstat.m_mtypes[256]; type specific mbuf allocations */
428 diag_printf("VM zone '%s':\n", zone->name);
429 diag_printf(" Total: %d, Free: %d, Allocs: %d, Frees: %d, Fails: %d\n",
430 zone->total, zone->free,
431 zone->alloc_tries, zone->alloc_frees, zone->alloc_fails);
435 cyg_mempool_var_get_info( net_mem, &info );
436 diag_printf( "Misc mpool: total %7d, free %7d, max free block %d\n",
442 cyg_mempool_fix_get_info( net_mbufs, &info );
443 diag_printf( "Mbufs pool: total %7d, free %7d, blocksize %4d\n",
450 cyg_mempool_fix_get_info( net_clusters, &info );
451 diag_printf( "Clust pool: total %7d, free %7d, blocksize %4d\n",
458 // This API is for our own automated network tests. It's not in any header
459 // files because it's not at all supported.
460 int cyg_net_get_mem_stats( int which, cyg_mempool_info *p )
462 CYG_CHECK_DATA_PTR( p, "Bad pointer to mempool_info" );
463 CYG_ASSERT( 0 <= which, "Mempool selector underflow" );
464 CYG_ASSERT( 2 >=which, "Mempool selector overflow" );
469 cyg_mempool_var_get_info( net_mem, p );
472 cyg_mempool_fix_get_info( net_mbufs, p );
475 cyg_mempool_fix_get_info( net_clusters, p );
487 res = (((u_long)(x) - (u_long)mbutl) >> MCLSHIFT);
495 res = (struct mbuf *)((caddr_t)((u_long)mbutl + ((u_long)(x) << MCLSHIFT)));
500 net_memcpy(void *d, void *s, int n)
504 FINISH_STATS(stats_memcpy);
508 net_memset(void *s, int v, int n)
512 FINISH_STATS(stats_memset);
515 // Rather than bring in the whole BSD 'random' code...
520 static unsigned long seed = 0xDEADB00B;
521 HAL_CLOCK_READ(&res); // Not so bad... (but often 0..N where N is small)
522 seed = ((seed & 0x007F00FF) << 7) ^
523 ((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
524 (res << 13) ^ (res >> 9); // using the clock too!
529 get_random_bytes(void *buf, size_t len)
531 unsigned long ranbuf, *lp;
532 lp = (unsigned long *)buf;
534 ranbuf = arc4random();
536 len -= sizeof(ranbuf);
541 read_random_unlimited(void *buf, size_t len)
543 get_random_bytes(buf, len);
547 void read_random(void *buf, size_t len)
549 CYG_ASSERT(0 == (len & ~3), "Only multiple of words allowed");
551 get_random_bytes(buf, len);
555 microtime(struct timeval *tp)
558 log(LOG_DEBUG, "%s: = %ld.%ld\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
559 ktime.tv_usec++; // In case clock isn't running yet
563 getmicrotime(struct timeval *tp)
566 log(LOG_DEBUG, "%s: = %ld.%ld\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
567 ktime.tv_usec++; // In case clock isn't running yet
571 getmicrouptime(struct timeval *tp)
574 log(LOG_DEBUG, "%s: = %ld.%ld\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
575 ktime.tv_usec++; // In case clock isn't running yet
578 // Taken from kern/kern_clock.c
580 * Compute number of ticks in the specified amount of time.
583 #define LONG_MAX 0x7FFFFFFF
586 tvtohz(struct timeval *tv)
588 register unsigned long ticks;
589 register long sec, usec;
592 * If the number of usecs in the whole seconds part of the time
593 * difference fits in a long, then the total number of usecs will
594 * fit in an unsigned long. Compute the total and convert it to
595 * ticks, rounding up and adding 1 to allow for the current tick
596 * to expire. Rounding also depends on unsigned long arithmetic
599 * Otherwise, if the number of ticks in the whole seconds part of
600 * the time difference fits in a long, then convert the parts to
601 * ticks separately and add, using similar rounding methods and
602 * overflow avoidance. This method would work in the previous
603 * case but it is slightly slower and assumes that hz is integral.
605 * Otherwise, round the time difference down to the maximum
606 * representable value.
608 * If ints have 32 bits, then the maximum value for any timeout in
609 * 10ms ticks is 248 days.
623 printf("tvotohz: negative time difference %ld sec %ld usec\n",
627 } else if (sec <= LONG_MAX / 1000000)
628 ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
630 else if (sec <= LONG_MAX / hz)
632 + ((unsigned long)usec + (tick - 1)) / tick + 1;
643 panic("get_mono_time");
647 csignal(pid_t pgid, int signum, uid_t uid, uid_t euid)
653 bcmp(const void *_p1, const void *_p2, size_t len)
656 unsigned char *p1 = (unsigned char *)_p1;
657 unsigned char *p2 = (unsigned char *)_p2;
666 copyout(const void *s, void *d, size_t len)
673 copyin(const void *s, void *d, size_t len)
680 ovbcopy(const void *s, void *d, size_t len)
686 // ------------------------------------------------------------------------
687 // THE NETWORK THREAD ITSELF
689 // Network software interrupt handler
690 // This function is run as a separate thread to allow
691 // processing of network events (mostly incoming packets)
692 // at "user level" instead of at interrupt time.
694 // The actual handlers are 'registered' at system startup
697 // The set of handlers
698 static netisr_t *_netisr_handlers[NETISR_MAX+1];
699 struct ifqueue ipintrq;
701 struct ifqueue ip6intrq;
703 char *hostname = "eCos_node";
705 // Register a 'netisr' handler for a given level
707 register_netisr(int level, netisr_t *fun)
709 CYG_ASSERT(level <= NETISR_MAX, "invalid netisr level");
710 CYG_ASSERT(_netisr_handlers[level] == 0, "re-registered netisr");
711 _netisr_handlers[level] = fun;
715 //int unregister_netisr __P((int));
718 cyg_netint(cyg_addrword_t param)
720 cyg_flag_value_t curisr;
724 curisr = cyg_flag_wait(&netint_flags, NETISR_ANY,
725 CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR);
726 spl = splsoftnet(); // Prevent any overlapping "stack" processing
727 for (lvl = NETISR_MIN; lvl <= NETISR_MAX; lvl++) {
728 if (curisr & (1<<lvl)) {
729 if (NULL != _netisr_handlers[lvl])
730 (*_netisr_handlers[lvl])();
738 // This just sets one of the pseudo-ISR bits used above.
742 // This is called if we are out of MBUFs - it doesn't do anything, and
743 // that situation is handled OK, so don't bother with the diagnostic:
745 // diag_printf("setsoftnet\n");
747 // No need to do this because it is ignored anyway:
748 // schednetisr(NETISR_SOFTNET);
752 /* Update the kernel globel ktime. */
754 cyg_ktime_func(cyg_handle_t alarm,cyg_addrword_t data)
756 cyg_tick_count_t now = cyg_current_time();
758 ktime.tv_usec = (now % hz) * tick;
759 ktime.tv_sec = 1 + now / hz;
765 cyg_handle_t ktime_alarm_handle;
766 static cyg_alarm ktime_alarm;
767 cyg_handle_t counter;
769 // Do not start at 0 - net stack thinks 0 an invalid time;
770 // Have a valid time available from right now:
774 cyg_clock_to_counter(cyg_real_time_clock(),&counter);
775 cyg_alarm_create(counter,
781 /* We want one alarm every 10ms. */
782 cyg_alarm_initialize(ktime_alarm_handle,cyg_current_time()+1,1);
783 cyg_alarm_enable(ktime_alarm_handle);
789 cyg_tick_count_t now = cyg_current_time();
794 // Network initialization
795 // This function is called during system initialization to setup the whole
796 // networking environment.
798 // Linker magic to execute this function as 'init'
799 extern void cyg_do_net_init(void);
801 extern void ifinit(void);
802 extern void loopattach(int);
803 extern void bridgeattach(int);
805 // Internal init functions:
806 extern void cyg_alarm_timeout_init(void);
807 extern void cyg_tsleep_init(void);
810 cyg_net_init_devs(void *ignored)
812 cyg_netdevtab_entry_t *t;
813 // Initialize all network devices
814 for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
815 log(LOG_INIT, "Init device '%s'\n", t->name);
817 t->status = CYG_NETDEVTAB_STATUS_AVAIL;
819 // What to do if device init fails?
820 t->status = 0; // Device not [currently] available
823 #if 0 // Bridge code not available yet
829 SYSINIT(devs, SI_SUB_DEVICES, SI_ORDER_FIRST, cyg_net_init_devs, NULL)
834 static int _init = false;
835 struct init_tab_entry *init_entry;
836 #ifdef CYGPKG_NET_FORCE_SERIAL_CONSOLE
838 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
843 #ifdef CYGPKG_NET_FORCE_SERIAL_CONSOLE
844 // Force default serial console during system initialization
845 // This avoids problems with debug messages occurring while the
846 // networking subsystem is being setup.
847 CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
850 cyg_do_net_init(); // Just forces linking in the initializer/constructor
851 // Initialize interrupt "flags"
852 cyg_flag_init(&netint_flags);
853 // Initialize timeouts and net service thread (pseudo-DSRs)
854 cyg_alarm_timeout_init();
855 // Initialize tsleep/wakeup support
857 // Initialize network memory system
859 // Initialize network time
861 // Create network background thread
862 cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY, // Priority
864 0, // entry parameter
865 "Network support", // Name
866 &netint_stack[0], // Stack
868 &netint_thread_handle, // Handle
869 &netint_thread_data // Thread data structure
871 cyg_thread_resume(netint_thread_handle); // Start it
873 // Run through dynamic initializers
874 for (init_entry = __NET_INIT_TAB__; init_entry != &__NET_INIT_TAB_END__; init_entry++) {
875 log(LOG_INIT, "[%s] Init: %s(%p)\n", __FUNCTION__, init_entry->name, init_entry->data);
876 (*init_entry->fun)(init_entry->data);
878 log(LOG_INIT, "[%s] Done\n", __FUNCTION__);
883 #ifdef CYGPKG_NET_FORCE_SERIAL_CONSOLE
884 // Revert to the original console, which might be a network connection
885 CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console);
891 #include <net/netdb.h>
892 #include <net/route.h>
893 externC void if_indextoname(int indx, char *buf, int len);
895 typedef void pr_fun(char *fmt, ...);
898 _mask(struct sockaddr *sa, char *buf, int _len)
900 unsigned char *cp = ((unsigned char *)sa) + 4;
901 int len = sa->sa_len - 4;
905 if (tot) *buf++ = '.';
906 buf += diag_sprintf(buf, "%u", *cp++);
911 if (tot) *buf++ = '.';
912 buf += diag_sprintf(buf, "%d", 0);
917 #ifdef CYGPKG_NET_INET6
919 _mask6(struct sockaddr *sa, char *buf, int _len)
921 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
926 while (addrword < 4) {
927 if (sin6->sin6_addr.s6_addr32[addrword] == 0) {
930 HAL_LSBIT_INDEX(index, sin6->sin6_addr.s6_addr32[addrword++]);
936 diag_sprintf(buf, "%d", bits);
940 _show_ifp(struct ifnet *ifp, pr_fun *pr)
943 char name[64], addr[64], netmask[64], broadcast[64];
945 if_indextoname(ifp->if_index, name, 64);
946 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
947 if (ifa->ifa_addr->sa_family != AF_LINK) {
949 getnameinfo (ifa->ifa_addr, ifa->ifa_addr->sa_len, addr,
950 sizeof(addr), 0, 0, NI_NUMERICHOST);
951 if (ifa->ifa_addr->sa_family == AF_INET) {
952 getnameinfo (ifa->ifa_dstaddr, ifa->ifa_dstaddr->sa_len,
953 broadcast, sizeof(broadcast),
954 0, 0, NI_NUMERICHOST);
955 _mask(ifa->ifa_netmask, netmask, 64);
956 (*pr)("IP: %s, Broadcast: %s, Netmask: %s\n",
957 addr, broadcast, netmask);
959 #ifdef CYGPKG_NET_INET6
960 if (ifa->ifa_addr->sa_family == AF_INET6) {
961 struct in6_ifaddr * ifa6 = (struct in6_ifaddr *) ifa;
962 _mask6(ifa->ifa_netmask, netmask, 64);
963 (*pr)("IP: %s/%s ", addr,netmask);
964 if (ifa6->ia6_flags & IN6_IFF_ANYCAST) (*pr) ("Anycast ");
965 if (ifa6->ia6_flags & IN6_IFF_TENTATIVE) (*pr) ("Tentative ");
966 if (ifa6->ia6_flags & IN6_IFF_DUPLICATED) (*pr) ("Duplicate ");
967 if (ifa6->ia6_flags & IN6_IFF_DETACHED) (*pr) ("Detached ");
968 if (ifa6->ia6_flags & IN6_IFF_DEPRECATED) (*pr) ("Deprecated ");
969 if (ifa6->ia6_flags & IN6_IFF_NODAD) (*pr) ("NoDAD ");
970 if (ifa6->ia6_flags & IN6_IFF_AUTOCONF) (*pr) ("AutoConf ");
971 if (ifa6->ia6_flags & IN6_IFF_TEMPORARY) (*pr) ("Tempory ");
972 if (ifa6->ia6_flags & IN6_IFF_HOME) (*pr) ("Home ");
977 if ((ifp->if_flags & IFF_UP)) (*pr)("UP ");
978 if ((ifp->if_flags & IFF_BROADCAST)) (*pr)("BROADCAST ");
979 if ((ifp->if_flags & IFF_LOOPBACK)) (*pr)("LOOPBACK ");
980 if ((ifp->if_flags & IFF_RUNNING)) (*pr)("RUNNING ");
981 if ((ifp->if_flags & IFF_PROMISC)) (*pr)("PROMISC ");
982 if ((ifp->if_flags & IFF_MULTICAST)) (*pr)("MULTICAST ");
983 if ((ifp->if_flags & IFF_ALLMULTI)) (*pr)("ALLMULTI ");
984 (*pr)("MTU: %d, Metric: %d\n", ifp->if_mtu, ifp->if_metric);
985 (*pr)(" Rx - Packets: %d, Bytes: %d",
986 ifa->if_data.ifi_ipackets, ifa->if_data.ifi_ibytes);
987 (*pr)(", Tx - Packets: %d, Bytes: %d\n",
988 ifa->if_data.ifi_opackets, ifa->if_data.ifi_obytes);
994 _dumpentry(struct radix_node *rn, void *vw)
996 struct rtentry *rt = (struct rtentry *)rn;
997 struct sockaddr *dst, *gate, *netmask, *genmask;
999 pr_fun *pr = (pr_fun *)vw;
1002 gate = rt->rt_gateway;
1003 netmask = rt_mask(rt);
1004 genmask = rt->rt_genmask;
1005 if ((rt->rt_flags & (RTF_UP | RTF_WASCLONED)) == RTF_UP) {
1006 _inet_ntop(dst, addr, sizeof(addr));
1007 (*pr)("%-15s ", addr);
1009 _inet_ntop(gate, addr, sizeof(addr));
1010 (*pr)("%-15s ", addr);
1012 (*pr)("%-15s ", " ");
1014 if (netmask != NULL) {
1015 if (dst->sa_family == AF_INET) {
1016 _mask(netmask, addr, sizeof(addr));
1017 (*pr)("%-15s ", addr);
1019 #ifdef CYGPKG_NET_INET6
1020 if (dst->sa_family == AF_INET6) {
1021 _mask6(netmask, addr, sizeof(addr));
1022 (*pr)("/%-14s ", addr);
1026 (*pr)("%-15s ", " ");
1029 if ((rt->rt_flags & RTF_UP)) *cp++ = 'U';
1030 if ((rt->rt_flags & RTF_GATEWAY)) *cp++ = 'G';
1031 if ((rt->rt_flags & RTF_HOST)) *cp++ = 'H';
1032 if ((rt->rt_flags & RTF_REJECT)) *cp++ = '!';
1033 if ((rt->rt_flags & RTF_STATIC)) *cp++ = 'S';
1034 if ((rt->rt_flags & RTF_DYNAMIC)) *cp++ = 'D';
1035 if ((rt->rt_flags & RTF_MODIFIED)) *cp++ = 'M';
1037 (*pr)("%-8s ", addr); // Flags
1038 if_indextoname(rt->rt_ifp->if_index, addr, 64);
1039 (*pr)("%-8s ", addr);
1046 show_network_tables(pr_fun *pr)
1049 struct radix_node_head *rnh;
1052 cyg_scheduler_lock();
1053 (*pr)("Routing tables\n");
1054 (*pr)("Destination Gateway Mask Flags Interface\n");
1055 for (i = 1; i <= AF_MAX; i++) {
1056 if ((rnh = rt_tables[i]) != NULL) {
1057 error = rnh->rnh_walktree(rnh, _dumpentry, pr);
1061 (*pr)("Interface statistics\n");
1062 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
1065 cyg_scheduler_unlock();
1068 #endif // CYGPKG_NET_DRIVER_FRAMEWORK