Ejemplo n.º 1
0
/* gdb_input: Handles user input to the GDB window.
 * ----------
 *
 *   key:  Keystroke received.
 *
 * Return Value:    0 if internal key was used, 
 *                  1 if input to gdb or ...
 *                  -1        : Error resizing terminal -- terminal too small
 */
static int gdb_input(int key)
{
    /* Handle special keys */
    switch (key) {
        case CGDB_KEY_PPAGE:
            scr_up(gdb_win, get_gdb_height() - 1);
            break;
        case CGDB_KEY_NPAGE:
            scr_down(gdb_win, get_gdb_height() - 1);
            break;
        case CGDB_KEY_F11:
            scr_home(gdb_win);
            break;
        case CGDB_KEY_F12:
            scr_end(gdb_win);
            break;
#if 0
            /* I would like to add better support for control-l in the GDB
             * window, but this patch didn't make me happy enough to release it.
             * The problem is, when it clears the screen, it adds a lot of 
             * whitespace in the buffer. If you hit page-up to look back in
             * the buffer, it's visible. This is really unacceptable.
             *
             * The approach I believe I would like to take with this, is to
             * have the GDB window behave more like the terminal. That is,
             * have GDB start at the top line, and move down as input 
             * becomes available. Then, when you hit ctrl-l, you just move
             * the prompt to the top line. */
        case CGDB_KEY_CTRL_L:
        {
            int height = get_gdb_height(), i;

            /* Allocate and print enough newlines to clear the gdb buffer. */
            char *buf = (char *) cgdb_malloc(sizeof (char *) * height);

            for (i = 0; i < height - 1; ++i) {
                buf[i] = '\n';
            }
            buf[i] = '\0';
            if_print(buf);
            free(buf);

            /* Sneaky return 1 here. Basically, this allows tricks readline to think
             * that gdb did not handle the Ctrl-l. That way readline will also handle
             * it. Because readline uses TERM=dumb, that means that it will clear a 
             * single line and put out the prompt. */
            return 1;
            break;
        }
#endif
        default:
            return 1;
    }

    if_draw();

    return 0;
}
Ejemplo n.º 2
0
int if_clear_line()
{
    std::string line;

    line.push_back('\r');
    line.append(get_gdb_width(), ' ');
    line.push_back('\r');

    if_print(line.c_str());

    return 0;
}
Ejemplo n.º 3
0
void if_print_message(const char *fmt, ...)
{
    va_list ap;
    char va_buf[MAXLINE];

    /* Get the buffer with format */
    va_start(ap, fmt);
#ifdef   HAVE_VSNPRINTF
    vsnprintf(va_buf, sizeof (va_buf), fmt, ap);    /* this is safe */
#else
    vsprintf(va_buf, fmt, ap);  /* this is not safe */
#endif
    va_end(ap);

    if_print(va_buf);
}
Ejemplo n.º 4
0
int if_clear_line()
{
    int width = get_gdb_width();
    int i;
    char line[width + 3];

    line[0] = '\r';

    for (i = 1; i <= width; ++i)
        line[i] = ' ';

    line[i] = '\r';
    line[i + 1] = '\0';

    if_print(line);

    return 0;
}
Ejemplo n.º 5
0
void if_tty_print(const char *buf)
{
    /* If the tty I/O window is not open send output to gdb window */
    if (!tty_win_on)
        if_print(buf);

    /* Print it to the scroller */
    scr_add(tty_win, buf);

    /* Only need to redraw if tty_win is being displayed */
    if (tty_win_on && get_gdb_height() > 0) {
        scr_refresh(tty_win, focus == TTY);

        /* Make sure cursor reappears in source window if focus is there */
        if (focus == CGDB)
            wrefresh(src_win->win);
    }
}
Ejemplo n.º 6
0
Archivo: cgdb.c Proyecto: i4fumi/cgdb
static int readline_input()
{
    const int MAX = 1024;
    char *buf = malloc(MAX + 1);
    int size;

    int masterfd = pty_pair_get_masterfd(pty_pair);

    if (masterfd == -1) {
        logger_write_pos(logger, __FILE__, __LINE__,
                "pty_pair_get_masterfd error");
        return -1;
    }

    size = read(masterfd, buf, MAX);
    if (size == -1) {
        logger_write_pos(logger, __FILE__, __LINE__, "read error");
        free(buf);
        buf = NULL;
        return -1;
    }

    buf[size] = 0;

    /* Display GDB output 
     * The strlen check is here so that if_print does not get called
     * when displaying the filedlg. If it does get called, then the 
     * gdb window gets displayed when the filedlg is up
     */
    if (size > 0)
        if_print(buf);

    free(buf);
    buf = NULL;
    return 0;
}
Ejemplo n.º 7
0
int main(int argc, char **argv)
{
    struct sockaddr sa;
    char host[128];
    struct aftype *ap;
    struct hwtype *hw;
    struct ifreq ifr;
    int goterr = 0, didnetmask = 0;
    char **spp;
    int fd;
#if HAVE_AFINET6
    extern struct aftype inet6_aftype;
    struct sockaddr_in6 sa6;
    struct in6_ifreq ifr6;
    unsigned long prefix_len;
    char *cp;
#endif

#if I18N
    bindtextdomain("net-tools", "/usr/share/locale");
    textdomain("net-tools");
#endif

    /* Create a channel to the NET kernel. */
    if ((skfd = sockets_open(0)) < 0) {
	perror("socket");
	exit(1);
    }

    /* Find any options. */
    argc--;
    argv++;
    while (argc && *argv[0] == '-') {
	if (!strcmp(*argv, "-a"))
	    opt_a = 1;

	if (!strcmp(*argv, "-v"))
	    opt_v = 1;

	if (!strcmp(*argv, "-V") || !strcmp(*argv, "-version") ||
	    !strcmp(*argv, "--version"))
	    version();

	if (!strcmp(*argv, "-?") || !strcmp(*argv, "-h") ||
	    !strcmp(*argv, "-help") || !strcmp(*argv, "--help"))
	    usage();

	argv++;
	argc--;
    }

    /* Do we have to show the current setup? */
    if (argc == 0) {
	int err = if_print((char *) NULL);
	(void) close(skfd);
	exit(err < 0);
    }
    /* No. Fetch the interface name. */
    spp = argv;
    safe_strncpy(ifr.ifr_name, *spp++, IFNAMSIZ);
    if (*spp == (char *) NULL) {
	int err = if_print(ifr.ifr_name);
	(void) close(skfd);
	exit(err < 0);
    }

	/* setup the vlan if required */
	if (if_name_is_vlan(ifr.ifr_name)) {
		struct interface *i;
		if ((i = lookup_interface(ifr.ifr_name)) == NULL) {
			fprintf (stderr, "Couldn't lookup interfaces\n");
			exit(1);
		}
		if (do_if_fetch(i) < 0) {
			int err;
			printf("Creating new vlan\n");
			err = setup_vlan(ifr.ifr_name);
			if (err < 0) {
				fprintf(stderr, "Cannot init required vlan %s - %d\n",
					ifr.ifr_name, err);
				exit(err < 0);
			}
		}
	}


    /* The next argument is either an address family name, or an option. */
    if ((ap = get_aftype(*spp)) == NULL)
	ap = get_aftype(DFLT_AF);
    else {
	/* XXX: should print the current setup if no args left, but only 
	   for this family */
	spp++;
	addr_family = ap->af;
    }

    if (sockets_open(addr_family) < 0) {
	perror("family socket");
	exit(1);
    }
    /* Process the remaining arguments. */
    while (*spp != (char *) NULL) {
	if (!strcmp(*spp, "arp")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_NOARP);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-arp")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_NOARP);
	    spp++;
	    continue;
	}
#ifdef IFF_PORTSEL
	if (!strcmp(*spp, "media") || !strcmp(*spp, "port")) {
	    if (*++spp == NULL)
		usage();
	    if (!strcasecmp(*spp, "auto")) {
		goterr |= set_flag(ifr.ifr_name, IFF_AUTOMEDIA);
	    } else {
		int i, j, newport;
		char *endp;
		newport = strtol(*spp, &endp, 10);
		if (*endp != 0) {
		    newport = -1;
		    for (i = 0; if_port_text[i][0] && newport == -1; i++) {
			for (j = 0; if_port_text[i][j]; j++) {
			    if (!strcasecmp(*spp, if_port_text[i][j])) {
				newport = i;
				break;
			    }
			}
		    }
		}
		spp++;
		if (newport == -1) {
		    fprintf(stderr, _("Unknown media type.\n"));
		    goterr = 1;
		} else {
		    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
			goterr = 1;
			continue;
		    }
		    ifr.ifr_map.port = newport;
		    if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
			perror("SIOCSIFMAP");
			goterr = 1;
		    }
		}
	    }
	    continue;
	}
#endif

	if (!strcmp(*spp, "trailers")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-trailers")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "promisc")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_PROMISC);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-promisc")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "multicast")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-multicast")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "allmulti")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-allmulti")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "up")) {
	    goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "down")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_UP);
	    spp++;
	    continue;
	}
#ifdef HAVE_DYNAMIC
	if (!strcmp(*spp, "dynamic")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_DYNAMIC);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-dynamic")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_DYNAMIC);
	    spp++;
	    continue;
	}
#endif

	if (!strcmp(*spp, "metric")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_metric = atoi(*spp);
	    if (ioctl(skfd, SIOCSIFMETRIC, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "mtu")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_mtu = atoi(*spp);
	    if (ioctl(skfd, SIOCSIFMTU, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#ifdef SIOCSKEEPALIVE
	if (!strcmp(*spp, "keepalive")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_data = (caddr_t) atoi(*spp);
	    if (ioctl(skfd, SIOCSKEEPALIVE, &ifr) < 0) {
		fprintf(stderr, "SIOCSKEEPALIVE: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#endif

#ifdef SIOCSOUTFILL
	if (!strcmp(*spp, "outfill")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_data = (caddr_t) atoi(*spp);
	    if (ioctl(skfd, SIOCSOUTFILL, &ifr) < 0) {
		fprintf(stderr, "SIOCSOUTFILL: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#endif

	if (!strcmp(*spp, "-broadcast")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "broadcast")) {
	    if (*++spp != NULL) {
		safe_strncpy(host, *spp, (sizeof host));
		if (ap->input(0, host, &sa) < 0) {
		    ap->herror(host);
		    goterr = 1;
		    spp++;
		    continue;
		}
		memcpy((char *) &ifr.ifr_broadaddr, (char *) &sa,
		       sizeof(struct sockaddr));
		if (ioctl(ap->fd, SIOCSIFBRDADDR, &ifr) < 0) {
		    fprintf(stderr, "SIOCSIFBRDADDR: %s\n",
			    strerror(errno));
		    goterr = 1;
		}
		spp++;
	    }
	    goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST);
	    continue;
	}
	if (!strcmp(*spp, "dstaddr")) {
	    if (*++spp == NULL)
		usage();
	    safe_strncpy(host, *spp, (sizeof host));
	    if (ap->input(0, host, &sa) < 0) {
		ap->herror(host);
		goterr = 1;
		spp++;
		continue;
	    }
	    memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
		   sizeof(struct sockaddr));
	    if (ioctl(ap->fd, SIOCSIFDSTADDR, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
			strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "netmask")) {
	    if (*++spp == NULL || didnetmask)
		usage();
	    safe_strncpy(host, *spp, (sizeof host));
	    if (ap->input(0, host, &sa) < 0) {
		ap->herror(host);
		goterr = 1;
		spp++;
		continue;
	    }
	    didnetmask++;
	    goterr = set_netmask(ap->fd, &ifr, &sa);
	    spp++;
	    continue;
	}
#ifdef HAVE_TXQUEUELEN
	if (!strcmp(*spp, "txqueuelen")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_qlen = strtoul(*spp, NULL, 0);
	    if (ioctl(skfd, SIOCSIFTXQLEN, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFTXQLEN: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#endif

	if (!strcmp(*spp, "mem_start")) {
	    if (*++spp == NULL)
		usage();
	    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
		goterr = 1;
		continue;
	    }
	    ifr.ifr_map.mem_start = strtoul(*spp, NULL, 0);
	    if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "io_addr")) {
	    if (*++spp == NULL)
		usage();
	    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
		goterr = 1;
		continue;
	    }
	    ifr.ifr_map.base_addr = strtol(*spp, NULL, 0);
	    if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "irq")) {
	    if (*++spp == NULL)
		usage();
	    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
		goterr = 1;
		continue;
	    }
	    ifr.ifr_map.irq = atoi(*spp);
	    if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-pointopoint")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "pointopoint")) {
	    if (*(spp + 1) != NULL) {
		spp++;
		safe_strncpy(host, *spp, (sizeof host));
		if (ap->input(0, host, &sa)) {
		    ap->herror(host);
		    goterr = 1;
		    spp++;
		    continue;
		}
		memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
		       sizeof(struct sockaddr));
		if (ioctl(ap->fd, SIOCSIFDSTADDR, &ifr) < 0) {
		    fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
			    strerror(errno));
		    goterr = 1;
		}
	    }
	    goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT);
	    spp++;
	    continue;
	};

	if (!strcmp(*spp, "hw")) {
	    if (*++spp == NULL)
		usage();
	    if ((hw = get_hwtype(*spp)) == NULL)
		usage();
	    if (*++spp == NULL)
		usage();
	    safe_strncpy(host, *spp, (sizeof host));
	    if (hw->input(host, &sa) < 0) {
		fprintf(stderr, _("%s: invalid %s address.\n"), host, hw->name);
		goterr = 1;
		spp++;
		continue;
	    }
	    memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa,
		   sizeof(struct sockaddr));
	    if (ioctl(skfd, SIOCSIFHWADDR, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFHWADDR: %s\n",
			strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#if HAVE_AFINET6
	if (!strcmp(*spp, "add")) {
	    if (*++spp == NULL)
		usage();
	    if ((cp = strchr(*spp, '/'))) {
		prefix_len = atol(cp + 1);
		if ((prefix_len < 0) || (prefix_len > 128))
		    usage();
		*cp = 0;
	    } else {
		prefix_len = 0;
	    }
	    safe_strncpy(host, *spp, (sizeof host));
	    if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) {
		inet6_aftype.herror(host);
		goterr = 1;
		spp++;
		continue;
	    }
	    memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
		   sizeof(struct in6_addr));

	    fd = get_socket_for_af(AF_INET6);
	    if (fd < 0) {
		fprintf(stderr, _("No support for INET6 on this system.\n"));
		goterr = 1;
		spp++;
		continue;
	    }
	    if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
		perror("SIOGIFINDEX");
		goterr = 1;
		spp++;
		continue;
	    }
	    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
	    ifr6.ifr6_prefixlen = prefix_len;
	    if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) {
		perror("SIOCSIFADDR");
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "del")) {
	    if (*++spp == NULL)
		usage();
	    if ((cp = strchr(*spp, '/'))) {
		prefix_len = atol(cp + 1);
		if ((prefix_len < 0) || (prefix_len > 128))
		    usage();
		*cp = 0;
	    } else {
		prefix_len = 0;
	    }
	    safe_strncpy(host, *spp, (sizeof host));
	    if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) {
		inet6_aftype.herror(host);
		goterr = 1;
		spp++;
		continue;
	    }
	    memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
		   sizeof(struct in6_addr));

	    fd = get_socket_for_af(AF_INET6);
	    if (fd < 0) {
		fprintf(stderr, _("No support for INET6 on this system.\n"));
		goterr = 1;
		spp++;
		continue;
	    }
	    if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
		perror("SIOGIFINDEX");
		goterr = 1;
		spp++;
		continue;
	    }
	    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
	    ifr6.ifr6_prefixlen = prefix_len;
#ifdef SIOCDIFADDR
	    if (ioctl(fd, SIOCDIFADDR, &ifr6) < 0) {
		fprintf(stderr, "SIOCDIFADDR: %s\n",
			strerror(errno));
		goterr = 1;
	    }
#else
	    fprintf(stderr, _("Address deletion not supported on this system.\n"));
#endif
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "tunnel")) {
	    if (*++spp == NULL)
		usage();
	    if ((cp = strchr(*spp, '/'))) {
		prefix_len = atol(cp + 1);
		if ((prefix_len < 0) || (prefix_len > 128))
		    usage();
		*cp = 0;
	    } else {
		prefix_len = 0;
	    }
	    safe_strncpy(host, *spp, (sizeof host));
	    if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) {
		inet6_aftype.herror(host);
		goterr = 1;
		spp++;
		continue;
	    }
	    memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
		   sizeof(struct in6_addr));

	    fd = get_socket_for_af(AF_INET6);
	    if (fd < 0) {
		fprintf(stderr, _("No support for INET6 on this system.\n"));
		goterr = 1;
		spp++;
		continue;
	    }
	    if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
		perror("SIOGIFINDEX");
		goterr = 1;
		spp++;
		continue;
	    }
	    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
	    ifr6.ifr6_prefixlen = prefix_len;

	    if (ioctl(fd, SIOCSIFDSTADDR, &ifr6) < 0) {
		fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
			strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#endif

	/* If the next argument is a valid hostname, assume OK. */
	safe_strncpy(host, *spp, (sizeof host));

	/* FIXME: sa is too small for INET6 addresses, inet6 should use that too, 
	   broadcast is unexpected */
	if (ap->getmask) {
	    switch (ap->getmask(host, &sa, NULL)) {
	    case -1:
		usage();
		break;
	    case 1:
		if (didnetmask)
		    usage();

		goterr = set_netmask(skfd, &ifr, &sa);
		didnetmask++;
		break;
	    }
	}
	if (ap->input(0, host, &sa) < 0) {
	    ap->herror(host);
	    usage();
	}
	memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr));
	{
	    int r = 0;		/* to shut gcc up */
	    switch (ap->af) {
#if HAVE_AFINET
	    case AF_INET:
		fd = get_socket_for_af(AF_INET);
		if (fd < 0) {
		    fprintf(stderr, _("No support for INET on this system.\n"));
		    exit(1);
		}
		r = ioctl(fd, SIOCSIFADDR, &ifr);
		break;
#endif
#if HAVE_AFECONET
	    case AF_ECONET:
		fd = get_socket_for_af(AF_ECONET);
		if (fd < 0) {
		    fprintf(stderr, _("No support for ECONET on this system.\n"));
		    exit(1);
		}
		r = ioctl(fd, SIOCSIFADDR, &ifr);
		break;
#endif
	    default:
		fprintf(stderr,
		_("Don't know how to set addresses for family %d.\n"), ap->af);
		exit(1);
	    }
	    if (r < 0) {
		perror("SIOCSIFADDR");
		goterr = 1;
	    }
	}
       /*
        * Don't do the set_flag() if the address is an alias with a - at the
        * end, since it's deleted already! - Roman
        *
        * Should really use regex.h here, not sure though how well it'll go
        * with the cross-platform support etc. 
        */
        {
            char *ptr;
            short int found_colon = 0;
            for (ptr = ifr.ifr_name; *ptr; ptr++ )
                if (*ptr == ':') found_colon++;
                
            if (!(found_colon && *(ptr - 1) == '-'))
                goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
        }

	spp++;
    }

    return (goterr);
}
Ejemplo n.º 8
0
/*
 * returns interface list with detailed informations
 */
struct iface * if_list_get() {

    /*
     * Translating between Mac OS X internal representation of link and IP address
     * and Dibbler internal format.
     */
    struct ifaddrs *addrs_lst = NULL; // list returned by system
    struct ifaddrs *addr_ptr = NULL; // single address
    struct iface *iface_lst = NULL;  // interface list
    struct iface *iface_ptr = NULL;  // pointer to single interface

    if (getifaddrs(&addrs_lst) != 0) {
        perror("Error in getifaddrs: ");
        return iface_lst;
    }

    /* First pass through entire addrs_lst: collect unique interface names and flags */
    addr_ptr = addrs_lst;
    while (addr_ptr != NULL) {
        // check if this interface name is already on target list
        iface_ptr = iface_lst;
        while (iface_ptr!=NULL) {
            if (!strcmp(addr_ptr->ifa_name, iface_ptr->name))
                break;
            iface_ptr = iface_ptr->next;
        }
        if (!iface_ptr) { // interface with that name not found, let's add one!
            iface_ptr = malloc(sizeof(struct iface));
            memset(iface_ptr, 0, sizeof(struct iface));

            strncpy(iface_ptr->name, addr_ptr->ifa_name, MAX_IFNAME_LENGTH - 1);
	    iface_ptr->name[MAX_IFNAME_LENGTH-1] = 0;
            iface_ptr->id = if_nametoindex(iface_ptr->name);
            iface_ptr->flags = addr_ptr->ifa_flags;
#ifdef LOWLEVEL_DEBUG
            printf("Detected interface %s, ifindex=%d, flags=%d\n",
                   iface_ptr->name, iface_ptr->id, iface_ptr->flags);
#endif

            // add this new structure to the end of the interfaces list
            iface_lst = if_list_add(iface_lst, iface_ptr);
        }

        addr_ptr = addr_ptr->ifa_next;
    }

    /*
     * Second pass through addrs_lst: collect link and IP layer info for each interface
     * by name
     */

    // for each address...
    for (addr_ptr = addrs_lst; addr_ptr != NULL; addr_ptr = addr_ptr->ifa_next) {
        for (iface_ptr = iface_lst; iface_ptr != NULL; iface_ptr = iface_ptr->next) {
            // ... find its corresponding interface
            if (strncmp(iface_ptr->name, addr_ptr->ifa_name, strlen(addr_ptr->ifa_name)))
                continue;

            switch (addr_ptr->ifa_addr->sa_family)
                {
                case AF_INET6:
                    {
                        char * ptr = (char*)(&((struct sockaddr_in6 *) addr_ptr->ifa_addr)->sin6_addr);
                        if (ptr[0] == 0xfe && ptr[1] == 0x80) { // link-local IPv6 address
                            char * addrs = malloc( (iface_ptr->linkaddrcount+1)*16);
                            memcpy(addrs, iface_ptr->linkaddr, 16*iface_ptr->linkaddrcount);
                            memcpy(addrs + 16*iface_ptr->linkaddrcount, ptr, 16);
                            free(iface_ptr->linkaddr);
                            iface_ptr->linkaddr = addrs;
                            iface_ptr->linkaddrcount++;
                        } else { // this is global address
                            char * addrs = malloc( (iface_ptr->globaladdrcount+1)*16);
                            memcpy(addrs, iface_ptr->globaladdr, 16*iface_ptr->globaladdrcount);
                            memcpy(addrs + 16*iface_ptr->globaladdrcount, ptr, 16);
                            free(iface_ptr->globaladdr);
                            iface_ptr->globaladdr = addrs;
                            iface_ptr->globaladdrcount++;
                        }
                        break;
                    } // end of AF_INET6 handling
                case AF_LINK:
                    {
                        struct sockaddr_dl *linkInfo;
                        linkInfo = (struct sockaddr_dl *) addr_ptr->ifa_addr;

                        // Note: sdl_type is unsigned character; hardwareType is integer
                        iface_ptr->hardwareType = linkInfo->sdl_type;
                        if (linkInfo->sdl_alen > 1) {
                            memcpy(iface_ptr->mac, LLADDR(linkInfo),
                                   linkInfo->sdl_alen);
                            iface_ptr->maclen = linkInfo->sdl_alen;
                        }
                        break;
                    }
                default:
                    break; // ignore other address families
                }
        }
    }

    /* Print out iface_lst data if debug mode */
#ifdef LOWLEVEL_DEBUG
    iface_ptr = iface_lst;
    while (iface_ptr) {
        if_print(iface_ptr);
        iface_ptr = iface_ptr->next;
    }
#endif

    return iface_lst;
} /* end of if_list_get */
Ejemplo n.º 9
0
Archivo: cgdb.c Proyecto: i4fumi/cgdb
/**
 * The goal of this function is to display the tab completion information
 * to the user in an asychronous and potentially interactive manner.
 *
 * It will output to the screen as much as can be until user input is needed. 
 * If user input is needed, then this function must stop, and wait until 
 * that data has been recieved.
 *
 * If this function is called a second time with the same completion_ptr
 * parameter, it will continue outputting the tab completion data from
 * where it left off.
 *
 * \param completion_ptr
 * The tab completion data to output to the user
 *
 * \param key
 * The key the user wants to pass to the query command that was made.
 * If -1, then this is assummed to be the first time this function has been
 * called.
 *
 * \return
 * 0 on success or -1 on error
 */
static int handle_tab_completion_request(tab_completion_ptr comptr, int key)
{
    int query_items;
    int gdb_window_size;

    if (!comptr)
        return -1;

    query_items = rline_get_rl_completion_query_items(rline);
    gdb_window_size = get_gdb_height();

    if (comptr->state == TAB_COMPLETION_START) {
        if_print("\n");

        if (query_items > 0 && comptr->num_matches >= query_items) {
            if_print_message("Display all %d possibilities? (y or n)\n",
                    comptr->num_matches);
            comptr->state = TAB_COMPLETION_QUERY_POSSIBILITIES;
            return 0;
        }

        comptr->state = TAB_COMPLETION_COMPLETION_DISPLAY;
    }

    if (comptr->state == TAB_COMPLETION_QUERY_POSSIBILITIES) {
        int val = cgdb_get_y_or_n(key, 0);

        if (val == 1)
            comptr->state = TAB_COMPLETION_COMPLETION_DISPLAY;
        else if (val == 0)
            comptr->state = TAB_COMPLETION_DONE;
        else
            return 0;           /* stay at the same state */
    }

    if (comptr->state == TAB_COMPLETION_QUERY_PAGER) {
        int i = cgdb_get_y_or_n(key, 1);

        if_clear_line();        /* Clear the --More-- */
        if (i == 0)
            comptr->state = TAB_COMPLETION_DONE;
        else if (i == 2) {
            comptr->lines--;
            comptr->state = TAB_COMPLETION_COMPLETION_DISPLAY;
        } else {
            comptr->lines = 0;
            comptr->state = TAB_COMPLETION_COMPLETION_DISPLAY;
        }
    }

    if (comptr->state == TAB_COMPLETION_COMPLETION_DISPLAY) {
        for (; comptr->total <= comptr->num_matches; comptr->total++) {
            if_print(comptr->matches[comptr->total]);
            if_print("\n");

            comptr->lines++;
            if (comptr->lines >= (gdb_window_size - 1) &&
                    comptr->total < comptr->num_matches) {
                if_print("--More--");
                comptr->state = TAB_COMPLETION_QUERY_PAGER;
                comptr->total++;
                return 0;
            }
        }

        comptr->state = TAB_COMPLETION_DONE;
    }

    if (comptr->state == TAB_COMPLETION_DONE) {
        tab_completion_destroy(completion_ptr);
        completion_ptr = NULL;
        is_tab_completing = 0;
        rline_rl_forced_update_display(rline);
    }

    return 0;
}
Ejemplo n.º 10
0
Archivo: cgdb.c Proyecto: i4fumi/cgdb
/* gdb_input: Recieves data from tgdb:
 *
 *  Returns:  -1 on error, 0 on success
 */
static int gdb_input()
{
    char *buf = malloc(GDB_MAXBUF + 1);
    int size;
    int is_finished;

    /* Read from GDB */
    size = tgdb_process(tgdb, buf, GDB_MAXBUF, &is_finished);
    if (size == -1) {
        logger_write_pos(logger, __FILE__, __LINE__,
                "tgdb_recv_debugger_data error");
        free(buf);
        buf = NULL;
        return -1;
    }

    buf[size] = 0;

    process_commands(tgdb);

    /* Display GDB output 
     * The strlen check is here so that if_print does not get called
     * when displaying the filedlg. If it does get called, then the 
     * gdb window gets displayed when the filedlg is up
     */
    if (strlen(buf) > 0)
        if_print(buf);

    free(buf);
    buf = NULL;

    /* Check to see if GDB is ready to recieve another command. If it is, then
     * readline should redisplay what it currently contains. There are 2 special
     * case's here.
     *
     * If there are no commands in the queue to send to GDB then  readline 
     * should simply redisplay what it has currently in it's buffer.
     * rl_forced_update_display does this.
     *
     * However, if there are commands in the queue to send to GDB, that means
     * the user already entered these through readline. In that case, simply 
     * write the command entered through readline directly, instead of having
     * readline do it (readline already processed the data). This is important
     * also because rl_forced_update_display doesn't write the data right away.
     * It writes data to rl_outstream, and then the main_loop handles both the
     * readline data and the data from the TGDB command being sent. This could
     * result in a race condition.
     */
    if (is_finished) {
        int size;

        tgdb_queue_size(tgdb, &size);
        /* This is the second case, this command was queued. */
        if (size > 0) {
            struct tgdb_request *request = tgdb_queue_pop(tgdb);
            char *prompt;

            rline_get_prompt(rline, &prompt);
            if_print(prompt);

            if (request->header == TGDB_REQUEST_CONSOLE_COMMAND) {
                if_print(request->choice.console_command.command);
                if_print("\n");
            }

            last_request = request;
            tgdb_process_command(tgdb, request);
            /* This is the first case */
        }
      /** If the user is currently completing, do not update the prompt */
        else if (!completion_ptr) {
            int update = 1, ret_val;

            if (last_request) {
                ret_val =
                        does_request_require_console_update(last_request,
                        &update);
                if (ret_val == -1)
                    return -1;
                last_request = NULL;
            }

            if (update)
                rline_rl_forced_update_display(rline);
        }
    }

    return 0;
}
int
main(int argc, char **argv)
{
	struct ifreq  ifr2, if_hwaddr, if_ipaddr, if_metric, if_mtu, if_dstaddr;
	struct ifreq  if_netmask, if_brdaddr, if_flags;
	int rv, goterr = 0;
	int c, errflag = 0;
	sa_family_t master_family;
	char **spp, *master_ifname, *slave_ifname;
	int hwaddr_notset;
	int abi_ver = 0;

	while ((c = getopt_long(argc, argv, "acdfrvV?h", longopts, 0)) != EOF)
		switch (c) {
		case 'a': opt_a++; break;
		case 'f': opt_f++; break;
		case 'r': opt_r++; break;
		case 'd': opt_d++; break;
		case 'c': opt_c++; break;
		case 'v': verbose++;		break;
		case 'V': opt_version++;	break;
		case 'h': opt_howto++;	break;
		case '?': errflag++;
		}

	/* option check */
	if (opt_c)
		if(opt_a || opt_f || opt_r || opt_d || verbose || opt_version ||
		   opt_howto || errflag ) {
			fprintf(stderr, usage_msg);
			return 2;
		}

	if (errflag) {
		fprintf(stderr, usage_msg);
		return 2;
	}

	if (opt_howto) {
		fprintf(stderr, howto_msg);
		return 0;
	}

	if (verbose || opt_version) {
		printf(version);
		if (opt_version)
			exit(0);
	}

	/* Open a basic socket. */
	if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
		perror("socket");
		exit(-1);
	}

	if (verbose)
		fprintf(stderr, "DEBUG: argc=%d, optind=%d and argv[optind] is %s.\n",
				argc, optind, argv[optind]);

	/* No remaining args means show all interfaces. */
	if (optind == argc) {
		if_print((char *)NULL);
		(void) close(skfd);
		exit(0);
	}

	/* Copy the interface name. */
	spp = argv + optind;
	master_ifname = *spp++;
	slave_ifname = *spp++;

	/* Check command line. */
	if (opt_c) {
		char **tempp = spp;
		if ((master_ifname == NULL)||(slave_ifname == NULL)||(*tempp++ != NULL)) {
			fprintf(stderr, usage_msg);
			(void) close(skfd);
			return 2;
		}
	}

	/* A single args means show the configuration for this interface. */
	if (slave_ifname == NULL) {
		if_print(master_ifname);
		(void) close(skfd);
		exit(0);
	}

	/* exchange abi version with bonding driver */
	abi_ver = get_abi_ver(master_ifname);
	if (abi_ver < 0) {
		(void) close(skfd);
		exit(1);
	}

	/* Get the vitals from the master interface. */
	{
		struct ifreq *ifra[7] = { &if_ipaddr, &if_mtu, &if_dstaddr,
								  &if_brdaddr, &if_netmask, &if_flags,
								  &if_hwaddr };
		const char *req_name[7] = {
			"IP address", "MTU", "destination address",
			"broadcast address", "netmask", "status flags",
			"hardware address" };
		const int ioctl_req_type[7] = {
			SIOCGIFADDR, SIOCGIFMTU, SIOCGIFDSTADDR,
			SIOCGIFBRDADDR, SIOCGIFNETMASK, SIOCGIFFLAGS,
			SIOCGIFHWADDR };
		int i;

		for (i = 0; i < 7; i++) {
			strncpy(ifra[i]->ifr_name, master_ifname, IFNAMSIZ);
			if (ioctl(skfd, ioctl_req_type[i], ifra[i]) < 0) {
				fprintf(stderr,
						"Something broke getting the master's %s: %s.\n",
						req_name[i], strerror(errno));
			}
		}

		/* check if master is up; if not then fail any operation */
		if (!(if_flags.ifr_flags & IFF_UP)) {
			fprintf(stderr, "Illegal operation; the specified master interface '%s' is not up.\n", master_ifname);
			(void) close(skfd);
			exit (1);
		}

		hwaddr_notset = 1; /* assume master's address not set yet */
		for (i = 0; hwaddr_notset && (i < 6); i++) {
			hwaddr_notset &= ((unsigned char *)if_hwaddr.ifr_hwaddr.sa_data)[i] == 0;
		}

		/* The family '1' is ARPHRD_ETHER for ethernet. */
		if (if_hwaddr.ifr_hwaddr.sa_family != 1 && !opt_f) {
			fprintf(stderr, "The specified master interface '%s' is not"
					" ethernet-like.\n  This program is designed to work"
					" with ethernet-like network interfaces.\n"
					" Use the '-f' option to force the operation.\n",
					master_ifname);
			(void) close(skfd);
			exit (1);
		}
		master_family = if_hwaddr.ifr_hwaddr.sa_family;
		if (verbose) {
			unsigned char *hwaddr = (unsigned char *)if_hwaddr.ifr_hwaddr.sa_data;
			printf("The current hardware address (SIOCGIFHWADDR) of %s is type %d  "
				   "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", master_ifname,
				   if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
				   hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
		}
	}


	/* do this when enslaving interfaces */
	do {
		if (opt_d) {  /* detach a slave interface from the master */
			strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
			strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
			if ((ioctl(skfd, SIOCBONDRELEASE, &if_flags) < 0) &&
				(ioctl(skfd, BOND_RELEASE_OLD, &if_flags) < 0)) {
					fprintf(stderr,	"SIOCBONDRELEASE: cannot detach %s from %s. errno=%s.\n",
							slave_ifname, master_ifname, strerror(errno));
			}
			else if (abi_ver < 1) {
			      	/* The driver is using an old ABI, so we'll set the interface
				 * down to avoid any conflicts due to same IP/MAC
				 */
				strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
				if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
					int saved_errno = errno;
					fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
						strerror(saved_errno));
				}
				else {
					ifr2.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
					if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
						int saved_errno = errno;
						fprintf(stderr, "Shutting down interface %s failed: %s\n",
							slave_ifname, strerror(saved_errno));
					}
				}
			}
		} else if (opt_c) { /* change primary slave */
			strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
			strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
			if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &if_flags) < 0) &&
			    (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &if_flags) < 0)) {
				fprintf(stderr,	"SIOCBONDCHANGEACTIVE: %s.\n", strerror(errno));
			}
		} else {  /* attach a slave interface to the master */

			strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
			if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
				int saved_errno = errno;
				fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
						strerror(saved_errno));
				(void) close(skfd);
				return 1;
			}

			if ((ifr2.ifr_flags & IFF_SLAVE) && !opt_r) {
				fprintf(stderr, "%s is already a slave\n", slave_ifname);
				(void) close(skfd);
				return 1;
			}

			/* if hwaddr_notset, assign the slave hw address to the master */
			if (hwaddr_notset) {
				/* assign the slave hw address to the
				 * master since it currently does not
				 * have one; otherwise, slaves may
				 * have different hw addresses in
				 * active-backup mode as seen when enslaving
				 * using "ifenslave bond0 eth0 eth1" because
				 * hwaddr_notset is set outside this loop.
				 * TODO: put this and the "else" portion in
				 *       a function.
				 */
				/* get the slaves MAC address */
				strncpy(if_hwaddr.ifr_name, slave_ifname,
					IFNAMSIZ);
				rv = ioctl(skfd, SIOCGIFHWADDR, &if_hwaddr);
				if (-1 == rv) {
					fprintf(stderr, "Could not get MAC "
						"address of %s: %s\n",
						slave_ifname,
						strerror(errno));
					strncpy(if_hwaddr.ifr_name,
						master_ifname, IFNAMSIZ);
					goterr = 1;
				}

				if (!goterr) {
					if (abi_ver < 1) {
						/* In ABI versions older than 1, the
						 * master's set_mac routine couldn't
						 * work if it was up, because it
						 * used the default ethernet set_mac
						 * function.
						 */
						/* bring master down */
						if_flags.ifr_flags &= ~IFF_UP;
						if (ioctl(skfd, SIOCSIFFLAGS,
								&if_flags) < 0) {
							goterr = 1;
							fprintf(stderr,
								"Shutting down "
								"interface %s failed: "
								"%s\n",
								master_ifname,
								strerror(errno));
						}
					}

					strncpy(if_hwaddr.ifr_name,
						master_ifname, IFNAMSIZ);
					if (ioctl(skfd, SIOCSIFHWADDR,
							&if_hwaddr) < 0) {
						fprintf(stderr,
							"Could not set MAC "
							"address of %s: %s\n",
							master_ifname,
							strerror(errno));
						goterr=1;
					} else {
						hwaddr_notset = 0;
					}

					if (abi_ver < 1) {
						/* bring master back up */
						if_flags.ifr_flags |= IFF_UP;
						if (ioctl(skfd, SIOCSIFFLAGS,
							  &if_flags) < 0) {
							fprintf(stderr,
								"Bringing up interface "
								"%s failed: %s\n",
								master_ifname,
								strerror(errno));
						}
					}
				}
			} else if (abi_ver < 1) { /* if (hwaddr_notset) */

			      	/* The driver is using an old ABI, so we'll set the interface
				 * down and assign the master's hwaddr to it
				 */
				if (ifr2.ifr_flags & IFF_UP) {
					ifr2.ifr_flags &= ~IFF_UP;
					if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
						int saved_errno = errno;
						fprintf(stderr, "Shutting down interface %s failed: %s\n",
							slave_ifname, strerror(saved_errno));
					}
				}

				strncpy(if_hwaddr.ifr_name, slave_ifname, IFNAMSIZ);
				if (ioctl(skfd, SIOCSIFHWADDR, &if_hwaddr) < 0) {
					int saved_errno = errno;
					fprintf(stderr, "SIOCSIFHWADDR on %s failed: %s\n", if_hwaddr.ifr_name,
						strerror(saved_errno));
					if (saved_errno == EBUSY)
						fprintf(stderr, "  The slave device %s is busy: it must be"
							" idle before running this command.\n", slave_ifname);
					else if (saved_errno == EOPNOTSUPP)
						fprintf(stderr, "  The slave device you specified does not support"
							" setting the MAC address.\n  Your kernel likely does not"
							" support slave devices.\n");
					else if (saved_errno == EINVAL)
						fprintf(stderr, "  The slave device's address type does not match"
							" the master's address type.\n");
				} else {
					if (verbose) {
						unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data;
						printf("Slave's (%s) hardware address set to "
							   "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", slave_ifname,
							   hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
					}
				}
			}

			if (*spp  &&  !strcmp(*spp, "metric")) {
				if (*++spp == NULL) {
					fprintf(stderr, usage_msg);
					(void) close(skfd);
					exit(2);
				}
				if_metric.ifr_metric = atoi(*spp);
				strncpy(if_metric.ifr_name, slave_ifname, IFNAMSIZ);
				if (ioctl(skfd, SIOCSIFMETRIC, &if_metric) < 0) {
					fprintf(stderr, "SIOCSIFMETRIC on %s: %s\n", slave_ifname,
							strerror(errno));
					goterr = 1;
				}
				spp++;
			}

			if (strncpy(if_ipaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
				|| ioctl(skfd, SIOCSIFADDR, &if_ipaddr) < 0) {
				fprintf(stderr,
						"Something broke setting the slave's address: %s.\n",
						strerror(errno));
			} else {
				if (verbose) {
					unsigned char *ipaddr = if_ipaddr.ifr_addr.sa_data;
					printf("Set the slave's (%s) IP address to %d.%d.%d.%d.\n",
						   slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
				}
			}

			if (strncpy(if_mtu.ifr_name, slave_ifname, IFNAMSIZ) <= 0
				|| ioctl(skfd, SIOCSIFMTU, &if_mtu) < 0) {
				fprintf(stderr, "Something broke setting the slave MTU: %s.\n",
						strerror(errno));
			} else {
				if (verbose)
					printf("Set the slave's (%s) MTU to %d.\n", slave_ifname, if_mtu.ifr_mtu);
			}

			if (strncpy(if_dstaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
				|| ioctl(skfd, SIOCSIFDSTADDR, &if_dstaddr) < 0) {
				fprintf(stderr, "Error setting the slave (%s) with SIOCSIFDSTADDR: %s.\n",
						slave_ifname, strerror(errno));
			} else {
				if (verbose) {
					unsigned char *ipaddr = if_dstaddr.ifr_dstaddr.sa_data;
					printf("Set the slave's (%s) destination address to %d.%d.%d.%d.\n",
						   slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
				}
			}

			if (strncpy(if_brdaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
				|| ioctl(skfd, SIOCSIFBRDADDR, &if_brdaddr) < 0) {
				fprintf(stderr,
						"Something broke setting the slave (%s) broadcast address: %s.\n",
						slave_ifname, strerror(errno));
			} else {
				if (verbose) {
					unsigned char *ipaddr = if_brdaddr.ifr_broadaddr.sa_data;
					printf("Set the slave's (%s) broadcast address to %d.%d.%d.%d.\n",
						   slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
				}
			}

			if (strncpy(if_netmask.ifr_name, slave_ifname, IFNAMSIZ) <= 0
				|| ioctl(skfd, SIOCSIFNETMASK, &if_netmask) < 0) {
				fprintf(stderr,
						"Something broke setting the slave (%s) netmask: %s.\n",
						slave_ifname, strerror(errno));
			} else {
				if (verbose) {
					unsigned char *ipaddr = if_netmask.ifr_netmask.sa_data;
					printf("Set the slave's (%s) netmask to %d.%d.%d.%d.\n",
						   slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
				}
			}

			if (abi_ver < 1) {

			      	/* The driver is using an old ABI, so we'll set the interface
				 * up before enslaving it
				 */
				ifr2.ifr_flags |= IFF_UP;
				if ((ifr2.ifr_flags &= ~(IFF_SLAVE | IFF_MASTER)) == 0
					|| strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ) <= 0
					|| ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
						fprintf(stderr,
							"Something broke setting the slave (%s) flags: %s.\n",
							slave_ifname, strerror(errno));
				} else {
					if (verbose)
						printf("Set the slave's (%s) flags %4.4x.\n",
							slave_ifname, if_flags.ifr_flags);
				}
			} else {
				/* the bonding module takes care of setting the slave's mac address
			 	 * and opening its interface
			 	 */
				if (ifr2.ifr_flags & IFF_UP) { /* the interface will need to be down */
					ifr2.ifr_flags &= ~IFF_UP;
					if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
						int saved_errno = errno;
						fprintf(stderr, "Shutting down interface %s failed: %s\n",
							slave_ifname, strerror(saved_errno));
					}
				}
			}

			/* Do the real thing */
			if (!opt_r) {
				strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
				strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
				if ((ioctl(skfd, SIOCBONDENSLAVE, &if_flags) < 0) &&
				    (ioctl(skfd, BOND_ENSLAVE_OLD, &if_flags) < 0)) {
					fprintf(stderr,	"SIOCBONDENSLAVE: %s.\n", strerror(errno));
				}
			}
		}
	} while ( (slave_ifname = *spp++) != NULL);

	/* Close the socket. */
	(void) close(skfd);

	return(goterr);
}
Ejemplo n.º 12
0
int
main(int argc, char **argv)
{
  struct sockaddr sa;
  char host[128];
  struct aftype *ap;
  struct hwtype *hw;
  struct ifreq ifr;
  int goterr = 0;
  char **spp;

#if NLS
  setlocale (LC_MESSAGES, "");
  catfd = catopen ("nettools", MCLoadBySet);
#endif

  /* Create a channel to the NET kernel. */
  if ((skfd = sockets_open()) < 0) {
	perror("socket");
	NLS_CATCLOSE(catfd)
	exit(-1);
  }
  /* Find any options. */
  argc--; argv++;
  while (argc && *argv[0] == '-') {
	if (!strcmp(*argv, "-a")) opt_a = 1;
	
	if (!strcmp(*argv, "-v")) opt_v = 1;
	
	if (!strcmp(*argv, "-V") || !strcmp(*argv, "-version") || 
	    !strcmp(*argv, "--version")) version();
	    
	if (!strcmp(*argv, "-?") || !strcmp(*argv, "-h") || 
	    !strcmp(*argv, "-help") || !strcmp(*argv, "--help")) usage();

	argv++;
	argc--;
  }

  /* Do we have to show the current setup? */
  if (argc == 0) {
	if_print((char *)NULL);
	(void) close(skfd);
	NLS_CATCLOSE(catfd)
	exit(0);
  }

  /* No. Fetch the interface name. */
  spp = argv;
  strncpy(ifr.ifr_name, *spp++, IFNAMSIZ);
  if (*spp == (char *)NULL) {
	if_print(ifr.ifr_name);
	(void) close(skfd);
	NLS_CATCLOSE(catfd)
	exit(0);
  }

  /* The next argument is either an address family name, or an option. */
  if ((ap = get_aftype(*spp)) == NULL) {
	ap = get_aftype("inet");
  } else spp++;
  addr_family = ap->af;

  /* Process the remaining arguments. */
  while (*spp != (char *)NULL) {
	if (!strcmp(*spp, "arp")) {
		goterr |= clr_flag(ifr.ifr_name, IFF_NOARP);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "-arp")) {
		goterr |= set_flag(ifr.ifr_name, IFF_NOARP);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "trailers")) {
		goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "-trailers")) {
		goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "promisc")) {
		goterr |= set_flag(ifr.ifr_name, IFF_PROMISC);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "-promisc")) {
		goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "multicast")) {
		goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "-multicast")) {
		goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "allmulti")) {
		goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "-allmulti")) {
		goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "up")) {
		goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
		spp++;
		continue;
	}

	if (!strcmp(*spp, "down")) {
		goterr |= clr_flag(ifr.ifr_name, IFF_UP);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "metric")) {
		if (*++spp == NULL) usage();
		ifr.ifr_metric = atoi(*spp);
		if (ioctl(skfd, SIOCSIFMETRIC, &ifr) < 0) {
			fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno));
			goterr = 1;
		}
		spp++;
		continue;
	}

	if (!strcmp(*spp, "mtu")) {
		if (*++spp == NULL) usage();
		ifr.ifr_mtu = atoi(*spp);
		if (ioctl(skfd, SIOCSIFMTU, &ifr) < 0) {
			fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno));
			goterr = 1;
		}
		spp++;
		continue;
	}

	if (!strcmp(*spp, "-broadcast")) {
		goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "broadcast")) {
		if (*++spp != NULL ) {
			strcpy(host, *spp);
			if (ap->input(0, host, &sa) < 0) {
				ap->herror(host);
				goterr = 1;
				spp++;
				continue;
			}
			memcpy((char *) &ifr.ifr_broadaddr, (char *) &sa,
						sizeof(struct sockaddr));
			if (ioctl(skfd, SIOCSIFBRDADDR, &ifr) < 0) {
				fprintf(stderr, "SIOCSIFBRDADDR: %s\n",
							strerror(errno));
				goterr = 1;
			}
			spp++;
		}
		goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST);
		continue;
	}

	if (!strcmp(*spp, "dstaddr")) {
		if (*++spp == NULL) usage();
		strcpy(host, *spp);
		if (ap->input(0, host, &sa) < 0) {
			ap->herror(host);
			goterr = 1;
			spp++;
			continue;
		}
		memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
						sizeof(struct sockaddr));
		if (ioctl(skfd, SIOCSIFDSTADDR, &ifr) < 0) {
			fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
						strerror(errno));
			goterr = 1;
		}
		spp++;
		continue;
	}

	if (!strcmp(*spp, "netmask")) {
		if (*++spp == NULL) usage();
		strcpy(host, *spp);
		if (ap->input(0, host, &sa) < 0) {
			ap->herror(host);
			goterr = 1;
			spp++;
			continue;
		}
		memcpy((char *) &ifr.ifr_netmask, (char *) &sa,
						sizeof(struct sockaddr));
		if (ioctl(skfd, SIOCSIFNETMASK, &ifr) < 0) {
			fprintf(stderr, "SIOCSIFNETMASK: %s\n",
						strerror(errno));
			goterr = 1;
		}
		spp++;
		continue;
	}

	if (!strcmp(*spp, "mem_start")) {
		if (*++spp == NULL) usage();
		if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
			goterr = 1;
			continue;
		}
		ifr.ifr_map.mem_start = strtoul(*spp, NULL, 0);
		if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
			fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
			goterr = 1;
		}
		spp++;
		continue;
	}

	if (!strcmp(*spp, "io_addr")) {
		if (*++spp == NULL) usage();
		if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
			goterr = 1;
			continue;
		}
		ifr.ifr_map.base_addr = strtol(*spp, NULL, 0);
		if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
			fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
			goterr = 1;
		}
		spp++;
		continue;
	}

	if (!strcmp(*spp, "irq")) {
		if (*++spp == NULL) usage();
		if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
			goterr = 1;
			continue;
		}
		ifr.ifr_map.irq = atoi(*spp);
		if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
			fprintf(stderr, "SIOCSIFMAP: %s\n", strerror(errno));
			goterr = 1;
		}
		spp++;
		continue;
	}

	if (!strcmp(*spp, "-pointopoint")) {
		goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT);
		spp++;
		continue;
	}

	if (!strcmp(*spp, "pointopoint")) {
		if (*(spp+1) != NULL) {
			spp++;
			strcpy(host, *spp);
			if (ap->input(0, host, &sa)) {
				ap->herror(host);
				goterr = 1;
				spp++;
				continue;
			};
			memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
						sizeof(struct sockaddr));
			if (ioctl(skfd, SIOCSIFDSTADDR, &ifr) < 0) {
				fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
							strerror(errno));
				goterr = 1;
			}
		}
		goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT);
		spp++;
		continue;
	};

	if (!strcmp(*spp, "hw")) {
		if (*++spp == NULL) usage();
		if ((hw = get_hwtype(*spp)) == NULL) usage();
		strcpy(host, *++spp);
		if (hw->input(host, &sa) < 0) {
			ap->herror(host);
			goterr = 1;
			spp++;
			continue;
		}
		memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa,
						sizeof(struct sockaddr));
		if (ioctl(skfd, SIOCSIFHWADDR, &ifr) < 0) {
			fprintf(stderr, "SIOCSIFHWADDR: %s\n",
						strerror(errno));
			goterr = 1;
		}
		spp++;
		continue;
	}

	/* If the next argument is a valid hostname, assume OK. */
	strcpy(host, *spp);
	if (ap->input(0, host, &sa) < 0) {
		ap->herror(host);
		usage();
	}

	memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr));
	if (ioctl(skfd, SIOCSIFADDR, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFADDR: %s\n", strerror(errno));
			goterr = 1;
	}
	goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
	spp++;
  }

  /* Close the socket. */
  (void) close(skfd);

  NLS_CATCLOSE(catfd)
  return(goterr);
}
Ejemplo n.º 13
0
int main(int argc, char **argv)
{
    struct sockaddr sa;
    struct sockaddr samask;
    struct sockaddr_in sin;
    char host[128];
    struct aftype *ap;
    struct hwtype *hw;
    struct ifreq ifr;
    int goterr = 0, didnetmask = 0, neednetmask=0;
    char **spp;
    int fd;
#if HAVE_AFINET6
    extern struct aftype inet6_aftype;
    struct sockaddr_in6 sa6;
    struct in6_ifreq ifr6;
    unsigned long prefix_len;
    char *cp;
#endif
#if HAVE_AFINET
    extern struct aftype inet_aftype;
#endif

#if I18N
    setlocale (LC_ALL, "");
    bindtextdomain("net-tools", "/usr/share/locale");
    textdomain("net-tools");
#endif

    /* Find any options. */
    argc--;
    argv++;
    while (argc && *argv[0] == '-') {
	if (!strcmp(*argv, "-a"))
	    opt_a = 1;

	else if (!strcmp(*argv, "-s"))
	    ife_short = 1;

	else if (!strcmp(*argv, "-v"))
	    opt_v = 1;
	
	else if (!strcmp(*argv, "-V") || !strcmp(*argv, "-version") ||
	    !strcmp(*argv, "--version"))
	    version();

	else if (!strcmp(*argv, "-?") || !strcmp(*argv, "-h") ||
	    !strcmp(*argv, "-help") || !strcmp(*argv, "--help"))
	    usage();

	else {
	    fprintf(stderr, _("ifconfig: option `%s' not recognised.\n"), 
		    argv[0]);
	    fprintf(stderr, _("ifconfig: `--help' gives usage information.\n"));
	    exit(1);
	}

	argv++;
	argc--;
    }

    /* Create a channel to the NET kernel. */
    if ((skfd = sockets_open(0)) < 0) {
	perror("socket");
	exit(1);
    }

    /* Do we have to show the current setup? */
    if (argc == 0) {
	int err = if_print((char *) NULL);
	(void) close(skfd);
	exit(err < 0);
    }
    /* No. Fetch the interface name. */
    spp = argv;
    safe_strncpy(ifr.ifr_name, *spp++, IFNAMSIZ);
    if (*spp == (char *) NULL) {
	int err = if_print(ifr.ifr_name);
	(void) close(skfd);
	exit(err < 0);
    }

    /* The next argument is either an address family name, or an option. */
    if ((ap = get_aftype(*spp)) != NULL)
	spp++; /* it was a AF name */
    else 
	ap = get_aftype(DFLT_AF);
	
    if (ap) {
	addr_family = ap->af;
	skfd = ap->fd;
    }

    /* Process the remaining arguments. */
    while (*spp != (char *) NULL) {
	if (!strcmp(*spp, "arp")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_NOARP);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-arp")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_NOARP);
	    spp++;
	    continue;
	}
#ifdef IFF_PORTSEL
	if (!strcmp(*spp, "media") || !strcmp(*spp, "port")) {
	    if (*++spp == NULL)
		usage();
	    if (!strcasecmp(*spp, "auto")) {
		goterr |= set_flag(ifr.ifr_name, IFF_AUTOMEDIA);
	    } else {
		int i, j, newport;
		char *endp;
		newport = strtol(*spp, &endp, 10);
		if (*endp != 0) {
		    newport = -1;
		    for (i = 0; if_port_text[i][0] && newport == -1; i++) {
			for (j = 0; if_port_text[i][j]; j++) {
			    if (!strcasecmp(*spp, if_port_text[i][j])) {
				newport = i;
				break;
			    }
			}
		    }
		}
		spp++;
		if (newport == -1) {
		    fprintf(stderr, _("Unknown media type.\n"));
		    goterr = 1;
		} else {
		    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
			perror("port: SIOCGIFMAP"); 
			goterr = 1;
			continue;
		    }
		    ifr.ifr_map.port = newport;
		    if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
			perror("port: SIOCSIFMAP");
			goterr = 1;
		    }
		}
	    }
	    continue;
	}
#endif

	if (!strcmp(*spp, "trailers")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_NOTRAILERS);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-trailers")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_NOTRAILERS);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "promisc")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_PROMISC);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-promisc")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_PROMISC);
	    if (test_flag(ifr.ifr_name, IFF_PROMISC) > 0)
	    	fprintf(stderr, _("Warning: Interface %s still in promisc mode... maybe other application is running?\n"), ifr.ifr_name);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "multicast")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_MULTICAST);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-multicast")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_MULTICAST);
	    if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0)
	    	fprintf(stderr, _("Warning: Interface %s still in MULTICAST mode.\n"), ifr.ifr_name);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "allmulti")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_ALLMULTI);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-allmulti")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_ALLMULTI);
	    if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0)
	    	fprintf(stderr, _("Warning: Interface %s still in ALLMULTI mode.\n"), ifr.ifr_name);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "up")) {
	    goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "down")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_UP);
	    spp++;
	    continue;
	}
#ifdef HAVE_DYNAMIC
	if (!strcmp(*spp, "dynamic")) {
	    goterr |= set_flag(ifr.ifr_name, IFF_DYNAMIC);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-dynamic")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_DYNAMIC);
	    spp++;
	    if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0)
	    	fprintf(stderr, _("Warning: Interface %s still in DYNAMIC mode.\n"), ifr.ifr_name);
	    continue;
	}
#endif

	if (!strcmp(*spp, "metric")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_metric = atoi(*spp);
	    if (ioctl(skfd, SIOCSIFMETRIC, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "mtu")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_mtu = atoi(*spp);
	    if (ioctl(skfd, SIOCSIFMTU, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFMTU: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#ifdef SIOCSKEEPALIVE
	if (!strcmp(*spp, "keepalive")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_data = (caddr_t) atoi(*spp);
	    if (ioctl(skfd, SIOCSKEEPALIVE, &ifr) < 0) {
		fprintf(stderr, "SIOCSKEEPALIVE: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#endif

#ifdef SIOCSOUTFILL
	if (!strcmp(*spp, "outfill")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_data = (caddr_t) atoi(*spp);
	    if (ioctl(skfd, SIOCSOUTFILL, &ifr) < 0) {
		fprintf(stderr, "SIOCSOUTFILL: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#endif

	if (!strcmp(*spp, "-broadcast")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_BROADCAST);
	    if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0)
	    	fprintf(stderr, _("Warning: Interface %s still in BROADCAST mode.\n"), ifr.ifr_name);
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "broadcast")) {
	    if (*++spp != NULL) {
		safe_strncpy(host, *spp, (sizeof host));
		if (ap->input(0, host, &sa) < 0) {
		    if (ap->herror)
		    	ap->herror(host);
		    else
		    	fprintf(stderr, _("ifconfig: Error resolving '%s' for broadcast\n"), host);
		    goterr = 1;
		    spp++;
		    continue;
		}
		memcpy((char *) &ifr.ifr_broadaddr, (char *) &sa,
		       sizeof(struct sockaddr));
		if (ioctl(ap->fd, SIOCSIFBRDADDR, &ifr) < 0) {
		    fprintf(stderr, "SIOCSIFBRDADDR: %s\n",
			    strerror(errno));
		    goterr = 1;
		}
		spp++;
	    }
	    goterr |= set_flag(ifr.ifr_name, IFF_BROADCAST);
	    continue;
	}
	if (!strcmp(*spp, "dstaddr")) {
	    if (*++spp == NULL)
		usage();
	    safe_strncpy(host, *spp, (sizeof host));
	    if (ap->input(0, host, &sa) < 0) {
		    if (ap->herror)
		    	ap->herror(host);
		    else
		    	fprintf(stderr, _("ifconfig: Error resolving '%s' for dstaddr\n"), host);
		goterr = 1;
		spp++;
		continue;
	    }
	    memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
		   sizeof(struct sockaddr));
	    if (ioctl(ap->fd, SIOCSIFDSTADDR, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
			strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "netmask")) {
	    if (*++spp == NULL || didnetmask)
		usage();
	    safe_strncpy(host, *spp, (sizeof host));
	    if (ap->input(0, host, &sa) < 0) {
		    if (ap->herror)
		    	ap->herror(host);
		    else
		    	fprintf(stderr, _("ifconfig: Error resolving '%s' for netmask\n"), host);
		goterr = 1;
		spp++;
		continue;
	    }
	    didnetmask++;
	    goterr |= set_netmask(ap->fd, &ifr, &sa);
	    spp++;
	    continue;
	}
#ifdef HAVE_TXQUEUELEN
	if (!strcmp(*spp, "txqueuelen")) {
	    if (*++spp == NULL)
		usage();
	    ifr.ifr_qlen = strtoul(*spp, NULL, 0);
	    if (ioctl(skfd, SIOCSIFTXQLEN, &ifr) < 0) {
		fprintf(stderr, "SIOCSIFTXQLEN: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#endif

	if (!strcmp(*spp, "mem_start")) {
	    if (*++spp == NULL)
		usage();
	    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
		fprintf(stderr, "mem_start: SIOCGIFMAP: %s\n", strerror(errno)); 
		spp++; 
		goterr = 1;
		continue;
	    }
	    ifr.ifr_map.mem_start = strtoul(*spp, NULL, 0);
	    if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
		fprintf(stderr, "mem_start: SIOCSIFMAP: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "io_addr")) {
	    if (*++spp == NULL)
		usage();
	    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
		fprintf(stderr, "io_addr: SIOCGIFMAP: %s\n", strerror(errno)); 
		spp++; 
		goterr = 1;
		continue;
	    }
	    ifr.ifr_map.base_addr = strtol(*spp, NULL, 0);
	    if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
		fprintf(stderr, "io_addr: SIOCSIFMAP: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "irq")) {
	    if (*++spp == NULL)
		usage();
	    if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
		fprintf(stderr, "irq: SIOCGIFMAP: %s\n", strerror(errno)); 
		goterr = 1;
		spp++; 
		continue;
	    }
	    ifr.ifr_map.irq = atoi(*spp);
	    if (ioctl(skfd, SIOCSIFMAP, &ifr) < 0) {
		fprintf(stderr, "irq: SIOCSIFMAP: %s\n", strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
	if (!strcmp(*spp, "-pointopoint")) {
	    goterr |= clr_flag(ifr.ifr_name, IFF_POINTOPOINT);
	    spp++;
	    if (test_flag(ifr.ifr_name, IFF_MULTICAST) > 0)
	    	fprintf(stderr, _("Warning: Interface %s still in POINTOPOINT mode.\n"), ifr.ifr_name);
	    continue;
	}
	if (!strcmp(*spp, "pointopoint")) {
	    if (*(spp + 1) != NULL) {
		spp++;
		safe_strncpy(host, *spp, (sizeof host));
		if (ap->input(0, host, &sa)) {
		    if (ap->herror)
		    	ap->herror(host);
		    else
		    	fprintf(stderr, _("ifconfig: Error resolving '%s' for pointopoint\n"), host);
		    goterr = 1;
		    spp++;
		    continue;
		}
		memcpy((char *) &ifr.ifr_dstaddr, (char *) &sa,
		       sizeof(struct sockaddr));
		if (ioctl(ap->fd, SIOCSIFDSTADDR, &ifr) < 0) {
		    fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
			    strerror(errno));
		    goterr = 1;
		}
	    }
	    goterr |= set_flag(ifr.ifr_name, IFF_POINTOPOINT);
	    spp++;
	    continue;
	};

	if (!strcmp(*spp, "hw")) {
	    if (*++spp == NULL)
		usage();
	    if ((hw = get_hwtype(*spp)) == NULL)
		usage();
	    if (hw->input == NULL) {
	    	fprintf(stderr, _("hw address type `%s' has no handler to set address. failed.\n"), *spp);
	    	spp+=2;
	    	goterr = 1;
	    	continue;
	    }
	    if (*++spp == NULL)
		usage();
	    safe_strncpy(host, *spp, (sizeof host));
	    if (hw->input(host, &sa) < 0) {
		fprintf(stderr, _("%s: invalid %s address.\n"), host, hw->name);
		goterr = 1;
		spp++;
		continue;
	    }
	    memcpy((char *) &ifr.ifr_hwaddr, (char *) &sa,
		   sizeof(struct sockaddr));
	    if (ioctl(skfd, SIOCSIFHWADDR, &ifr) < 0) {
		if (errno == EBUSY)
			fprintf(stderr, "SIOCSIFHWADDR: %s - you may need to down the interface\n",
				strerror(errno));
		else
			fprintf(stderr, "SIOCSIFHWADDR: %s\n",
				strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#if HAVE_AFINET || HAVE_AFINET6
	if (!strcmp(*spp, "add")) {
	    if (*++spp == NULL)
		usage();
#if HAVE_AFINET6
	    if (strchr(*spp, ':')) {
		/* INET6 */
		if ((cp = strchr(*spp, '/'))) {
		    prefix_len = atol(cp + 1);
		    if ((prefix_len < 0) || (prefix_len > 128))
			usage();
		    *cp = 0;
		} else {
		    prefix_len = 128;
		}
		safe_strncpy(host, *spp, (sizeof host));
		if (inet6_aftype.input(1, host, 
				       (struct sockaddr *) &sa6) < 0) {
		    if (inet6_aftype.herror)
		    	inet6_aftype.herror(host);
		    else
		    	fprintf(stderr, _("ifconfig: Error resolving '%s' for add\n"), host);
		    goterr = 1;
		    spp++;
		    continue;
		}
		memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
		       sizeof(struct in6_addr));

		fd = get_socket_for_af(AF_INET6);
		if (fd < 0) {
		    fprintf(stderr, 
			    _("No support for INET6 on this system.\n"));
		    goterr = 1;
		    spp++;
		    continue;
		}
		if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
		    perror("SIOGIFINDEX");
		    goterr = 1;
		    spp++;
		    continue;
		}
		ifr6.ifr6_ifindex = ifr.ifr_ifindex;
		ifr6.ifr6_prefixlen = prefix_len;
		if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) {
		    perror("SIOCSIFADDR");
		    goterr = 1;
		}
		spp++;
		continue;
	    }
#endif
#ifdef HAVE_AFINET
	    { /* ipv4 address a.b.c.d */
		unsigned long ip, nm, bc;
		safe_strncpy(host, *spp, (sizeof host));
		if (inet_aftype.input(0, host, (struct sockaddr *)&sin) < 0) {
		    ap->herror(host);
		    goterr = 1;
		    spp++;
		    continue;
		}
		fd = get_socket_for_af(AF_INET);
		if (fd < 0) {
		    fprintf(stderr, 
			    _("No support for INET on this system.\n"));
		    goterr = 1;
		    spp++;
		    continue;
		}

		memcpy(&ip, &sin.sin_addr.s_addr, sizeof(unsigned long));
		
		if (get_nmbc_parent(ifr.ifr_name, &nm, &bc) < 0) {
			fprintf(stderr, _("Interface %s not initialized\n"),
				ifr.ifr_name);
			goterr = 1;
			spp++;
			continue;
		}
		set_ifstate(ifr.ifr_name, ip, nm, bc, 1);
		
	    }
	    spp++;
	    continue;
#else
	    fprintf(stderr, _("Bad address.\n"));
#endif
	}
#endif

#if HAVE_AFINET || HAVE_AFINET6
	if (!strcmp(*spp, "del")) {
	    if (*++spp == NULL)
		usage();

#ifdef SIOCDIFADDR
#if HAVE_AFINET6
	    if (strchr(*spp, ':')) {	/* INET6 */
		if ((cp = strchr(*spp, '/'))) {
		    prefix_len = atol(cp + 1);
		    if ((prefix_len < 0) || (prefix_len > 128))
			usage();
		    *cp = 0;
		} else {
		    prefix_len = 128;
		}
		safe_strncpy(host, *spp, (sizeof host));
		if (inet6_aftype.input(1, host, 
				       (struct sockaddr *) &sa6) < 0) {
		    inet6_aftype.herror(host);
		    goterr = 1;
		    spp++;
		    continue;
		}
		memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
		       sizeof(struct in6_addr));
		
		fd = get_socket_for_af(AF_INET6);
		if (fd < 0) {
		    fprintf(stderr, 
			    _("No support for INET6 on this system.\n"));
		    goterr = 1;
		    spp++;
		    continue;
		}
		if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
		    perror("SIOGIFINDEX");
		    goterr = 1;
		    spp++;
		    continue;
		}
		ifr6.ifr6_ifindex = ifr.ifr_ifindex;
		ifr6.ifr6_prefixlen = prefix_len;
		if (opt_v)
			fprintf(stderr, "now deleting: ioctl(SIOCDIFADDR,{ifindex=%d,prefixlen=%ld})\n",ifr.ifr_ifindex,prefix_len);
		if (ioctl(fd, SIOCDIFADDR, &ifr6) < 0) {
		    fprintf(stderr, "SIOCDIFADDR: %s\n",
			    strerror(errno));
		    goterr = 1;
		}
		spp++;
		continue;
	    }
#endif
#ifdef HAVE_AFINET
	    {
		/* ipv4 address a.b.c.d */
		unsigned long ip, nm, bc;
		safe_strncpy(host, *spp, (sizeof host));
		if (inet_aftype.input(0, host, (struct sockaddr *)&sin) < 0) {
		    ap->herror(host);
		    goterr = 1;
		    spp++;
		    continue;
		}
		fd = get_socket_for_af(AF_INET);
		if (fd < 0) {
		    fprintf(stderr, _("No support for INET on this system.\n"));
		    goterr = 1;
		    spp++;
		    continue;
		}
		
		memcpy(&ip, &sin.sin_addr.s_addr, sizeof(unsigned long));
		
		if (get_nmbc_parent(ifr.ifr_name, &nm, &bc) < 0) {
		    fprintf(stderr, _("Interface %s not initialized\n"),
			    ifr.ifr_name);
		    goterr = 1;
		    spp++;
		    continue;
		}
		set_ifstate(ifr.ifr_name, ip, nm, bc, 0);
	    }
	    spp++;
	    continue;
#else
	    fprintf(stderr, _("Bad address.\n"));
#endif
#else
	    fprintf(stderr, _("Address deletion not supported on this system.\n"));
#endif
	}
#endif
#if HAVE_AFINET6
	if (!strcmp(*spp, "tunnel")) {
	    if (*++spp == NULL)
		usage();
	    if ((cp = strchr(*spp, '/'))) {
		prefix_len = atol(cp + 1);
		if ((prefix_len < 0) || (prefix_len > 128))
		    usage();
		*cp = 0;
	    } else {
		prefix_len = 128;
	    }
	    safe_strncpy(host, *spp, (sizeof host));
	    if (inet6_aftype.input(1, host, (struct sockaddr *) &sa6) < 0) {
		inet6_aftype.herror(host);
		goterr = 1;
		spp++;
		continue;
	    }
	    memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
		   sizeof(struct in6_addr));

	    fd = get_socket_for_af(AF_INET6);
	    if (fd < 0) {
		fprintf(stderr, _("No support for INET6 on this system.\n"));
		goterr = 1;
		spp++;
		continue;
	    }
	    if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
		perror("SIOGIFINDEX");
		goterr = 1;
		spp++;
		continue;
	    }
	    ifr6.ifr6_ifindex = ifr.ifr_ifindex;
	    ifr6.ifr6_prefixlen = prefix_len;

	    if (ioctl(fd, SIOCSIFDSTADDR, &ifr6) < 0) {
		fprintf(stderr, "SIOCSIFDSTADDR: %s\n",
			strerror(errno));
		goterr = 1;
	    }
	    spp++;
	    continue;
	}
#endif

	/* If the next argument is a valid hostname, assume OK. */
	safe_strncpy(host, *spp, (sizeof host));

	/* FIXME: sa is too small for INET6 addresses, inet6 should use that too, 
	   broadcast is unexpected */
	if (ap->getmask) {
	    switch (ap->getmask(host, &samask, NULL)) {
	    case -1:
		usage();
		break;
	    case 1:
		if (didnetmask)
		    usage();

		// remeber to set the netmask from samask later
		neednetmask = 1;
		break;
	    }
	}
	if (ap->input == NULL) {
	   fprintf(stderr, _("ifconfig: Cannot set address for this protocol family.\n"));
	   exit(1);
	}
	if (ap->input(0, host, &sa) < 0) {
	    if (ap->herror)
	    	ap->herror(host);
	    else
	    	fprintf(stderr,_("ifconfig: error resolving '%s' to set address for af=%s\n"), host, ap->name); fprintf(stderr,
	    _("ifconfig: `--help' gives usage information.\n")); exit(1);
	}
	memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr));
	{
	    int r = 0;		/* to shut gcc up */
	    switch (ap->af) {
#if HAVE_AFINET
	    case AF_INET:
		fd = get_socket_for_af(AF_INET);
		if (fd < 0) {
		    fprintf(stderr, _("No support for INET on this system.\n"));
		    exit(1);
		}
		r = ioctl(fd, SIOCSIFADDR, &ifr);
		break;
#endif
#if HAVE_AFECONET
	    case AF_ECONET:
		fd = get_socket_for_af(AF_ECONET);
		if (fd < 0) {
		    fprintf(stderr, _("No support for ECONET on this system.\n"));
		    exit(1);
		}
		r = ioctl(fd, SIOCSIFADDR, &ifr);
		break;
#endif
	    default:
		fprintf(stderr,
		_("Don't know how to set addresses for family %d.\n"), ap->af);
		exit(1);
	    }
	    if (r < 0) {
		perror("SIOCSIFADDR");
		goterr = 1;
	    }
	}

       /*
        * Don't do the set_flag() if the address is an alias with a - at the
        * end, since it's deleted already! - Roman
        *
        * Should really use regex.h here, not sure though how well it'll go
        * with the cross-platform support etc. 
        */
        {
            char *ptr;
            short int found_colon = 0;
            for (ptr = ifr.ifr_name; *ptr; ptr++ )
                if (*ptr == ':') found_colon++;
                
            if (!(found_colon && *(ptr - 1) == '-'))
                goterr |= set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
        }

	spp++;
    }

    if (neednetmask) {
	goterr |= set_netmask(skfd, &ifr, &samask);
	didnetmask++;
    }

    if (opt_v && goterr)
    	fprintf(stderr, _("WARNING: at least one error occured. (%d)\n"), goterr);

    return (goterr);
}
Ejemplo n.º 14
0
int main(int argc, char *argv[])
{
	char **spp, *master_ifname, *slave_ifname;
	int c, i, rv;
	int res = 0;
	int exclusive = 0;

	while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) {
		switch (c) {
		case 'a': opt_a++; exclusive++; break;
		case 'c': opt_c++; exclusive++; break;
		case 'd': opt_d++; exclusive++; break;
		case 'f': opt_f++; exclusive++; break;
		case 'h': opt_h++; exclusive++; break;
		case 'u': opt_u++; exclusive++; break;
		case 'v': opt_v++; break;
		case 'V': opt_V++; exclusive++; break;

		case '?':
			fprintf(stderr, usage_msg);
			res = 2;
			goto out;
		}
	}

	/* options check */
	if (exclusive > 1) {
		fprintf(stderr, usage_msg);
		res = 2;
		goto out;
	}

	if (opt_v || opt_V) {
		printf(version);
		if (opt_V) {
			res = 0;
			goto out;
		}
	}

	if (opt_u) {
		printf(usage_msg);
		res = 0;
		goto out;
	}

	if (opt_h) {
		printf(usage_msg);
		printf(help_msg);
		res = 0;
		goto out;
	}

	/* Open a basic socket */
	if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket");
		res = 1;
		goto out;
	}

	if (opt_a) {
		if (optind == argc) {
			/* No remaining args */
			/* show all interfaces */
			if_print((char *)NULL);
			goto out;
		} else {
			/* Just show usage */
			fprintf(stderr, usage_msg);
			res = 2;
			goto out;
		}
	}

	/* Copy the interface name */
	spp = argv + optind;
	master_ifname = *spp++;

	if (master_ifname == NULL) {
		fprintf(stderr, usage_msg);
		res = 2;
		goto out;
	}

	/* exchange abi version with bonding module */
	res = get_drv_info(master_ifname);
	if (res) {
		fprintf(stderr,
			"Master '%s': Error: handshake with driver failed. "
			"Aborting\n",
			master_ifname);
		goto out;
	}

	slave_ifname = *spp++;

	if (slave_ifname == NULL) {
		if (opt_d || opt_c) {
			fprintf(stderr, usage_msg);
			res = 2;
			goto out;
		}

		/* A single arg means show the
		 * configuration for this interface
		 */
		if_print(master_ifname);
		goto out;
	}

	res = get_if_settings(master_ifname, master_ifra);
	if (res) {
		/* Probably a good reason not to go on */
		fprintf(stderr,
			"Master '%s': Error: get settings failed: %s. "
			"Aborting\n",
			master_ifname, strerror(res));
		goto out;
	}

	/* check if master is indeed a master;
	 * if not then fail any operation
	 */
	if (!(master_flags.ifr_flags & IFF_MASTER)) {
		fprintf(stderr,
			"Illegal operation; the specified interface '%s' "
			"is not a master. Aborting\n",
			master_ifname);
		res = 1;
		goto out;
	}

	/* check if master is up; if not then fail any operation */
	if (!(master_flags.ifr_flags & IFF_UP)) {
		fprintf(stderr,
			"Illegal operation; the specified master interface "
			"'%s' is not up.\n",
			master_ifname);
		res = 1;
		goto out;
	}

	/* Only for enslaving */
	if (!opt_c && !opt_d) {
		sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family;
		unsigned char *hwaddr =
			(unsigned char *)master_hwaddr.ifr_hwaddr.sa_data;

		/* The family '1' is ARPHRD_ETHER for ethernet. */
		if (master_family != 1 && !opt_f) {
			fprintf(stderr,
				"Illegal operation: The specified master "
				"interface '%s' is not ethernet-like.\n "
				"This program is designed to work with "
				"ethernet-like network interfaces.\n "
				"Use the '-f' option to force the "
				"operation.\n",
				master_ifname);
			res = 1;
			goto out;
		}

		/* Check master's hw addr */
		for (i = 0; i < 6; i++) {
			if (hwaddr[i] != 0) {
				hwaddr_set = 1;
				break;
			}
		}

		if (hwaddr_set) {
			v_print("current hardware address of master '%s' "
				"is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
				"type %d\n",
				master_ifname,
				hwaddr[0], hwaddr[1],
				hwaddr[2], hwaddr[3],
				hwaddr[4], hwaddr[5],
				master_family);
		}
	}

	/* Accepts only one slave */
	if (opt_c) {
		/* change active slave */
		res = get_slave_flags(slave_ifname);
		if (res) {
			fprintf(stderr,
				"Slave '%s': Error: get flags failed. "
				"Aborting\n",
				slave_ifname);
			goto out;
		}
		res = change_active(master_ifname, slave_ifname);
		if (res) {
			fprintf(stderr,
				"Master '%s', Slave '%s': Error: "
				"Change active failed\n",
				master_ifname, slave_ifname);
		}
	} else {
		/* Accept multiple slaves */
		do {
			if (opt_d) {
				/* detach a slave interface from the master */
				rv = get_slave_flags(slave_ifname);
				if (rv) {
					/* Can't work with this slave. */
					/* remember the error and skip it*/
					fprintf(stderr,
						"Slave '%s': Error: get flags "
						"failed. Skipping\n",
						slave_ifname);
					res = rv;
					continue;
				}
				rv = release(master_ifname, slave_ifname);
				if (rv) {
					fprintf(stderr,
						"Master '%s', Slave '%s': Error: "
						"Release failed\n",
						master_ifname, slave_ifname);
					res = rv;
				}
			} else {
				/* attach a slave interface to the master */
				rv = get_if_settings(slave_ifname, slave_ifra);
				if (rv) {
					/* Can't work with this slave. */
					/* remember the error and skip it*/
					fprintf(stderr,
						"Slave '%s': Error: get "
						"settings failed: %s. "
						"Skipping\n",
						slave_ifname, strerror(rv));
					res = rv;
					continue;
				}
				rv = enslave(master_ifname, slave_ifname);
				if (rv) {
					fprintf(stderr,
						"Master '%s', Slave '%s': Error: "
						"Enslave failed\n",
						master_ifname, slave_ifname);
					res = rv;
				}
			}
		} while ((slave_ifname = *spp++) != NULL);
	}

out:
	if (skfd >= 0) {
		close(skfd);
	}

	return res;
}
int main(int argc, char *argv[])
{
	char **spp, *master_ifname, *slave_ifname;
	int c, i, rv;
	int res = 0;
	int exclusive = 0;

	while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) {
		switch (c) {
		case 'a': opt_a++; exclusive++; break;
		case 'c': opt_c++; exclusive++; break;
		case 'd': opt_d++; exclusive++; break;
		case 'f': opt_f++; exclusive++; break;
		case 'h': opt_h++; exclusive++; break;
		case 'u': opt_u++; exclusive++; break;
		case 'v': opt_v++; break;
		case 'V': opt_V++; exclusive++; break;

		case '?':
			fprintf(stderr, "%s", usage_msg);
			res = 2;
			goto out;
		}
	}

	/*               */
	if (exclusive > 1) {
		fprintf(stderr, "%s", usage_msg);
		res = 2;
		goto out;
	}

	if (opt_v || opt_V) {
		printf("%s", version);
		if (opt_V) {
			res = 0;
			goto out;
		}
	}

	if (opt_u) {
		printf("%s", usage_msg);
		res = 0;
		goto out;
	}

	if (opt_h) {
		printf("%s", usage_msg);
		printf("%s", help_msg);
		res = 0;
		goto out;
	}

	/*                     */
	if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket");
		res = 1;
		goto out;
	}

	if (opt_a) {
		if (optind == argc) {
			/*                   */
			/*                     */
			if_print((char *)NULL);
			goto out;
		} else {
			/*                 */
			fprintf(stderr, "%s", usage_msg);
			res = 2;
			goto out;
		}
	}

	/*                         */
	spp = argv + optind;
	master_ifname = *spp++;

	if (master_ifname == NULL) {
		fprintf(stderr, "%s", usage_msg);
		res = 2;
		goto out;
	}

	/*                                          */
	res = get_drv_info(master_ifname);
	if (res) {
		fprintf(stderr,
			"Master '%s': Error: handshake with driver failed. "
			"Aborting\n",
			master_ifname);
		goto out;
	}

	slave_ifname = *spp++;

	if (slave_ifname == NULL) {
		if (opt_d || opt_c) {
			fprintf(stderr, "%s", usage_msg);
			res = 2;
			goto out;
		}

		/*                            
                                     
   */
		if_print(master_ifname);
		goto out;
	}

	res = get_if_settings(master_ifname, master_ifra);
	if (res) {
		/*                                     */
		fprintf(stderr,
			"Master '%s': Error: get settings failed: %s. "
			"Aborting\n",
			master_ifname, strerror(res));
		goto out;
	}

	/*                                    
                                  
  */
	if (!(master_flags.ifr_flags & IFF_MASTER)) {
		fprintf(stderr,
			"Illegal operation; the specified interface '%s' "
			"is not a master. Aborting\n",
			master_ifname);
		res = 1;
		goto out;
	}

	/*                                                       */
	if (!(master_flags.ifr_flags & IFF_UP)) {
		fprintf(stderr,
			"Illegal operation; the specified master interface "
			"'%s' is not up.\n",
			master_ifname);
		res = 1;
		goto out;
	}

	/*                    */
	if (!opt_c && !opt_d) {
		sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family;
		unsigned char *hwaddr =
			(unsigned char *)master_hwaddr.ifr_hwaddr.sa_data;

		/*                                              */
		if (master_family != 1 && !opt_f) {
			fprintf(stderr,
				"Illegal operation: The specified master "
				"interface '%s' is not ethernet-like.\n "
				"This program is designed to work with "
				"ethernet-like network interfaces.\n "
				"Use the '-f' option to force the "
				"operation.\n",
				master_ifname);
			res = 1;
			goto out;
		}

		/*                        */
		for (i = 0; i < 6; i++) {
			if (hwaddr[i] != 0) {
				hwaddr_set = 1;
				break;
			}
		}

		if (hwaddr_set) {
			v_print("current hardware address of master '%s' "
				"is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
				"type %d\n",
				master_ifname,
				hwaddr[0], hwaddr[1],
				hwaddr[2], hwaddr[3],
				hwaddr[4], hwaddr[5],
				master_family);
		}
	}

	/*                        */
	if (opt_c) {
		/*                     */
		res = get_slave_flags(slave_ifname);
		if (res) {
			fprintf(stderr,
				"Slave '%s': Error: get flags failed. "
				"Aborting\n",
				slave_ifname);
			goto out;
		}
		res = change_active(master_ifname, slave_ifname);
		if (res) {
			fprintf(stderr,
				"Master '%s', Slave '%s': Error: "
				"Change active failed\n",
				master_ifname, slave_ifname);
		}
	} else {
		/*                        */
		do {
			if (opt_d) {
				/*                                          */
				rv = get_slave_flags(slave_ifname);
				if (rv) {
					/*                             */
					/*                               */
					fprintf(stderr,
						"Slave '%s': Error: get flags "
						"failed. Skipping\n",
						slave_ifname);
					res = rv;
					continue;
				}
				rv = release(master_ifname, slave_ifname);
				if (rv) {
					fprintf(stderr,
						"Master '%s', Slave '%s': Error: "
						"Release failed\n",
						master_ifname, slave_ifname);
					res = rv;
				}
			} else {
				/*                                        */
				rv = get_if_settings(slave_ifname, slave_ifra);
				if (rv) {
					/*                             */
					/*                               */
					fprintf(stderr,
						"Slave '%s': Error: get "
						"settings failed: %s. "
						"Skipping\n",
						slave_ifname, strerror(rv));
					res = rv;
					continue;
				}
				rv = enslave(master_ifname, slave_ifname);
				if (rv) {
					fprintf(stderr,
						"Master '%s', Slave '%s': Error: "
						"Enslave failed\n",
						master_ifname, slave_ifname);
					res = rv;
				}
			}
		} while ((slave_ifname = *spp++) != NULL);
	}

out:
	if (skfd >= 0) {
		close(skfd);
	}

	return res;
}