static int mxt_proc_proximity_msg(struct plugin_ac *p,unsigned long pl_flag)
{
	const struct mxt_config *dcfg = p->dcfg;
	struct device *dev = dcfg->dev;
	struct t72_observer *obs = p->obs;
	int ret;

	dev_info2(dev, "mxt t72 at mxt_proc_proximity_msg flag 0x%lx pl_flag 0x%lx\n",obs->flag,pl_flag);

	//proximity

	if (test_flag(IRAD_FLAG_PROXIMITY_DETECTED, &obs->flag)) {
		proximity_enable(true);
		ret = get_proximity_data();
		if (ret != 0) {
			dev_info(dev, "mxt t72 proximity removed\n");
			clear_flag(IRAD_FLAG_PROXIMITY_DETECTED, &obs->flag);
			p->set_and_clr_flag(p->dev, PL_STATUS_FLAG_PROXIMITY_REMOVED, 0);
		}
		proximity_enable(false);
	}else if (test_flag(/*T72_FLAG_CAL*/T72_FLAG_RESUME, &obs->flag)) {//only check when proximity not detected
		proximity_enable(true);
		ret = get_proximity_data();
		if (ret == 0) {
			dev_info(dev, "mxt t72 proximity detected\n");
			set_flag(IRAD_FLAG_PROXIMITY_DETECTED, &obs->flag);
		}else {
			dev_info(dev, "mxt t72 proximity not detected\n");
			clear_flag(IRAD_FLAG_PROXIMITY_DETECTED, &obs->flag);
		}
		proximity_enable(false);
	}

	return 0;
}
static int mxt_proc_noise_msg(struct plugin_ac *p,unsigned long pl_flag)
{
	const struct mxt_config *dcfg = p->dcfg;
	struct device *dev = dcfg->dev;
	struct t72_observer *obs = p->obs;

	dev_info2(dev, "mxt t72 at mxt_proc_noise_msg flag 0x%lx pl_flag 0x%lx\n",obs->flag,pl_flag);

	//very noise
	if (test_flag(PL_STATUS_FLAG_CAL_END,&pl_flag)) {
		if (test_flag(T72_FLAG_VERY_NOISE,&obs->flag)) {
			dev_info(dev, "mxt t72 enter very noise state\n");
			p->set_t9_t100_cfg(p->dev, T9_T100_THLD_VERY_NOISE, BIT_MASK(MXT_T9_MRGTHR)|BIT_MASK(MXT_T9_MRGHYST));
			p->set_t55_adp_thld(p->dev, T55_DISABLE);
		//noise
		}else if (test_flag(T72_FLAG_NOISE,&obs->flag)) {
			dev_info(dev, "mxt t72 enter noise state\n");
			p->set_t9_t100_cfg(p->dev, T9_T100_THLD_NOISE, BIT_MASK(MXT_T9_MRGTHR)|BIT_MASK(MXT_T9_MRGHYST));
			p->set_t55_adp_thld(p->dev, T55_DISABLE);
		//stable
		}else{
			dev_info(dev, "mxt t72 enter very stable state\n");
			p->set_t9_t100_cfg(p->dev, T9_T100_NORMAL, BIT_MASK(MXT_T9_MRGTHR)|BIT_MASK(MXT_T9_MRGHYST));
			p->set_t55_adp_thld(p->dev, T55_NORMAL);
		}
	}

	clear_flag(T72_FLAG_STATE_CHANGE, &obs->flag);
	p->set_and_clr_flag(p->dev, PL_STATUS_FLAG_NOISE_CHANGE, 0);
	return 0;
}
Beispiel #3
0
int main(int argc, char *argv[])
{
	int lc;
	const char *msg;

	msg = parse_opts(argc, argv, NULL, NULL);
	if (msg != NULL)
		tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);

	setup();
	for (lc = 0; TEST_LOOPING(lc); lc++) {
		if (ns_uts_fd != -1) {
			tst_resm(TINFO, "test_newuts");
			test_flag(CLONE_NEWUTS, CLONE_NEWUTS, do_child_newuts);
			test_flag(CLONE_NEWUTS, 0, do_child_newuts);
		}
		if (ns_ipc_fd != -1) {
			tst_resm(TINFO, "test_newipc");
			test_flag(CLONE_NEWIPC, CLONE_NEWIPC, do_child_newipc);
			test_flag(CLONE_NEWIPC, 0, do_child_newipc);
		}
	}
	cleanup();
	tst_exit();
}
static void plugin_cal_t72_hook_t6(struct plugin_ac *p, u8 status)
{
	const struct mxt_config *dcfg = p->dcfg;
	struct device *dev = dcfg->dev;
	struct t72_observer *obs = p->obs;

	if (status & (MXT_T6_STATUS_RESET|MXT_T6_STATUS_CAL)) {
		dev_info2(dev, "T72 hook T6 0x%x\n", status);

		if (status & MXT_T6_STATUS_CAL) {
			set_and_clr_flag(T72_FLAG_CAL,
					T72_FLAG_MASK_NORMAL,&obs->flag);
		}
		if (status & MXT_T6_STATUS_RESET) {
			set_and_clr_flag(T72_FLAG_RESET,
					T72_FLAG_MASK,&obs->flag);
		}
	} else {
		if (test_flag(T72_FLAG_CAL|T72_FLAG_RESET,&obs->flag)) {
			dev_info2(dev, "T72 hook T6 end\n");
			set_and_clr_flag(T72_FLAG_START_T61, 0, &obs->flag);
		}
	}

	dev_info2(dev, "mxt t72 flag=0x%lx\n",
			obs->flag);
}
static void plugin_ac_hook_t72(struct plugin_ac *p, u8 *msg)
{
	const struct mxt_config *dcfg = p->dcfg;
	struct device *dev = dcfg->dev;

	struct t72_observer *obs = (struct t72_observer *)p->obs;
	int state,dualx;

	state = msg[2] & T72_NOISE_STATE_MASK;
	dualx = msg[2] & T72_NOISE_DUALX_MASK;

	dev_info2(dev, "mxt hook t72 %d(%d,%d,%d)\n",
			state,NOISE_STABLE,NOISE_NOISY,NOISE_VERY_NOISY);

	if (state == NOISE_STABLE) {
		if (!test_flag(T72_FLAG_STABLE, &obs->flag)) {
			set_and_clr_flag(T72_FLAG_STABLE | T72_FLAG_STATE_CHANGE, T72_NOISE_MASK, &obs->flag);
			p->set_and_clr_flag(p->dev, 0, PL_STATUS_FLAG_NOISE_MASK);
		}
	} else if (state == NOISE_NOISY) {
		if (!test_flag(T72_FLAG_NOISE, &obs->flag)) {
			set_and_clr_flag(T72_FLAG_NOISE | T72_FLAG_STATE_CHANGE, T72_NOISE_MASK, &obs->flag);
			p->set_and_clr_flag(p->dev, PL_STATUS_FLAG_NOISE, PL_STATUS_FLAG_NOISE_MASK);
		}
	} else if (state == NOISE_VERY_NOISY) {
		if (!test_flag(T72_FLAG_VERY_NOISE | T72_FLAG_STATE_CHANGE, &obs->flag)) {
			set_and_clr_flag(T72_FLAG_VERY_NOISE, T72_NOISE_MASK, &obs->flag);
			p->set_and_clr_flag(p->dev, PL_STATUS_FLAG_VERY_NOISE, PL_STATUS_FLAG_NOISE_MASK);
		}
	} else {
		dev_info(dev, "mxt hook t72 unknow status %d\n",state);
	}

	if (dualx) {
		dev_info(dev, "mxt hook t72 dualx %d\n",dualx);
		p->set_and_clr_flag(p->dev, PL_STATUS_FLAG_DUALX, 0);
	} else {
		p->set_and_clr_flag(p->dev, 0, PL_STATUS_FLAG_DUALX);
	}
}
static long plugin_ac_t72_post_process_messages(struct plugin_ac *p, unsigned long pl_flag)
{
	const struct mxt_config *dcfg = p->dcfg;
	struct device *dev = dcfg->dev;
	struct t72_config *cfg = p->cfg;
	struct t72_observer *obs = p->obs;
	long next_interval = MAX_SCHEDULE_TIMEOUT;
	int ret = 0;

	if (test_flag(T72_FLAG_WORKAROUND_HALT,&obs->flag))
		return MAX_SCHEDULE_TIMEOUT;

	if (test_flag(T72_FLAG_STATE_CHANGE, &obs->flag)) {
		mxt_proc_noise_msg(p, pl_flag);
	}

	if (test_flag(/*T72_FLAG_CAL*/T72_FLAG_RESUME, &obs->flag)) {
		mxt_proc_proximity_msg(p, pl_flag);
	}

	if (test_flag(T72_FLAG_START_T61, &obs->flag)) {
		mxt_proc_timer_msg(p, pl_flag);
	}

	if (test_flag(T72_FLAG_MASK_LOW, &obs->flag)) {
		mxt_proc_hw_msg(p, pl_flag);
	}

	if (time_after_eq(jiffies,obs->time_next_st)) {
		if (test_flag(IRAD_FLAG_PROXIMITY_DETECTED, &obs->flag)) {
		mxt_proc_proximity_msg(p, pl_flag);
		}
	}else {
		dev_dbg2(dev, "mxt wait %lu\n", obs->time_next_st - jiffies);
		ret = -ETIME;
	}

	if (ret == -ETIME)
		next_interval = obs->time_next_st - jiffies + 1;
	if (ret == -EAGAIN)
		next_interval = cfg->interval_fast;
	else {
		next_interval = status_interval(p,obs->flag);
	}

	if (ret != -ETIME) {
		obs->time_next_st = jiffies;
		if (next_interval != MAX_SCHEDULE_TIMEOUT)
			obs->time_next_st = jiffies + next_interval;
		else
			obs->time_next_st = next_interval;
	}

	if (!next_interval)
		next_interval = MAX_SCHEDULE_TIMEOUT; //just wait interrupt if zero

	dev_dbg2(dev, "t72 mxt interval %lu wait %ld\n",next_interval,obs->time_next_st - jiffies);
	return next_interval;
}
long status_interval(struct plugin_ac *p, unsigned long flag)
{
	const struct mxt_config *dcfg = p->dcfg;
	struct device *dev = dcfg->dev;
	struct t72_config *cfg = p->cfg;
	unsigned long interval;

	if (test_flag(IRAD_FLAG_PROXIMITY_DETECTED, &flag))
		interval = cfg->interval_proximity_check;
	else
		interval = MAX_SCHEDULE_TIMEOUT;

	dev_dbg2(dev, "mxt interval %lu\n",interval);
	return (long)interval;
}
/*
 * Free block identified with <page, offset>
 */
void xv_free(struct xv_pool *pool, struct page *page, u32 offset)
{
	void *page_start;
	struct block_header *block, *tmpblock;

	offset -= XV_ALIGN;

	spin_lock(&pool->lock);

	page_start = get_ptr_atomic(page, 0);
	block = (struct block_header *)((char *)page_start + offset);

	/* Catch double free bugs */
	BUG_ON(test_flag(block, BLOCK_FREE));

	block->size = ALIGN(block->size, XV_ALIGN);

	tmpblock = BLOCK_NEXT(block);
	if (offset + block->size + XV_ALIGN == PAGE_SIZE)
		tmpblock = NULL;

	/* Merge next block if its free */
	if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) {
		/*
		 * Blocks smaller than XV_MIN_ALLOC_SIZE
		 * are not inserted in any free list.
		 */
		if (tmpblock->size >= XV_MIN_ALLOC_SIZE) {
			remove_block(pool, page,
				    offset + block->size + XV_ALIGN, tmpblock,
				    get_index_for_insert(tmpblock->size));
		}
		block->size += tmpblock->size + XV_ALIGN;
	}

	/* Merge previous block if its free */
	if (test_flag(block, PREV_FREE)) {
		tmpblock = (struct block_header *)((char *)(page_start) +
						get_blockprev(block));
		offset = offset - tmpblock->size - XV_ALIGN;

		if (tmpblock->size >= XV_MIN_ALLOC_SIZE)
			remove_block(pool, page, offset, tmpblock,
				    get_index_for_insert(tmpblock->size));

		tmpblock->size += block->size + XV_ALIGN;
		block = tmpblock;
	}

	/* No used objects in this page. Free it. */
	if (block->size == PAGE_SIZE - XV_ALIGN) {
		put_ptr_atomic(page_start);
		spin_unlock(&pool->lock);

		__free_page(page);
		stat_dec(&pool->total_pages);
		return;
	}

	set_flag(block, BLOCK_FREE);
	if (block->size >= XV_MIN_ALLOC_SIZE)
		insert_block(pool, page, offset, block);

	if (offset + block->size + XV_ALIGN != PAGE_SIZE) {
		tmpblock = BLOCK_NEXT(block);
		set_flag(tmpblock, PREV_FREE);
		set_blockprev(tmpblock, offset);
	}

	put_ptr_atomic(page_start);
	spin_unlock(&pool->lock);
}
Beispiel #9
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);
}