/*** * * tools/rtifconfig.c * ifconfig replacement for RTnet * * rtnet - real-time networking subsystem * Copyright (C) 1999, 2000 Zentropic Computing, LLC * 2004, 2005 Jan Kiszka * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* Some old toolchains don't ARPHRD_IEEE1394 defined */ #ifndef ARPHRD_IEEE1394 #define ARPHRD_IEEE1394 24 #endif #define PRINT_FLAG_ALL 1 #define PRINT_FLAG_INACTIVE 2 int f; struct rtnet_core_cmd cmd; struct user_net_device_stats { unsigned long long rx_packets; /* total packets received */ unsigned long long tx_packets; /* total packets transmitted */ unsigned long long rx_bytes; /* total bytes received */ unsigned long long tx_bytes; /* total bytes transmitted */ unsigned long rx_errors; /* bad packets received */ unsigned long tx_errors; /* packet transmit problems */ unsigned long rx_dropped; /* no space in linux buffers */ unsigned long tx_dropped; /* no space available in linux */ unsigned long rx_multicast; /* multicast packets received */ unsigned long rx_compressed; unsigned long tx_compressed; unsigned long collisions; /* detailed rx_errors: */ unsigned long rx_length_errors; unsigned long rx_over_errors; /* receiver ring buff overflow */ unsigned long rx_crc_errors; /* recved pkt with crc error */ unsigned long rx_frame_errors; /* recv'd frame alignment error */ unsigned long rx_fifo_errors; /* recv'r fifo overrun */ unsigned long rx_missed_errors; /* receiver missed packet */ /* detailed tx_errors */ unsigned long tx_aborted_errors; unsigned long tx_carrier_errors; unsigned long tx_fifo_errors; unsigned long tx_heartbeat_errors; unsigned long tx_window_errors; }; struct itf_stats { char name[IFNAMSIZ]; struct user_net_device_stats stats; struct itf_stats *next; }; static struct itf_stats *itf_stats_head; void parse_stats(void) { struct itf_stats *itf; char buf[512]; FILE *fh; int ret; fh = fopen("/proc/rtnet/stats", "r"); if (!fh) return; fgets(buf, sizeof buf, fh); /* eat headers */ fgets(buf, sizeof buf, fh); while (fgets(buf, sizeof buf, fh)) { char *name, *p; itf = malloc(sizeof(*itf)); if (!itf) return; name = buf; while (isspace(*name)) name++; p = name; while (*p && *p != ':') p++; *p = '\0'; snprintf(itf->name, sizeof(itf->name), "%s", name); p++; ret = sscanf(p, "%llu %llu %lu %lu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu %lu", &itf->stats.rx_bytes, &itf->stats.rx_packets, &itf->stats.rx_errors, &itf->stats.rx_dropped, &itf->stats.rx_fifo_errors, &itf->stats.rx_frame_errors, &itf->stats.rx_compressed, &itf->stats.rx_multicast, &itf->stats.tx_bytes, &itf->stats.tx_packets, &itf->stats.tx_errors, &itf->stats.tx_dropped, &itf->stats.tx_fifo_errors, &itf->stats.collisions, &itf->stats.tx_carrier_errors, &itf->stats.tx_compressed); if (ret < 16) { free(itf); continue; } itf->next = itf_stats_head; itf_stats_head = itf; } fclose(fh); } struct itf_stats *find_stats(const char *itf_name) { struct itf_stats *itf; for(itf = itf_stats_head; itf; itf = itf->next) if(!strcmp(itf->name, itf_name)) break; return itf; } void help(void) { fprintf(stderr, "Usage:\n" "\trtifconfig [-a] []\n" "\trtifconfig up [ [netmask ]] " "[hw
] [[-]promisc]\n" "\trtifconfig down\n" ); exit(1); } void print_dev(void) { struct in_addr ip_addr; struct in_addr broadcast_ip; unsigned int flags; struct itf_stats *itf; cmd.head.if_name[IFNAMSIZ - 1] = 0; printf("%-9s Medium: ", cmd.head.if_name); if ((cmd.args.info.flags & IFF_LOOPBACK) != 0) printf("Local Loopback\n"); else switch (cmd.args.info.type) { case ARPHRD_ETHER: case ARPHRD_IEEE1394: printf("%s Hardware address: " "%02X:%02X:%02X:%02X:%02X:%02X\n", (cmd.args.info.type == ARPHRD_ETHER) ? "Ethernet " : "Eth1394 ", cmd.args.info.dev_addr[0], cmd.args.info.dev_addr[1], cmd.args.info.dev_addr[2], cmd.args.info.dev_addr[3], cmd.args.info.dev_addr[4], cmd.args.info.dev_addr[5]); break; default: printf("unknown (%X)\n", cmd.args.info.type); } if (cmd.args.info.ip_addr != 0) { ip_addr.s_addr = cmd.args.info.ip_addr; broadcast_ip.s_addr = cmd.args.info.broadcast_ip; printf(" IP address: %s ", inet_ntoa(ip_addr)); if (cmd.args.info.flags & IFF_BROADCAST) printf("Broadcast address: %s", inet_ntoa(broadcast_ip)); printf("\n"); } flags = cmd.args.info.flags & (IFF_UP | IFF_BROADCAST | IFF_LOOPBACK | IFF_RUNNING | IFF_PROMISC); printf(" %s%s%s%s%s%s MTU: %d\n", ((flags & IFF_UP) != 0) ? "UP " : "", ((flags & IFF_BROADCAST) != 0) ? "BROADCAST " : "", ((flags & IFF_LOOPBACK) != 0) ? "LOOPBACK " : "", ((flags & IFF_RUNNING) != 0) ? "RUNNING " : "", ((flags & IFF_PROMISC) != 0) ? "PROMISC " : "", (flags == 0) ? "[NO FLAGS] " : "", cmd.args.info.mtu); if ((itf = find_stats(cmd.head.if_name))) { unsigned long long rx, tx, short_rx, short_tx; char Rext[5]="b"; char Text[5]="b"; printf(" "); printf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n", itf->stats.rx_packets, itf->stats.rx_errors, itf->stats.rx_dropped, itf->stats.rx_fifo_errors, itf->stats.rx_frame_errors); printf(" "); printf("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n", itf->stats.tx_packets, itf->stats.tx_errors, itf->stats.tx_dropped, itf->stats.tx_fifo_errors, itf->stats.tx_carrier_errors); printf(" collisions:%lu ", itf->stats.collisions); printf("\n "); rx = itf->stats.rx_bytes; tx = itf->stats.tx_bytes; short_rx = rx * 10; short_tx = tx * 10; if (rx > 1048576) { short_rx /= 1048576; strcpy(Rext, "Mb"); } else if (rx > 1024) { short_rx /= 1024; strcpy(Rext, "Kb"); } if (tx > 1048576) { short_tx /= 1048576; strcpy(Text, "Mb"); } else if (tx > 1024) { short_tx /= 1024; strcpy(Text, "Kb"); } printf("RX bytes:%llu (%lu.%lu %s) TX bytes:%llu (%lu.%lu %s)\n", rx, (unsigned long)(short_rx / 10), (unsigned long)(short_rx % 10), Rext, tx, (unsigned long)(short_tx / 10), (unsigned long)(short_tx % 10), Text); } printf("\n"); } void do_display(int print_flags) { int i; int ret; parse_stats(); if ((print_flags & PRINT_FLAG_ALL) != 0) for (i = 1; i <= MAX_RT_DEVICES; i++) { cmd.args.info.ifindex = i; ret = ioctl(f, IOC_RT_IFINFO, &cmd); if (ret == 0) { if (((print_flags & PRINT_FLAG_INACTIVE) != 0) || ((cmd.args.info.flags & IFF_UP) != 0)) print_dev(); } else if (errno != ENODEV) { perror("ioctl"); exit(1); } } else { cmd.args.info.ifindex = 0; ret = ioctl(f, IOC_RT_IFINFO, &cmd); if (ret < 0) { perror("ioctl"); exit(1); } print_dev(); } exit(0); } void do_up(int argc, char *argv[]) { int ret; int i; struct in_addr addr; __u32 ip_mask; struct ether_addr hw_addr; if ((argc > 3) && (inet_aton(argv[3], &addr))) { i = 4; cmd.args.up.ip_addr = addr.s_addr; if (addr.s_addr == 0xFFFFFFFF) { fprintf(stderr, "Invalid IP address!\n"); exit(1); } } else { i = 3; /* don't change ip settings */ cmd.args.up.ip_addr = 0xFFFFFFFF; } /* set default netmask */ if (ntohl(cmd.args.up.ip_addr) <= 0x7FFFFFFF) /* 127.255.255.255 */ ip_mask = 0x000000FF; /* 255.0.0.0 */ else if (ntohl(cmd.args.up.ip_addr) <= 0xBFFFFFFF) /* 191.255.255.255 */ ip_mask = 0x0000FFFF; /* 255.255.0.0 */ else ip_mask = 0x00FFFFFF; /* 255.255.255.0 */ /* default: don't change flags, don't set dev_addr */ cmd.args.up.set_dev_flags = 0; cmd.args.up.clear_dev_flags = 0; cmd.args.up.dev_addr_type = 0xFFFF; /* parse optional parameters */ for ( ; i < argc; i++) { if (strcmp(argv[i], "netmask") == 0) { if ((++i >= argc) || (cmd.args.up.ip_addr == 0) || (!inet_aton(argv[i], &addr))) help(); ip_mask = addr.s_addr; } else if (strcmp(argv[i], "hw") == 0) { if ((++i >= argc) || (strcmp(argv[i], "ether") != 0) || (++i >= argc) || (ether_aton_r(argv[i], &hw_addr) == NULL)) help(); memcpy(cmd.args.up.dev_addr, hw_addr.ether_addr_octet, sizeof(hw_addr.ether_addr_octet)); cmd.args.up.dev_addr_type = ARPHRD_ETHER; } else if (strcmp(argv[i], "promisc") == 0) { cmd.args.up.set_dev_flags |= IFF_PROMISC; cmd.args.up.clear_dev_flags &= ~IFF_PROMISC; } else if (strcmp(argv[i], "-promisc") == 0) { cmd.args.up.set_dev_flags &= ~IFF_PROMISC; cmd.args.up.clear_dev_flags |= IFF_PROMISC; } else help(); } cmd.args.up.broadcast_ip = cmd.args.up.ip_addr | (~ip_mask); ret = ioctl(f, IOC_RT_IFUP, &cmd); if (ret < 0) { perror("ioctl"); exit(1); } exit(0); } void do_down(int argc,char *argv[]) { int r; if (argc > 3) help(); r = ioctl(f, IOC_RT_IFDOWN, &cmd); if (r < 0) { perror("ioctl"); exit(1); } exit(0); } int main(int argc, char *argv[]) { if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) help(); f = open("/dev/rtnet", O_RDWR); if (f < 0) { perror("/dev/rtnet"); exit(1); } if (argc == 1) do_display(PRINT_FLAG_ALL); if (strcmp(argv[1], "-a") == 0) { if (argc == 3) { strncpy(cmd.head.if_name, argv[2], IFNAMSIZ); do_display(PRINT_FLAG_INACTIVE); } else do_display(PRINT_FLAG_INACTIVE | PRINT_FLAG_ALL); } else strncpy(cmd.head.if_name, argv[1], IFNAMSIZ); if (argc < 3) do_display(0); if (strcmp(argv[2], "up") == 0) do_up(argc,argv); if (strcmp(argv[2], "down") == 0) do_down(argc,argv); help(); return 0; }