/* $Id: isdnctrl.c,v 1.2 1997/03/10 09:51:24 fritz Exp $
 * ISDN driver for Linux. (Control-Utility)
 *
 * Copyright 1994,95 by Fritz Elfert (fritz@wuemaus.franken.de)
 * Copyright 1995 Thinking Objects Software GmbH Wuerzburg
 *
 * This file is part of Isdn4Linux.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Log: isdnctrl.c,v $
 * Revision 1.2  1997/03/10 09:51:24  fritz
 * Bugfix: mapping was broken.
 *
 * Revision 1.1  1997/02/17 00:09:21  fritz
 * New CVS tree
 *
 * Revision 1.14  1996/06/06 22:08:46  fritz
 * Bugfix: verbose and getconf checked wrong number of parameters.
 * thanks to Andreas Jaeger <aj@arthur.pfalz.de>
 *
 * Revision 1.13  1996/04/30 12:48:35  fritz
 * Added Michael's ippp-bind patch.
 *
 * Revision 1.12  1996/04/30 12:43:18  fritz
 * Changed ioctl-names according to kernel-version
 *
 * Revision 1.11  1996/01/04 02:44:52  fritz
 * Changed copying policy to GPL
 * Added addslave, dial, sdelay and mapping.
 *
 * Revision 1.10  1995/12/18  18:03:19  fritz
 * New License, minor cleanups.
 *
 * Revision 1.9  1995/10/29  21:38:51  fritz
 * Changed all references to driver-numbers to new DriverId's
 *
 * Revision 1.8  1995/07/15  20:39:56  fritz
 * Added support for cisco_h Encapsulation.
 * Added suppurt for pre-binding an interface to a channel.
 *
 * Revision 1.7  1995/04/29  13:13:44  fritz
 * Added new command verbose.
 *
 * Revision 1.6  1995/04/23  13:38:34  fritz
 * Adapted addphone and delphone to support changes in isdn.c
 *
 * Revision 1.5  1995/03/25  23:35:35  fritz
 * Added ihup-Feature.
 *
 * Revision 1.4  1995/03/15  12:44:15  fritz
 * Added generic conversion-routines for keyword<->value conversion.
 * Added display of phone-numbers in list-routine
 * Corrected some typos
 *
 * Revision 1.3  1995/02/20  03:38:59  fritz
 * Added getmax and rmax for performance-tests of tty-driver.
 *
 * Revision 1.2  1995/01/29  23:27:52  fritz
 * Added keywords: list, l2_proto, l3_proto, huptimeout, chargehup and
 * encap.
 *
 * Revision 1.1  1995/01/09  07:35:35  fritz
 * Initial revision
 *
 *
 */

#undef  ISDN_DEBUG_MODEM_SENDOPT

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#include <linux/isdn.h>
#include <linux/isdnif.h>

char *l2protostr[] = {
        "x75i", "x75ui", "x75bui", "hdlc", "\0"
};

int l2protoval[] = {
        ISDN_PROTO_L2_X75I, ISDN_PROTO_L2_X75UI,
        ISDN_PROTO_L2_X75BUI, ISDN_PROTO_L2_HDLC, -1
};

char *l3protostr[] = {
        "trans", "\0"
};

int l3protoval[] = {
        ISDN_PROTO_L3_TRANS, -1
};

char *pencapstr[] = {
        "ethernet", "rawip", "ip", "cisco-h", "syncppp",
        "uihdlc", "\0"
};

int pencapval[] = {
        ISDN_NET_ENCAP_ETHER, ISDN_NET_ENCAP_RAWIP,
        ISDN_NET_ENCAP_IPTYP, ISDN_NET_ENCAP_CISCOHDLC,
        ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, -1
};

char *num2callb[] = {
        "off", "in", "out"
};

char *cmd;
char nextlistif[10];

void usage(void)
{
        fprintf(stderr, "usage: %s <command> <options>\n", cmd);
#if 0
        fprintf(stderr, "\n");
        fprintf(stderr, "where <command> is one of the following:\n");
        fprintf(stderr, "\n");
        fprintf(stderr, "    addif [name]               add net-interface\n");
        fprintf(stderr, "    delif name                 remove net-interface\n");
        fprintf(stderr, "    addphone name in|out num   add phone-number to interface\n");
        fprintf(stderr, "    delphone name in|out num   remove phone-number from interface\n");
        fprintf(stderr, "    eaz name [eaz|msn]         get/set eaz for interface\n");
        fprintf(stderr, "    huptimeout name [seconds]  get/set hangup-timeout for interface\n");
        fprintf(stderr, "    ihup name [on|off]         get/set incoming-hangup for interface\n");
        fprintf(stderr, "    chargehup name [on|off]    get/set charge-hangup for interface\n");
        fprintf(stderr, "    chargeint name [seconds]   get/set charge-interval if not given by telco\n");
        fprintf(stderr, "    secure name [on|off]       get/set secure-feature for interface\n");
        fprintf(stderr, "    callback name [in|outon|off]\n");
        fprintf(stderr, "                               get/set active callback-feature for interface\n");
        fprintf(stderr, "    cbhup name [on|off]        get/set reject-before-callback for interface\n");
        fprintf(stderr, "    cbdelay name [seconds]     get/set delay before callback for interface\n");
        fprintf(stderr, "    dialmax name [num]         get/set number of dial-atempts for interface\n");
        fprintf(stderr, "    encap name [encapname]     get/set packet-encapsulation for interface\n");
        fprintf(stderr, "    l2_prot name [protocol]    get/set layer-2-protocol for interface\n");
        fprintf(stderr, "    l3_prot name [protocol]    get/set layer-3-protocol for interface\n");
        fprintf(stderr, "    bind name [drvId,channel [exclusive]]\n");
        fprintf(stderr, "                               pre-bind interface to a channel\n");
        fprintf(stderr, "    unbind name                delete pre-binding\n");
        fprintf(stderr, "    list name|all              show current setup of interface(s)\n");
        fprintf(stderr, "    verbose num                set verbose-level\n");
        fprintf(stderr, "    hangup name                force hangup of interface\n");
        fprintf(stderr, "    busreject drvId on|off     set bus-reject-mode\n");
        fprintf(stderr, "    mapping drvId [MSN,MSN...] set MSN<->EAZ-Mapping\n");
        fprintf(stderr, "    addslave name slavename    add slave-interface\n");
        fprintf(stderr, "    sdelay mastername delay    set slave-activation delay\n");
        fprintf(stderr, "    dial name                  force dialing of interface\n");
        fprintf(stderr, "    system on|off              switch isdn-system on or off\n");
        fprintf(stderr, "    addlink name               MPPP, increase number of links\n");
        fprintf(stderr, "    removelink name            MPPP, decrease number of links\n");
        fprintf(stderr, "    pppbind name [devicenum]   PPP, bind interface to ippp-device (exclusive)\n");
        fprintf(stderr, "    pppunbind name             PPP, remove ippp-device binding\n");
#endif
        exit(-2);
}

static int key2num(char *key, char **keytable, int *numtable)
{
        int i = -1;
        while (strlen(keytable[++i]))
                if (!strcmp(keytable[i], key))
                        return numtable[i];
        return -1;
}

static char *
 num2key(int num, char **keytable, int *numtable)
{
        int i = -1;
        while (numtable[++i] >= 0)
                if (numtable[i] == num)
                        return keytable[i];
        return "???";
}

static void listbind(char *s, int e)
{
        if (strlen(s)) {
                char *p = strchr(s, ',');
                int ch;
                sscanf(p + 1, "%d", &ch);
                *p = '\0';
                printf("%s, Channel %d%s\n", s, ch, (e > 0) ? ", exclusive" : "");
        } else
                printf("Nothing\n");
}

static void listif(int isdnctrl, char *name, int errexit)
{
        isdn_net_ioctl_cfg cfg;
        union p {
                isdn_net_ioctl_phone phone;
                char n[1024];
        } ph;
        char nn[1024];

        strcpy(cfg.name, name);
        if (ioctl(isdnctrl, IIOCNETGCF, &cfg) < 0) {
                if (errexit) {
                        perror(name);
                        exit(-1);
                } else
                        return;
        }
        strcpy(ph.phone.name, name);
        ph.phone.outgoing = 0;
        if (ioctl(isdnctrl, IIOCNETGNM, &ph.phone) < 0) {
                if (errexit) {
                        perror(name);
                        exit(-1);
                } else
                        return;
        }
        strcpy(nn, ph.n);
        strcpy(ph.phone.name, name);
        ph.phone.outgoing = 1;
        if (ioctl(isdnctrl, IIOCNETGNM, &ph.phone) < 0) {
                if (errexit) {
                        perror(name);
                        exit(-1);
                } else
                        return;
        }
        printf("\nCurrent setup of interface '%s':\n\n", cfg.name);
        printf("EAZ/MSN:                %s\n", cfg.eaz);
        printf("Phone number(s):\n");
        printf("  Outgoing:	            %s\n", ph.n);
        printf("  Incoming:	            %s\n", nn);
        printf("Secure:        	        %s\n", cfg.secure ? "on" : "off");
        printf("Callback:               %s\n", num2callb[cfg.callback]);
        if (cfg.callback == 2)
                printf("Hangup after Dial       %s\n", cfg.cbdelay ? "on" : "off");
        else
                printf("Reject before Callback: %s\n", cfg.cbhup ? "on" : "off");
        printf("Callback-delay:         %d\n", cfg.cbdelay / 5);
        printf("Dialmax:                %d\n", cfg.dialmax);
        printf("Hangup-Timeout:         %d\n", cfg.onhtime);
        printf("Incoming-Hangup:        %s\n", cfg.ihup ? "on" : "off");
        printf("ChargeHangup:           %s\n", cfg.chargehup ? "on" : "off");
        printf("Charge-Units:           %d\n", cfg.charge);
        printf("Charge-Interval:        %d\n", cfg.chargeint);
        printf("Layer-2-Protocol:       %s\n", num2key(cfg.l2_proto, l2protostr, l2protoval));
        printf("Layer-3-Protocol:       %s\n", num2key(cfg.l3_proto, l3protostr, l3protoval));
        printf("Encapsulation:          %s\n", num2key(cfg.p_encap, pencapstr, pencapval));
        printf("Slave Interface:        %s\n", strlen(cfg.slave) ? cfg.slave : "None");
        printf("Slave delay:            %d\n", cfg.slavedelay);
        printf("Master Interface:       %s\n", strlen(cfg.master) ? cfg.master : "None");
        printf("Pre-Bound to:           ");
        listbind(cfg.drvid, cfg.exclusive);
        if (cfg.slave && strlen(cfg.slave))
                strcpy(nextlistif, cfg.slave);
        else
                nextlistif[0] = '\0';
}

static void get_setup(int isdnctrl, char *name)
{
        isdn_net_ioctl_cfg cfg;
        char buffer[0x1000];
        char *p;
        FILE *f;

        if (ioctl(isdnctrl, IIOCGETSET, &buffer) < 0) {
                perror("ioctl GET_SETUP");
                exit(-1);
        }
		if (strcmp(name,"-"))
        	f = fopen(name, "w");
		else
			f = stdout;
        if (!f) {
                perror(name);
                exit(-1);
        }
        p = buffer;
		fprintf(f,"[isdnctrl]\n");
        while (strlen(p)) {
                if (strlen(cfg.master)) {
					fprintf(f, "  netslave=\"%s\"\n", p);
					fprintf(f, "    master=\"%s\"\n", p);
				} else
                	fprintf(f, "  netif=\"%s\"\n", p);
                p += 10;
                memcpy((char *) &cfg, p, sizeof(cfg));
                fprintf(f, "    eazmsn=\"%s\"\n", cfg.eaz);
                fprintf(f, "    secure=%d\n", cfg.secure);
                fprintf(f, "    callback=%d\n", cfg.callback);
                fprintf(f, "    huptimeout=%d\n", cfg.onhtime);
                fprintf(f, "    ihup=%d\n", cfg.ihup);
                fprintf(f, "    chargehup=%d\n", cfg.chargehup);
                fprintf(f, "    l2prot=%d\n", cfg.l2_proto);
                fprintf(f, "    l3prot=%d\n", cfg.l3_proto);
                fprintf(f, "    encap=%d\n", cfg.p_encap);
                fprintf(f, "    chargeint=%d\n", cfg.chargeint);
                fprintf(f, "    slavedelay=%d\n", cfg.slavedelay);
                fprintf(f, "    exclusive=%d\n", cfg.exclusive);
                fprintf(f, "    binddev=\"%s\"\n", cfg.drvid);
                p += sizeof(cfg);
                fprintf(f, "    outphones=\"%s\"\n", p);
                p += (strlen(p) + 1);
                fprintf(f, "    inphones=\"%s\"\n", p);
                p += (strlen(p) + 1);
        }
		if (f != stdout)
        	fclose(f);
}

enum {
        ADDIF, ADDSLAVE, DELIF, DIAL,
        BIND, UNBIND, PPPBIND, PPPUNBIND,
        BUSREJECT, MAPPING, SYSTEM, HANGUP,
        ADDPHONE, DELPHONE, LIST, EAZ,
        VERBOSE, GETCONF, HUPTIMEOUT, CBDELAY,
        CHARGEINT, DIALMAX, SDELAY, CHARGEHUP,
        CBHUP, IHUP, SECURE, CALLBACK,
        L2_PROT, L3_PROT, ADDLINK, REMOVELINK,
        ENCAP
};

typedef struct {
        char *cmd;
        char *argno;
} cmd_struct;

static cmd_struct cmds[] =
{
        {"addif", "0"},
        {"addslave", "1"},
        {"delif", "0"},
        {"dial", "0"},
        {"bind", "12"},
        {"unbind", "0"},
        {"pppbind", "1"},
        {"pppunbind", "0"},
        {"busreject", "1"},
        {"mapping", "01"},
        {"system", "0"},
        {"hangup", "0"},
        {"addphone", "2"},
        {"delphone", "2"},
        {"list", "0"},
        {"eaz", "01"},
        {"verbose", "0"},
        {"getconf", "0"},
        {"huptimeout", "01"},
        {"cbdelay", "01"},
        {"chargeint", "01"},
        {"dialmax", "01"},
        {"sdelay", "01"},
        {"chargehup", "01"},
        {"cbhup", "01"},
        {"ihup", "01"},
        {"secure", "01"},
        {"callback", "01"},
        {"l2_prot", "01"},
        {"l3_prot", "01"},
        {"addlink", "0"},
        {"removelink", "0"},
        {"encap", "01"},
        {NULL,}
};

int findcmd(char *str)
{
        int i;

        for (i = 0; cmds[i].cmd; i++)
                if (!strcmp(cmds[i].cmd, str))
                        return i;
        return -1;
}

void main(int argc, char **argv)
{
        int fd;
        int i,
         n,
         args,
         cmdptr;
        int result;
        FILE *iflst;
        char *p;
        char s[255];
        isdn_net_ioctl_phone phone;
        isdn_net_ioctl_cfg cfg;
        isdn_ioctl_struct iocts;
        unsigned long j;
        char nstring[255];
        char *id;
        char *arg1;
        char *arg2;

        cmd = argv[0];
        if (argc < 3) {
                usage();
                return;
        }
        fd = open("/dev/isdnctrl", O_RDWR);
        if (fd < 0) {
                perror("/dev/isdnctrl");
                exit(-1);
        }
        id = argv[2];
        i = findcmd(argv[1]);
        for (cmdptr = 2; cmdptr < argc;) {
                if (i < 0) {    /* Unknown command */
                        fprintf(stderr, "The given command \"%s\" is unknown.\n\n", argv[cmdptr]);
                        usage();
                        return;
                }
                if (i != GETCONF) {
                        if (strlen(id) > 8) {
                                fprintf(stderr, "Interface name must not exceed 8 characters!\n");
                                close(fd);
                                return;
                        }
                }
                args = 0;
                for (n = 0; cmds[i].argno[n]; n++) {
                        args = cmds[i].argno[n] - '0';
                        if (!n && (args + cmdptr > argc - 1)) {
                                fprintf(stderr, "Too few arguments given for %s\n", cmds[i].cmd);
                                usage();
                                return;
                        }
                        if (n && ((cmdptr + args > argc - 1) || findcmd(argv[cmdptr + args]) >= 0)) {
                                args = cmds[i].argno[n - 1] - '0';
                                break;
                        }
                }
                arg1 = args ? argv[cmdptr + 1] : "";
                arg2 = (args > 1) ? argv[cmdptr + 2] : "";
                switch (i) {
                case ADDIF:
                        strcpy(s, id);
                        if ((result = ioctl(fd, IIOCNETAIF, s)) < 0) {
                                perror("addif");
                                exit(-1);
                        }
                        printf("%s added\n", s);
                        break;

                case ADDSLAVE:
                        if (strlen(arg1) > 8) {
                                fprintf(stderr, "slavename must not exceed 8 characters\n");
                                exit(-1);
                        }
                        sprintf(s, "%s,%s", id, arg1);
                        if ((result = ioctl(fd, IIOCNETASL, s)) < 0) {
                                perror("addslave");
                                exit(-1);
                        }
                        printf("%s added as slave to %s\n", s, id);
                        break;

                case DELIF:
                        if ((result = ioctl(fd, IIOCNETDIF, id)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        printf("%s deleted\n", id);
                        break;

                case DIAL:
                        if ((result = ioctl(fd, IIOCNETDIL, id)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        printf("Dialing of %s triggered\n", id);
                        break;

                case BIND:
                        if (args == 2)
                                if (strncmp(arg2, "excl", 4))
                                        usage();
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        sscanf(argv[3], "%s", cfg.drvid);
                        cfg.exclusive = (args == 2);
                        if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                sprintf(s, "%s or %s", id, arg2);
                                perror(s);
                                exit(-1);
                        }
                        printf("%s bound to ", id);
                        listbind(cfg.drvid, cfg.exclusive);
                        break;

                case UNBIND:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (!strlen(cfg.drvid)) {
                                printf("%s was not bound to anything\n", id);
                                exit(0);
                        }
                        cfg.drvid[0] = '\0';
                        cfg.exclusive = -1;
                        if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        printf("%s unbound successfully\n", id);
                        break;

                case PPPBIND:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        sscanf(arg1, "%d", &cfg.pppbind);
                        if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                sprintf(s, "%s or %s", id, arg1);
                                perror(s);
                                exit(-1);
                        }
                        printf("%s bound to %s", id, arg1);
                        break;

                case PPPUNBIND:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (cfg.pppbind < 0) {
                                printf("%s was not bound to anything\n", id);
                                exit(0);
                        }
                        cfg.pppbind = -1;
                        if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        printf("%s unbound successfully\n", id);
                        break;

                case BUSREJECT:
                        strcpy(iocts.drvid, id);
                        if (strcmp(arg1, "on") && strcmp(arg1, "off")) {
                                fprintf(stderr, "Bus-Reject must be 'on' or 'off'\n");
                                exit(-1);
                        }
                        iocts.arg = strcmp(arg1, "off");
                        if ((result = ioctl(fd, IIOCSETBRJ, &iocts)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        break;

                case MAPPING:
                        strcpy(iocts.drvid, id);
                        if (!args) {
                                iocts.arg = (unsigned long) &nstring;
                                if ((result = ioctl(fd, IIOCGETMAP, &iocts)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                                printf("MSN/EAZ-mapping for %s:\n%s\n", id, nstring);
                        } else {
                                char buf[400];
                                strncpy(buf, arg1, sizeof(buf) - 1);
                                iocts.arg = (unsigned long) buf;
                                if ((result = ioctl(fd, IIOCSETMAP, &iocts)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        break;

                case SYSTEM:
                        if (strcmp(id, "on") && strcmp(id, "off")) {
                                fprintf(stderr, "System-Mode must be 'on' or 'off'\n");
                                exit(-1);
                        }
                        j = strcmp(id, "on");
                        if ((result = ioctl(fd, IIOCSETGST, j)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        break;

                case HANGUP:
                        if ((result = ioctl(fd, IIOCNETHUP, id)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (result)
                                printf("%s not connected\n", id);
                        else
                                printf("%s hung up\n", id);
                        break;

                case ADDPHONE:
                        if (strcmp(arg1, "in") && strcmp(arg1, "out")) {
                                fprintf(stderr, "Direction must be \"in\" or \"out\"\n");
                                exit(-1);
                        }
                        phone.outgoing = strcmp(arg1, "out") ? 0 : 1;
                        if (strlen(arg2) > 20) {
                                fprintf(stderr, "phone-number must not exceed 20 characters\n");
                                exit(-1);
                        }
                        strcpy(phone.name, id);
                        strcpy(phone.phone, arg2);
                        if ((result = ioctl(fd, IIOCNETANM, &phone)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        break;

                case DELPHONE:
                        if (strcmp(arg1, "in") && strcmp(arg1, "out")) {
                                fprintf(stderr, "Direction must be \"in\" or \"out\"\n");
                                exit(-1);
                        }
                        phone.outgoing = strcmp(arg1, "out") ? 0 : 1;
                        if (strlen(arg2) > 20) {
                                fprintf(stderr, "phone-number must not exceed 20 characters\n");
                                exit(-1);
                        }
                        strcpy(phone.name, id);
                        strcpy(phone.phone, arg2);
                        if ((result = ioctl(fd, IIOCNETDNM, &phone)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        break;

                case LIST:
                        if (!strcmp(id, "all")) {
                                char name[10];
                                if ((iflst = fopen("/proc/net/dev", "r")) == NULL) {
                                        perror("/proc/net/dev");
                                        exit(-1);
                                }
                                while (!feof(iflst)) {
                                        fgets(s, sizeof(s), iflst);
                                        if ((p = strchr(s, ':'))) {
                                                *p = 0;
                                                sscanf(s, "%s", name);
                                                listif(fd, name, 0);
                                                while (strlen(nextlistif))
                                                        listif(fd, nextlistif, 0);
                                        }
                                }
                                fclose(iflst);
                        } else
                                listif(fd, id, 1);
                        break;

                case EAZ:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                strncpy(cfg.eaz, arg1, sizeof(cfg.eaz) - 1);
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("EAZ/MSN for %s is %s\n", cfg.name, cfg.eaz);
                        break;

                case VERBOSE:
                        i = -1;
                        sscanf(id, "%d", &i);
                        if (i < 0) {
                                fprintf(stderr, "Verbose-level must be >= 0\n");
                                exit(-1);
                        }
                        if ((result = ioctl(fd, IIOCSETVER, i)) < 0) {
                                perror("IIOCSETVER");
                                exit(-1);
                        }
                        printf("Verbose-level set to %d.\n", i);
                        break;

                case GETCONF:
                        get_setup(fd, id);
                        printf("Configuration written to %s.\n", id);
                        break;

                case HUPTIMEOUT:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                sscanf(arg1, "%d", &i);
                                if (i < 0) {
                                        fprintf(stderr, "Hangup-Timeout must be >= 0\n");
                                        exit(-1);
                                }
                                cfg.onhtime = i;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Hangup-Timeout for %s is %d sec.\n", cfg.name, cfg.onhtime);
                        break;

                case CBDELAY:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                sscanf(arg1, "%d", &i);
                                if (i < 0) {
                                        fprintf(stderr, "Callback delay must be >= 0\n");
                                        exit(-1);
                                }
                                cfg.cbdelay = i * 5;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Callback delay for %s is %d sec.\n", cfg.name, cfg.cbdelay / 5);
                        break;

                case CHARGEINT:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                sscanf(arg1, "%d", &i);
                                if (i < 0) {
                                        fprintf(stderr, "Charge interval must be >= 0\n");
                                        exit(-1);
                                }
                                cfg.chargeint = i;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Charge Interval for %s is %d sec.\n", cfg.name, cfg.chargeint);
                        break;

                case DIALMAX:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                sscanf(arg1, "%d", &i);
                                if (i < 1) {
                                        fprintf(stderr, "Dialmax must be > 0\n");
                                        exit(-1);
                                }
                                cfg.dialmax = i;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Dialmax for %s is %d times.\n", cfg.name, cfg.dialmax);
                        break;

                case SDELAY:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                sscanf(arg1, "%d", &i);
                                if (i < 1) {
                                        fprintf(stderr, "Slave-activation delay must be >= 1\n");
                                        exit(-1);
                                }
                                cfg.slavedelay = i;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Slave-activation delay for %s is %d sec.\n", cfg.name,
                               cfg.slavedelay);
                        break;

                case CHARGEHUP:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                if (strcmp(arg1, "on") && strcmp(arg1, "off")) {
                                        fprintf(stderr, "Charge-Hangup must be 'on' or 'off'\n");
                                        exit(-1);
                                }
                                cfg.chargehup = strcmp(arg1, "off");
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Charge-Hangup for %s is %s\n", cfg.name, cfg.chargehup ? "on" : "off");
                        break;

                case CBHUP:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                if (strcmp(arg1, "on") && strcmp(arg1, "off")) {
                                        fprintf(stderr, "Callback-Hangup must be 'on' or 'off'\n");
                                        exit(-1);
                                }
                                cfg.cbhup = strcmp(arg1, "off");
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Reject before Callback for %s is %s\n", cfg.name, cfg.cbhup ? "on" : "off");
                        break;

                case IHUP:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                if (strcmp(arg1, "on") && strcmp(arg1, "off")) {
                                        fprintf(stderr, "Incoming-Hangup must be 'on' or 'off'\n");
                                        exit(-1);
                                }
                                cfg.ihup = strcmp(arg1, "off");
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Incoming-Hangup for %s is %s\n", cfg.name, cfg.ihup ? "on" : "off");
                        break;

                case SECURE:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                if (strcmp(arg1, "on") && strcmp(arg1, "off")) {
                                        fprintf(stderr, "Secure-parameter must be 'on' or 'off'\n");
                                        exit(-1);
                                }
                                cfg.secure = strcmp(arg1, "off");
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Security for %s is %s\n", cfg.name, cfg.secure ? "on" : "off");
                        break;

                case CALLBACK:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = -1;
                                if (strcmp(arg1, "on") && strcmp(arg1, "off") &&
                                    strcmp(arg1, "in") && strcmp(arg1, "out")) {
                                        fprintf(stderr, "Callback-parameter must be 'on', 'in', 'out' or 'off'\n");
                                        exit(-1);
                                }
                                cfg.callback = strcmp(arg1, "off") ? 1 : 0;
                                if (!strcmp(arg1, "out"))
                                        cfg.callback = 2;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Callback for %s is %s\n", cfg.name, num2callb[cfg.callback]);
                        break;

                case L2_PROT:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = key2num(arg1, l2protostr, l2protoval);
                                if (i < 0) {
                                        fprintf(stderr, "Layer-2-Protocol must be one of the following:\n");
                                        i = 0;
                                        while (strlen(l2protostr[i]))
                                                fprintf(stderr, "\t\"%s\"\n", l2protostr[i++]);
                                        exit(-1);
                                }
                                cfg.l2_proto = i;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Layer-2-Protocol for %s is %s\n", cfg.name,
                          num2key(cfg.l2_proto, l2protostr, l2protoval));
                        break;

                case L3_PROT:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = key2num(arg1, l3protostr, l3protoval);
                                if (i < 0) {
                                        fprintf(stderr, "Layer-3-Protocol must be one of the following:\n");
                                        i = 0;
                                        while (strlen(l3protostr[i]))
                                                fprintf(stderr, "\t\"%s\"\n", l3protostr[i++]);
                                        exit(-1);
                                }
                                cfg.l3_proto = i;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Layer-3-Protocol for %s is %s\n", cfg.name,
                          num2key(cfg.l3_proto, l3protostr, l3protoval));
                        break;

                case ADDLINK:
                        if ((result = ioctl(fd, IIOCNETALN, id)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (result)
                                printf("Can't increase number of links: %d\n", result);
                        else
                                printf("Ok, added a new link. (dialing)\n");
                        break;

                case REMOVELINK:
                        if ((result = ioctl(fd, IIOCNETDLN, id)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (result)
                                printf("Can't decrease number of links: %d\n", result);
                        else
                                printf("Ok, removed a link. (hangup)\n");
                        break;

                case ENCAP:
                        strcpy(cfg.name, id);
                        if ((result = ioctl(fd, IIOCNETGCF, &cfg)) < 0) {
                                perror(id);
                                exit(-1);
                        }
                        if (args) {
                                i = key2num(arg1, pencapstr, pencapval);
                                if (i < 0) {
                                        fprintf(stderr, "Encapsulation must be one of the following:\n");
                                        i = 0;
                                        while (strlen(pencapstr[i]))
                                                fprintf(stderr, "\t\"%s\"\n", pencapstr[i++]);
                                        exit(-1);
                                }
                                cfg.p_encap = i;
                                if ((result = ioctl(fd, IIOCNETSCF, &cfg)) < 0) {
                                        perror(id);
                                        exit(-1);
                                }
                        }
                        printf("Encapsulation for %s is %s\n", cfg.name,
                             num2key(cfg.p_encap, pencapstr, pencapval));
                        break;
                }
                cmdptr += args + 1;
                if (cmdptr < argc) {
						printf("args=%d nextcmd %s\n",args, argv[cmdptr]);
                        i = findcmd(argv[cmdptr]);
				}
        }
        close(fd);
}
