int mt_main(int argc, char **argv) { const char *file = "/dev/tape"; struct mtop op; struct mtpos position; int fd, mode, idx; if (argc < 2) { bb_show_usage(); } if (strcmp(argv[1], "-f") == 0) { if (argc < 4) { bb_show_usage(); } file = argv[2]; argv += 2; argc -= 2; } idx = index_in_strings(opcode_name, argv[1]); if (idx < 0) bb_error_msg_and_die("unrecognized opcode %s", argv[1]); op.mt_op = opcode_value[idx]; if (argc >= 3) op.mt_count = xatoi_u(argv[2]); else op.mt_count = 1; /* One, not zero, right? */ switch (opcode_value[idx]) { case MTWEOF: case MTERASE: case MTWSM: case MTSETDRVBUFFER: mode = O_WRONLY; break; default: mode = O_RDONLY; break; } fd = xopen(file, mode); switch (opcode_value[idx]) { case MTTELL: ioctl_or_perror_and_die(fd, MTIOCPOS, &position, "%s", file); printf("At block %d\n", (int) position.mt_blkno); break; default: ioctl_or_perror_and_die(fd, MTIOCTOP, &op, "%s", file); break; } return EXIT_SUCCESS; }
static void eject_scsi(const char *dev) { static const char sg_commands[3][6] = { { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 }, { START_STOP, 0, 0, 0, 1, 0 }, { START_STOP, 0, 0, 0, 2, 0 } }; unsigned i; unsigned char sense_buffer[32]; unsigned char inqBuff[2]; sg_io_hdr_t io_hdr; if ((ioctl(dev_fd, SG_GET_VERSION_NUM, &i) < 0) || (i < 30000)) bb_error_msg_and_die("not a sg device or old sg driver"); memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); io_hdr.interface_id = 'S'; io_hdr.cmd_len = 6; io_hdr.mx_sb_len = sizeof(sense_buffer); io_hdr.dxfer_direction = SG_DXFER_NONE; /* io_hdr.dxfer_len = 0; */ io_hdr.dxferp = inqBuff; io_hdr.sbp = sense_buffer; io_hdr.timeout = 2000; for (i = 0; i < 3; i++) { io_hdr.cmdp = (void *)sg_commands[i]; ioctl_or_perror_and_die(dev_fd, SG_IO, (void *)&io_hdr, "%s", dev); } /* force kernel to reread partition table when new disc is inserted */ ioctl(dev_fd, BLKRRPART); }
int eject_main(int argc, char **argv) { unsigned long flags; const char *device; int dev, cmd; opt_complementary = "?1:t--T:T--t"; flags = getopt32(argv, "tT"); device = argv[optind] ? : "/dev/cdrom"; // We used to do "umount <device>" here, but it was buggy // if something was mounted OVER cdrom and // if cdrom is mounted many times. // // This works equally well (or better): // #!/bin/sh // umount /dev/cdrom // eject dev = xopen(device, O_RDONLY|O_NONBLOCK); cmd = CDROMEJECT; if (flags & FLAG_CLOSE || (flags & FLAG_SMART && ioctl(dev, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN)) cmd = CDROMCLOSETRAY; ioctl_or_perror_and_die(dev, cmd, NULL, "%s", device); if (ENABLE_FEATURE_CLEAN_UP) close(dev); return EXIT_SUCCESS; }
int vconfig_main(int argc, char **argv) { struct vlan_ioctl_args ifr; const char *p; int fd; if (argc < 3) { bb_show_usage(); } /* Don't bother closing the filedes. It will be closed on cleanup. */ /* Will die if 802.1q is not present */ xopen(conf_file_name, O_RDONLY); memset(&ifr, 0, sizeof(struct vlan_ioctl_args)); ++argv; p = xfind_str(cmds+2, *argv); ifr.cmd = *p; if (argc != p[-1]) { bb_show_usage(); } if (ifr.cmd == SET_VLAN_NAME_TYPE_CMD) { /* set_name_type */ ifr.u.name_type = *xfind_str(name_types+1, argv[1]); } else { if (strlen(argv[1]) >= IF_NAMESIZE) { bb_error_msg_and_die("if_name >= %d chars", IF_NAMESIZE); } strcpy(ifr.device1, argv[1]); p = argv[2]; /* I suppose one could try to combine some of the function calls below, * since ifr.u.flag, ifr.u.VID, and ifr.u.skb_priority are all same-sized * (unsigned) int members of a unions. But because of the range checking, * doing so wouldn't save that much space and would also make maintainence * more of a pain. */ if (ifr.cmd == SET_VLAN_FLAG_CMD) { /* set_flag */ ifr.u.flag = xatoul_range(p, 0, 1); /* DM: in order to set reorder header, qos must be set */ ifr.vlan_qos = xatoul_range(argv[3], 0, 7); } else if (ifr.cmd == ADD_VLAN_CMD) { /* add */ ifr.u.VID = xatoul_range(p, 0, VLAN_GROUP_ARRAY_LEN-1); } else if (ifr.cmd != DEL_VLAN_CMD) { /* set_{egress|ingress}_map */ ifr.u.skb_priority = xatou(p); ifr.vlan_qos = xatoul_range(argv[3], 0, 7); } } fd = xsocket(AF_INET, SOCK_STREAM, 0); ioctl_or_perror_and_die(fd, SIOCSIFVLAN, &ifr, "ioctl error for %s", *argv); return 0; }
static void eject_cdrom(unsigned flags, const char *dev) { int cmd = CDROMEJECT; if (flags & FLAG_CLOSE || ((flags & FLAG_SMART) && ioctl(dev_fd, CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN) ) { cmd = CDROMCLOSETRAY; } ioctl_or_perror_and_die(dev_fd, cmd, NULL, "%s", dev); }
int blkdiscard_main(int argc UNUSED_PARAM, char **argv) { unsigned opts; const char *offset_str = "0"; const char *length_str; uint64_t offset; /* Leaving these two variables out does not */ uint64_t length; /* shrink code size and hampers readability. */ uint64_t range[2]; // struct stat st; int fd; enum { OPT_OFFSET = (1 << 0), OPT_LENGTH = (1 << 1), OPT_SECURE = (1 << 2), }; opt_complementary = "=1"; opts = getopt32(argv, "o:l:s", &offset_str, &length_str); argv += optind; fd = xopen(argv[0], O_RDWR|O_EXCL); //Why bother, BLK[SEC]DISCARD will fail on non-blockdevs anyway? // xfstat(fd, &st); // if (!S_ISBLK(st.st_mode)) // bb_error_msg_and_die("%s: not a block device", argv[0]); offset = xatoull_sfx(offset_str, kMG_suffixes); if (opts & OPT_LENGTH) length = xatoull_sfx(length_str, kMG_suffixes); else { xioctl(fd, BLKGETSIZE64, &length); length -= offset; } range[0] = offset; range[1] = length; ioctl_or_perror_and_die(fd, (opts & OPT_SECURE) ? BLKSECDISCARD : BLKDISCARD, &range, "%s: %s failed", argv[0], (opts & OPT_SECURE) ? "BLKSECDISCARD" : "BLKDISCARD" ); if (ENABLE_FEATURE_CLEAN_UP) close(fd); return EXIT_SUCCESS; }
int freeramdisk_main(int argc UNUSED_PARAM, char **argv) { int fd; fd = xopen(single_argv(argv), O_RDWR); // Act like freeramdisk, fdflush, or both depending on configuration. ioctl_or_perror_and_die(fd, (ENABLE_FREERAMDISK && applet_name[1] == 'r') || !ENABLE_FDFLUSH ? BLKFLSBUF : FDFLUSH, NULL, "%s", argv[1]); if (ENABLE_FEATURE_CLEAN_UP) close(fd); return EXIT_SUCCESS; }
/* Get the hardware address to a specified interface name */ static void arp_getdevhw(char *ifname, struct sockaddr *sa, const struct hwtype *hwt) { struct ifreq ifr; const struct hwtype *xhw; strcpy(ifr.ifr_name, ifname); ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr, "cant get HW-Address for '%s'", ifname); if (hwt && (ifr.ifr_hwaddr.sa_family != hw->type)) { bb_error_msg_and_die("protocol type mismatch"); } memcpy(sa, &(ifr.ifr_hwaddr), sizeof(struct sockaddr)); if (option_mask32 & ARP_OPT_v) { xhw = get_hwntype(ifr.ifr_hwaddr.sa_family); if (!xhw || !xhw->print) { xhw = get_hwntype(-1); } bb_error_msg("device '%s' has HW address %s '%s'", ifname, xhw->name, xhw->print((char *) &ifr.ifr_hwaddr.sa_data)); } }
int arping_main(int argc UNUSED_PARAM, char **argv) { const char *device = "eth0"; char *source = NULL; char *target; unsigned char *packet; char *err_str; INIT_G(); sock_fd = xsocket(AF_PACKET, SOCK_DGRAM, 0); // Drop suid root privileges // Need to remove SUID_NEVER from applets.h for this to work //xsetuid(getuid()); err_str = xasprintf("interface %s %%s", device); { unsigned opt; char *str_timeout; /* Dad also sets quit_on_reply. * Advert also sets unsolicited. */ opt_complementary = "=1:Df:AU:c+"; opt = getopt32(argv, "DUAqfbc:w:I:s:", &count, &str_timeout, &device, &source); if (opt & 0x80) /* -w: timeout */ timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000; //if (opt & 0x200) /* -s: source */ option_mask32 &= 0x3f; /* set respective flags */ } target = argv[optind]; xfunc_error_retval = 2; { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy_IFNAMSIZ(ifr.ifr_name, device); /* We use ifr.ifr_name in error msg so that problem * with truncated name will be visible */ ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found"); me.sll_ifindex = ifr.ifr_ifindex; xioctl(sock_fd, SIOCGIFFLAGS, (char *) &ifr); if (!(ifr.ifr_flags & IFF_UP)) { bb_error_msg_and_die(err_str, "is down"); } if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { bb_error_msg(err_str, "is not ARPable"); return (option_mask32 & DAD ? 0 : 2); } } /* if (!inet_aton(target, &dst)) - not needed */ { len_and_sockaddr *lsa; lsa = xhost_and_af2sockaddr(target, 0, AF_INET); dst = lsa->u.sin.sin_addr; if (ENABLE_FEATURE_CLEAN_UP) free(lsa); } if (source && !inet_aton(source, &src)) { bb_error_msg_and_die("invalid source address %s", source); } if ((option_mask32 & (DAD|UNSOLICITED)) == UNSOLICITED && src.s_addr == 0) src = dst; if (!(option_mask32 & DAD) || src.s_addr) { struct sockaddr_in saddr; int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); setsockopt_bindtodevice(probe_fd, device); memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; if (src.s_addr) { /* Check that this is indeed our IP */ saddr.sin_addr = src; xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); } else { /* !(option_mask32 & DAD) case */ /* Find IP address on this iface */ socklen_t alen = sizeof(saddr); saddr.sin_port = htons(1025); saddr.sin_addr = dst; if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1) bb_perror_msg("setsockopt(SO_DONTROUTE)"); xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) { bb_perror_msg_and_die("getsockname"); } if (saddr.sin_family != AF_INET) bb_error_msg_and_die("no IP address configured"); src = saddr.sin_addr; } close(probe_fd); } me.sll_family = AF_PACKET; //me.sll_ifindex = ifindex; - done before me.sll_protocol = htons(ETH_P_ARP); xbind(sock_fd, (struct sockaddr *) &me, sizeof(me)); { socklen_t alen = sizeof(me); if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) { bb_perror_msg_and_die("getsockname"); } } if (me.sll_halen == 0) { bb_error_msg(err_str, "is not ARPable (no ll address)"); return (option_mask32 & DAD ? 0 : 2); } he = me; memset(he.sll_addr, -1, he.sll_halen); if (!(option_mask32 & QUIET)) { /* inet_ntoa uses static storage, can't use in same printf */ printf("ARPING to %s", inet_ntoa(dst)); printf(" from %s via %s\n", inet_ntoa(src), device); } signal_SA_RESTART_empty_mask(SIGINT, (void (*)(int))finish); signal_SA_RESTART_empty_mask(SIGALRM, (void (*)(int))catcher); catcher(); packet = xmalloc(4096); while (1) { sigset_t sset, osset; struct sockaddr_ll from; socklen_t alen = sizeof(from); int cc; cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen); if (cc < 0) { bb_perror_msg("recvfrom"); continue; } sigemptyset(&sset); sigaddset(&sset, SIGALRM); sigaddset(&sset, SIGINT); sigprocmask(SIG_BLOCK, &sset, &osset); recv_pack(packet, cc, &from); sigprocmask(SIG_SETMASK, &osset, NULL); } }
int nameif_main(int argc, char **argv) { ethtable_t *clist = NULL; FILE *ifh; const char *fname = "/etc/mactab"; char *line; char *line_ptr; int linenum; int ctl_sk; ethtable_t *ch; if (1 & getopt32(argv, "sc:", &fname)) { openlog(applet_name, 0, LOG_LOCAL0); logmode = LOGMODE_SYSLOG; } argc -= optind; argv += optind; if (argc & 1) bb_show_usage(); if (argc) { while (*argv) { char *ifname = xstrdup(*argv++); prepend_new_eth_table(&clist, ifname, *argv++); } } else { ifh = xfopen(fname, "r"); while ((line = xmalloc_fgets(ifh)) != NULL) { char *next; line_ptr = skip_whitespace(line); if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) { free(line); continue; } next = skip_non_whitespace(line_ptr); if (*next) *next++ = '\0'; prepend_new_eth_table(&clist, line_ptr, next); free(line); } fclose(ifh); } ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); ifh = xfopen("/proc/net/dev", "r"); linenum = 0; while (clist) { struct ifreq ifr; #if ENABLE_FEATURE_NAMEIF_EXTENDED struct ethtool_drvinfo drvinfo; #endif line = xmalloc_fgets(ifh); if (line == NULL) break; /* Seems like we're done */ if (linenum++ < 2 ) goto next_line; /* Skip the first two lines */ /* Find the current interface name and copy it to ifr.ifr_name */ line_ptr = skip_whitespace(line); *skip_non_whitespace(line_ptr) = '\0'; memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, line_ptr, sizeof(ifr.ifr_name)); #if ENABLE_FEATURE_NAMEIF_EXTENDED /* Check for driver etc. */ memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo)); drvinfo.cmd = ETHTOOL_GDRVINFO; ifr.ifr_data = (caddr_t) &drvinfo; /* Get driver and businfo first, so we have it in drvinfo */ ioctl(ctl_sk, SIOCETHTOOL, &ifr); #endif ioctl(ctl_sk, SIOCGIFHWADDR, &ifr); /* Search the list for a matching device */ for (ch = clist; ch; ch = ch->next) { #if ENABLE_FEATURE_NAMEIF_EXTENDED if (ch->bus_info && strcmp(ch->bus_info, drvinfo.bus_info) != 0) continue; if (ch->driver && strcmp(ch->driver, drvinfo.driver) != 0) continue; #endif if (ch->mac && memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != 0) continue; /* if we came here, all selectors have matched */ goto found; } /* Nothing found for current interface */ goto next_line; found: if (strcmp(ifr.ifr_name, ch->ifname) != 0) { strcpy(ifr.ifr_newname, ch->ifname); ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr, "cannot change ifname %s to %s", ifr.ifr_name, ch->ifname); } /* Remove list entry of renamed interface */ if (ch->prev != NULL) ch->prev->next = ch->next; else clist = ch->next; if (ch->next != NULL) ch->next->prev = ch->prev; if (ENABLE_FEATURE_CLEAN_UP) { free(ch->ifname); free(ch->mac); free(ch); } next_line: free(line); } if (ENABLE_FEATURE_CLEAN_UP) { fclose(ifh); }; return 0; }
int ether_wake_main(int argc UNUSED_PARAM, char **argv) { const char *ifname = "eth0"; char *pass; unsigned flags; unsigned char wol_passwd[6]; int wol_passwd_sz = 0; int s; /* Raw socket */ int pktsize; unsigned char outpack[1000]; struct ether_addr eaddr; struct whereto_t whereto; /* who to wake up */ /* handle misc user options */ opt_complementary = "=1"; flags = getopt32(argv, "bi:p:", &ifname, &pass); if (flags & 4) /* -p */ wol_passwd_sz = get_wol_pw(pass, wol_passwd); flags &= 1; /* we further interested only in -b [bcast] flag */ /* create the raw socket */ s = make_socket(); /* now that we have a raw socket we can drop root */ /* xsetuid(getuid()); - but save on code size... */ /* look up the dest mac address */ get_dest_addr(argv[optind], &eaddr); /* fill out the header of the packet */ pktsize = get_fill(outpack, &eaddr, flags /* & 1 OPT_BROADCAST */); bb_debug_dump_packet(outpack, pktsize); /* Fill in the source address, if possible. */ #ifdef __linux__ { struct ifreq if_hwaddr; strncpy_IFNAMSIZ(if_hwaddr.ifr_name, ifname); ioctl_or_perror_and_die(s, SIOCGIFHWADDR, &if_hwaddr, "SIOCGIFHWADDR on %s failed", ifname); memcpy(outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6); # ifdef DEBUG { unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data; printf("The hardware address (SIOCGIFHWADDR) of %s is type %d " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n\n", ifname, if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); } # endif } #endif /* __linux__ */ bb_debug_dump_packet(outpack, pktsize); /* append the password if specified */ if (wol_passwd_sz > 0) { memcpy(outpack+pktsize, wol_passwd, wol_passwd_sz); pktsize += wol_passwd_sz; } bb_debug_dump_packet(outpack, pktsize); /* This is necessary for broadcasts to work */ if (flags /* & 1 OPT_BROADCAST */) { if (setsockopt_broadcast(s) != 0) bb_perror_msg("SO_BROADCAST"); } #if defined(PF_PACKET) { struct ifreq ifr; strncpy_IFNAMSIZ(ifr.ifr_name, ifname); xioctl(s, SIOCGIFINDEX, &ifr); memset(&whereto, 0, sizeof(whereto)); whereto.sll_family = AF_PACKET; whereto.sll_ifindex = ifr.ifr_ifindex; /* The manual page incorrectly claims the address must be filled. We do so because the code may change to match the docs. */ whereto.sll_halen = ETH_ALEN; memcpy(whereto.sll_addr, outpack, ETH_ALEN); } #else whereto.sa_family = 0; strcpy(whereto.sa_data, ifname); #endif xsendto(s, outpack, pktsize, (struct sockaddr *)&whereto, sizeof(whereto)); if (ENABLE_FEATURE_CLEAN_UP) close(s); return EXIT_SUCCESS; }
/* Size reducing helpers for xxx_check_funcs(). */ static void get_funcs_matrix(int fd, unsigned long *funcs) { ioctl_or_perror_and_die(fd, I2C_FUNCS, funcs, "can't get adapter functionality matrix"); }
static void i2c_set_slave_addr(int fd, int addr, int force) { ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE, itoptr(addr), "can't set address to 0x%02x", addr); }
int nameif_main(int argc, char **argv) { mactable_t *clist = NULL; FILE *ifh; const char *fname = "/etc/mactab"; char *line; int ctl_sk; int if_index = 1; mactable_t *ch; if (1 & getopt32(argv, "sc:", &fname)) { openlog(applet_name, 0, LOG_LOCAL0); logmode = LOGMODE_SYSLOG; } if ((argc - optind) & 1) bb_show_usage(); if (optind < argc) { char **a = argv + optind; while (*a) { if (strlen(*a) > IF_NAMESIZE) bb_error_msg_and_die("interface name '%s' " "too long", *a); ch = xzalloc(sizeof(mactable_t)); ch->ifname = xstrdup(*a++); ch->mac = cc_macaddr(*a++); if (clist) clist->prev = ch; ch->next = clist; clist = ch; } } else { ifh = xfopen(fname, "r"); while ((line = xmalloc_fgets(ifh)) != NULL) { char *line_ptr; size_t name_length; line_ptr = line + strspn(line, " \t"); if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) { free(line); continue; } name_length = strcspn(line_ptr, " \t"); ch = xzalloc(sizeof(mactable_t)); ch->ifname = xstrndup(line_ptr, name_length); if (name_length > IF_NAMESIZE) bb_error_msg_and_die("interface name '%s' " "too long", ch->ifname); line_ptr += name_length; line_ptr += strspn(line_ptr, " \t"); name_length = strspn(line_ptr, "0123456789ABCDEFabcdef:"); line_ptr[name_length] = '\0'; ch->mac = cc_macaddr(line_ptr); if (clist) clist->prev = ch; ch->next = clist; clist = ch; free(line); } fclose(ifh); } ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); while (clist) { struct ifreq ifr; memset(&ifr, 0, sizeof(struct ifreq)); if_index++; ifr.ifr_ifindex = if_index; /* Get ifname by index or die */ if (ioctl(ctl_sk, SIOCGIFNAME, &ifr)) break; /* Has this device hwaddr? */ if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr)) continue; /* Search for mac like in ifr.ifr_hwaddr.sa_data */ for (ch = clist; ch; ch = ch->next) if (!memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN)) break; /* Nothing found for current ifr.ifr_hwaddr.sa_data */ if (ch == NULL) continue; strcpy(ifr.ifr_newname, ch->ifname); ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr, "cannot change ifname %s to %s", ifr.ifr_name, ch->ifname); /* Remove list entry of renamed interface */ if (ch->prev != NULL) { (ch->prev)->next = ch->next; } else { clist = ch->next; } if (ch->next != NULL) (ch->next)->prev = ch->prev; if (ENABLE_FEATURE_CLEAN_UP) { free(ch->ifname); free(ch->mac); free(ch); } } return 0; }
int nameif_main(int argc UNUSED_PARAM, char **argv) { ethtable_t *clist = NULL; const char *fname = "/etc/mactab"; int ctl_sk; ethtable_t *ch; parser_t *parser; char *token[2]; if (1 & getopt32(argv, "sc:", &fname)) { openlog(applet_name, 0, LOG_LOCAL0); /* Why not just "="? I assume logging to stderr * can't hurt. 2>/dev/null if you don't like it: */ logmode |= LOGMODE_SYSLOG; } argv += optind; if (argv[0]) { do { if (!argv[1]) bb_show_usage(); prepend_new_eth_table(&clist, argv[0], argv[1]); argv += 2; } while (*argv); } else { parser = config_open(fname); while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) prepend_new_eth_table(&clist, token[0], token[1]); config_close(parser); } ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); parser = config_open2("/proc/net/dev", xfopen_for_read); while (clist && config_read(parser, token, 2, 2, "\0: \t", PARSE_NORMAL)) { struct ifreq ifr; #if ENABLE_FEATURE_NAMEIF_EXTENDED struct ethtool_drvinfo drvinfo; struct ethtool_cmd eth_settings; #endif if (parser->lineno <= 2) continue; /* Skip the first two lines */ /* Find the current interface name and copy it to ifr.ifr_name */ memset(&ifr, 0, sizeof(struct ifreq)); strncpy_IFNAMSIZ(ifr.ifr_name, token[0]); #if ENABLE_FEATURE_NAMEIF_EXTENDED /* Check for phy address */ memset(ð_settings, 0, sizeof(eth_settings)); eth_settings.cmd = ETHTOOL_GSET; ifr.ifr_data = (caddr_t) ð_settings; ioctl(ctl_sk, SIOCETHTOOL, &ifr); /* Check for driver etc. */ memset(&drvinfo, 0, sizeof(drvinfo)); drvinfo.cmd = ETHTOOL_GDRVINFO; ifr.ifr_data = (caddr_t) &drvinfo; /* Get driver and businfo first, so we have it in drvinfo */ ioctl(ctl_sk, SIOCETHTOOL, &ifr); #endif ioctl(ctl_sk, SIOCGIFHWADDR, &ifr); /* Search the list for a matching device */ for (ch = clist; ch; ch = ch->next) { #if ENABLE_FEATURE_NAMEIF_EXTENDED if (ch->bus_info && strcmp(ch->bus_info, drvinfo.bus_info) != 0) continue; if (ch->driver && strcmp(ch->driver, drvinfo.driver) != 0) continue; if (ch->phy_address != -1 && ch->phy_address != eth_settings.phy_address) continue; #endif if (ch->mac && memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != 0) continue; /* if we came here, all selectors have matched */ break; } /* Nothing found for current interface */ if (!ch) continue; if (strcmp(ifr.ifr_name, ch->ifname) != 0) { strcpy(ifr.ifr_newname, ch->ifname); ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr, "can't change ifname %s to %s", ifr.ifr_name, ch->ifname); } /* Remove list entry of renamed interface */ if (ch->prev != NULL) ch->prev->next = ch->next; else clist = ch->next; if (ch->next != NULL) ch->next->prev = ch->prev; if (ENABLE_FEATURE_CLEAN_UP) delete_eth_table(ch); } if (ENABLE_FEATURE_CLEAN_UP) { for (ch = clist; ch; ch = ch->next) delete_eth_table(ch); config_close(parser); }; return 0; }
static void i2c_set_pec(int fd, int pec) { ioctl_or_perror_and_die(fd, I2C_PEC, itoptr(pec ? 1 : 0), "can't set PEC"); }
int brctl_main(int argc UNUSED_PARAM, char **argv) { static const char keywords[] ALIGN1 = "addbr\0" "delbr\0" "addif\0" "delif\0" IF_FEATURE_BRCTL_FANCY( "stp\0" "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setpathcost\0" "setportprio\0" "setbridgeprio\0" ) IF_FEATURE_BRCTL_SHOW("show\0"); enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif IF_FEATURE_BRCTL_FANCY(, ARG_stp, ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio ) IF_FEATURE_BRCTL_SHOW(, ARG_show) }; int fd; smallint key; struct ifreq ifr; char *br, *brif; argv++; while (*argv) { #if ENABLE_FEATURE_BRCTL_FANCY int ifidx[MAX_PORTS]; unsigned long args[4]; ifr.ifr_data = (char *) &args; #endif key = index_in_strings(keywords, *argv); if (key == -1) /* no match found in keywords array, bail out. */ bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); argv++; fd = xsocket(AF_INET, SOCK_STREAM, 0); #if ENABLE_FEATURE_BRCTL_SHOW if (key == ARG_show) { /* show */ char brname[IFNAMSIZ]; int bridx[MAX_PORTS]; int i, num; arm_ioctl(args, BRCTL_GET_BRIDGES, (unsigned long) bridx, MAX_PORTS); num = xioctl(fd, SIOCGIFBR, args); puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); for (i = 0; i < num; i++) { char ifname[IFNAMSIZ]; int j, tabs; struct __bridge_info bi; unsigned char *x; if (!if_indextoname(bridx[i], brname)) bb_perror_msg_and_die("can't get bridge name for index %d", i); strncpy_IFNAMSIZ(ifr.ifr_name, brname); arm_ioctl(args, BRCTL_GET_BRIDGE_INFO, (unsigned long) &bi, 0); xioctl(fd, SIOCDEVPRIVATE, &ifr); printf("%s\t\t", brname); /* print bridge id */ x = (unsigned char *) &bi.bridge_id; for (j = 0; j < 8; j++) { printf("%02x", x[j]); if (j == 1) bb_putchar('.'); } printf(bi.stp_enabled ? "\tyes" : "\tno"); /* print interface list */ arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long) ifidx, MAX_PORTS); xioctl(fd, SIOCDEVPRIVATE, &ifr); tabs = 0; for (j = 0; j < MAX_PORTS; j++) { if (!ifidx[j]) continue; if (!if_indextoname(ifidx[j], ifname)) bb_perror_msg_and_die("can't get interface name for index %d", j); if (tabs) printf("\t\t\t\t\t"); else tabs = 1; printf("\t\t%s\n", ifname); } if (!tabs) /* bridge has no interfaces */ bb_putchar('\n'); } goto done; } #endif if (!*argv) /* all but 'show' need at least one argument */ bb_show_usage(); br = *argv++; if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */ ioctl_or_perror_and_die(fd, key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, br, "bridge %s", br); goto done; } if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ bb_show_usage(); strncpy_IFNAMSIZ(ifr.ifr_name, br); if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ brif = *argv; ifr.ifr_ifindex = if_nametoindex(brif); if (!ifr.ifr_ifindex) { bb_perror_msg_and_die("iface %s", brif); } ioctl_or_perror_and_die(fd, key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, &ifr, "bridge %s", br); goto done_next_argv; } #if ENABLE_FEATURE_BRCTL_FANCY if (key == ARG_stp) { /* stp */ static const char no_yes[] ALIGN1 = "0\0" "off\0" "n\0" "no\0" /* 0 .. 3 */ "1\0" "on\0" "y\0" "yes\0"; /* 4 .. 7 */ int onoff = index_in_strings(no_yes, *argv); if (onoff < 0) bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, applet_name); onoff = (unsigned)onoff / 4; arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, onoff, 0); goto fire; } if ((unsigned)(key - ARG_setageing) < 4) { /* time related ops */ static const uint8_t ops[] ALIGN1 = { BRCTL_SET_AGEING_TIME, /* ARG_setageing */ BRCTL_SET_BRIDGE_FORWARD_DELAY, /* ARG_setfd */ BRCTL_SET_BRIDGE_HELLO_TIME, /* ARG_sethello */ BRCTL_SET_BRIDGE_MAX_AGE /* ARG_setmaxage */ }; arm_ioctl(args, ops[key - ARG_setageing], str_to_jiffies(*argv), 0); goto fire; } if (key == ARG_setpathcost || key == ARG_setportprio || key == ARG_setbridgeprio ) { static const uint8_t ops[] ALIGN1 = { BRCTL_SET_PATH_COST, /* ARG_setpathcost */ BRCTL_SET_PORT_PRIORITY, /* ARG_setportprio */ BRCTL_SET_BRIDGE_PRIORITY /* ARG_setbridgeprio */ }; int port = -1; unsigned arg1, arg2; if (key != ARG_setbridgeprio) { /* get portnum */ unsigned i; port = if_nametoindex(*argv++); if (!port) bb_error_msg_and_die(bb_msg_invalid_arg_to, *argv, "port"); memset(ifidx, 0, sizeof ifidx); arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx, MAX_PORTS); xioctl(fd, SIOCDEVPRIVATE, &ifr); for (i = 0; i < MAX_PORTS; i++) { if (ifidx[i] == port) { port = i; break; } } } arg1 = port; arg2 = xatoi_positive(*argv); if (key == ARG_setbridgeprio) { arg1 = arg2; arg2 = 0; } arm_ioctl(args, ops[key - ARG_setpathcost], arg1, arg2); } fire: /* Execute the previously set command */ xioctl(fd, SIOCDEVPRIVATE, &ifr); #endif done_next_argv: argv++; done: close(fd); } return EXIT_SUCCESS; }
int brctl_main(int argc ATTRIBUTE_UNUSED, char **argv) { static const char keywords[] ALIGN1 = "addbr\0" "delbr\0" "addif\0" "delif\0" USE_FEATURE_BRCTL_FANCY( "stp\0" "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setpathcost\0" "setportprio\0" "setbridgeprio\0" ) USE_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif USE_FEATURE_BRCTL_FANCY(, ARG_stp, ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio ) USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) }; int fd; smallint key; struct ifreq ifr; char *br, *brif; #if ENABLE_FEATURE_BRCTL_FANCY unsigned long args[4] = {0, 0, 0, 0}; int port; int tmp; #endif argv++; while (*argv) { key = index_in_strings(keywords, *argv); if (key == -1) /* no match found in keywords array, bail out. */ bb_error_msg_and_die(bb_msg_invalid_arg, *argv, applet_name); argv++; #if ENABLE_FEATURE_BRCTL_SHOW if (key == ARG_show) { /* show */ goto out; /* FIXME: implement me! :) */ } #endif fd = xsocket(AF_INET, SOCK_STREAM, 0); br = *argv++; if (key == ARG_addbr || key == ARG_delbr) { /* addbr or delbr */ ioctl_or_perror_and_die(fd, key == ARG_addbr ? SIOCBRADDBR : SIOCBRDELBR, br, "bridge %s", br); goto done; } if (!*argv) /* all but 'show' need at least one argument */ bb_show_usage(); safe_strncpy(ifr.ifr_name, br, IFNAMSIZ); if (key == ARG_addif || key == ARG_delif) { /* addif or delif */ brif = *argv++; ifr.ifr_ifindex = if_nametoindex(brif); if (!ifr.ifr_ifindex) { bb_perror_msg_and_die("iface %s", brif); } ioctl_or_perror_and_die(fd, key == ARG_addif ? SIOCBRADDIF : SIOCBRDELIF, &ifr, "bridge %s", br); goto done; } #if ENABLE_FEATURE_BRCTL_FANCY ifr.ifr_data = (char *) &args; if (key == ARG_stp) { /* stp */ /* FIXME: parsing yes/y/on/1 versus no/n/off/0 is too involved */ arm_ioctl(args, BRCTL_SET_BRIDGE_STP_STATE, (unsigned)(**argv - '0'), 0); goto fire; } if ((unsigned)(key - ARG_stp) < 5) { /* time related ops */ unsigned long op = (key == ARG_setageing) ? BRCTL_SET_AGEING_TIME : (key == ARG_setfd) ? BRCTL_SET_BRIDGE_FORWARD_DELAY : (key == ARG_sethello) ? BRCTL_SET_BRIDGE_HELLO_TIME : /*key == ARG_setmaxage*/ BRCTL_SET_BRIDGE_MAX_AGE; arm_ioctl(args, op, str_to_jiffies(*argv), 0); goto fire; } port = -1; if (key == ARG_setpathcost || key == ARG_setportprio) {/* get portnum */ int ifidx[MAX_PORTS]; unsigned i; port = if_nametoindex(*argv); if (!port) bb_error_msg_and_die(bb_msg_invalid_arg, *argv, "port"); argv++; memset(ifidx, 0, sizeof ifidx); arm_ioctl(args, BRCTL_GET_PORT_LIST, (unsigned long)ifidx, MAX_PORTS); xioctl(fd, SIOCDEVPRIVATE, &ifr); for (i = 0; i < MAX_PORTS; i++) { if (ifidx[i] == port) { port = i; break; } } } if (key == ARG_setpathcost || key == ARG_setportprio || key == ARG_setbridgeprio ) { unsigned long op = (key == ARG_setpathcost) ? BRCTL_SET_PATH_COST : (key == ARG_setportprio) ? BRCTL_SET_PORT_PRIORITY : /*key == ARG_setbridgeprio*/ BRCTL_SET_BRIDGE_PRIORITY; unsigned long arg1 = port; unsigned long arg2; # if BRCTL_USE_INTERNAL tmp = xatoi(*argv); # else if (sscanf(*argv, "%i", &tmp) != 1) bb_error_msg_and_die(bb_msg_invalid_arg, *argv, key == ARG_setpathcost ? "cost" : "prio"); # endif if (key == ARG_setbridgeprio) { arg1 = tmp; arg2 = 0; } else arg2 = tmp; arm_ioctl(args, op, arg1, arg2); } fire: /* Execute the previously set command. */ xioctl(fd, SIOCDEVPRIVATE, &ifr); argv++; #endif done: if (ENABLE_FEATURE_CLEAN_UP) close(fd); } USE_FEATURE_BRCTL_SHOW(out:) return EXIT_SUCCESS; }