Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
/* 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));
	}
}
Ejemplo n.º 9
0
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);
	}
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
/* 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");
}
Ejemplo n.º 13
0
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);
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
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(&eth_settings, 0, sizeof(eth_settings));
		eth_settings.cmd = ETHTOOL_GSET;
		ifr.ifr_data = (caddr_t) &eth_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;
}
Ejemplo n.º 16
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");
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
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;
}