/* * sethdlc.c * * Copyright (C) 1999 - 2001 Krzysztof Halasa * * 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 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_FW_LEN (128 * 1024) /* max firmware file length */ static struct ifreq req; /* for ioctl */ static int argc; static char **argv; int sock; static void error(const char *format, ...) __attribute__ ((noreturn)); static void error(const char *format, ...) { va_list args; va_start(args, format); fprintf(stderr, "%s: ", req.ifr_name); vfprintf(stderr, format, args); va_end(args); exit(1); } typedef struct { const char *name; const unsigned int value; } parsertab; static int checkkey(const char* name) { if (argc < 1) return -1; /* no enough parameters */ if (strcmp(name, argv[0])) return -1; argc--; argv++; return 0; } static int checktab(parsertab *tab, unsigned int *value) { int i; if (argc < 1) return -1; /* no enough parameters */ for (i = 0; tab[i].name; i++) if (!strcmp(tab[i].name, argv[0])) { argc--; argv++; *value = tab[i].value; return 0; } return -1; /* Not found */ } static const char* tabstr(unsigned int value, parsertab *tab, const char* unknown) { int i; for (i = 0; tab[i].name; i++) if (tab[i].value == value) return tab[i].name; return unknown; /* Not found */ } static unsigned int match(const char* name, unsigned int *value, unsigned int minimum, unsigned int maximum) { char test; if (argc < 1) return -1; /* no enough parameters */ if (name) { if (strcmp(name, argv[0])) return -1; argc--; argv++; } if (argc < 1) error("Missing parameter\n"); if (sscanf(argv[0], "%u%c", value, &test) != 1) error("Invalid parameter: %s\n", argv[0]); if ((*value > maximum) || (*value < minimum)) error("Parameter out of range [%u - %u]: %u\n", minimum, maximum, *value); argc--; argv++; return 0; } static parsertab ifaces[] = {{ "v35", IF_IFACE_V35 }, { "v24", IF_IFACE_V24 }, { "x21", IF_IFACE_X21 }, { "e1", IF_IFACE_E1 }, { "t1", IF_IFACE_T1 }, { NULL, 0 }}; static parsertab clocks[] = {{ "int", CLOCK_INT }, { "ext", CLOCK_EXT }, { "txint", CLOCK_TXINT }, { "txfromrx", CLOCK_TXFROMRX }, { NULL, 0 }}; static parsertab protos[] = {{ "hdlc", IF_PROTO_HDLC}, { "cisco", IF_PROTO_CISCO}, { "fr", IF_PROTO_FR}, { "ppp", IF_PROTO_PPP}, { "x25", IF_PROTO_X25}, { NULL, 0 }}; static parsertab hdlc_enc[] = {{ "nrz", ENCODING_NRZ }, { "nrzi", ENCODING_NRZI }, { "fm-mark", ENCODING_FM_MARK }, { "fm-space", ENCODING_FM_SPACE }, { "manchester", ENCODING_MANCHESTER }, { NULL, 0 }}; static parsertab hdlc_par[] = {{ "no-parity", PARITY_NONE }, { "crc16", PARITY_CRC16_PR1 }, { "crc16-pr0", PARITY_CRC16_PR0 }, { "crc16-itu", PARITY_CRC16_PR1_CCITT }, { "crc16-itu-pr0", PARITY_CRC16_PR0_CCITT }, { "crc32-itu", PARITY_CRC32_PR1_CCITT }, { NULL, 0 }}; static parsertab lmi[] = {{ "none", LMI_NONE }, { "ansi", LMI_ANSI }, { "ccitt", LMI_CCITT }, { NULL, 0 }}; static void set_iface(void) { sync_serial_settings synch; te1_settings telco = { 0, 0, 0, 0 }; int orig_argc = argc; req.ifr_settings.type = IF_IFACE_SYNC_SERIAL; while (argc > 0) { if (req.ifr_settings.type == IF_IFACE_SYNC_SERIAL) if (!checktab(ifaces, &req.ifr_settings.type)) continue; if (!telco.clock_type) { if (!checkkey("clock")) { if (checktab(clocks, &telco.clock_type)) error("Invalid clock type\n"); continue; } } if (!telco.clock_rate && (telco.clock_type == CLOCK_INT || telco.clock_type == CLOCK_TXINT)) if (!match("rate", &telco.clock_rate, 1, 0xFFFFFFFF)) continue; if (!telco.loopback) { if (!checkkey("loopback") || !checkkey("lb")) { telco.loopback = 1; continue; } } /* slotmap goes here */ if (orig_argc == argc) return; /* not an iface definition */ error("Invalid parameter: %s\n", argv[0]); } if (!telco.clock_rate && (telco.clock_type == CLOCK_INT || telco.clock_type == CLOCK_TXINT)) telco.clock_rate = 64000; if (req.ifr_settings.type == IF_IFACE_T1 || req.ifr_settings.type == IF_IFACE_E1) { req.ifr_settings.data_length = sizeof(telco); req.ifr_settings.data = &telco; } else { synch.clock_rate = telco.clock_rate; synch.clock_type = telco.clock_type; synch.loopback = telco.loopback; req.ifr_settings.data_length = sizeof(synch); req.ifr_settings.data = &synch; } if (ioctl(sock, SIOCDEVICE, &req)) error("Unable to set interface information: %s\n", strerror(errno)); exit(0); } static void set_proto_fr(void) { fr_proto fr; unsigned int dce = 0, lmi_type = 0; memset(&fr, 0, sizeof(fr)); while (argc > 0) { if (!lmi_type) if (!checkkey("lmi")) { if (checktab(lmi, &lmi_type)) error("Invalid LMI type: %s\n", argv[0]); continue; } if (lmi_type && lmi_type != LMI_NONE) { if (!dce) if (!checkkey("dce")) { dce = 1; continue; } if (!fr.t391) if (!match("t391", &fr.t391, 1, 1000)) continue; if (!fr.t392) if (!match("t392", &fr.t392, 1, 1000)) continue; if (!fr.n391) if (!match("n391", &fr.n391, 1, 1000)) continue; if (!fr.n392) if (!match("n392", &fr.n392, 1, 1000)) continue; if (!fr.n393) if (!match("n393", &fr.n393, 1, 1000)) continue; } error("Invalid parameter: %s\n", argv[0]); } if (!fr.t391) fr.t391 = 10; /* polling verification timer*/ /* link integrity verification polling timer */ if (!fr.t392) fr.t392 = 15; if (!fr.n391) fr.n391 = 6; /* full status polling counter*/ if (!fr.n392) fr.n392 = 3; /* error threshold */ if (!fr.n393) fr.n393 = 4; /* monitored events count */ if (!lmi_type) fr.lmi = LMI_ANSI; else fr.lmi = lmi_type; fr.dce = dce; req.ifr_settings.data_length = sizeof(fr); req.ifr_settings.data = &fr; if (ioctl(sock, SIOCDEVICE, &req)) error("Unable to set FR protocol information: %s\n", strerror(errno)); } static void set_proto_hdlc(void) { hdlc_proto hdlc; unsigned int enc = 0, par = 0; memset(&hdlc, 0, sizeof(hdlc)); while (argc > 0) { if (!enc) if (!checktab(hdlc_enc, &enc)) continue; if (!par) if (!checktab(hdlc_par, &par)) continue; error("Invalid parameter: %s\n", argv[0]); } if (!enc) hdlc.encoding = ENCODING_NRZ; else hdlc.encoding = enc; if (!par) hdlc.parity = PARITY_CRC16_PR1; else hdlc.parity = par; req.ifr_settings.data_length = sizeof(hdlc); req.ifr_settings.data = &hdlc; if (ioctl(sock, SIOCDEVICE, &req)) error("Unable to set HDLC protocol information: %s\n", strerror(errno)); } static void set_proto_cisco(void) { cisco_proto cisco; memset(&cisco, 0, sizeof(cisco)); while (argc > 0) { if (!cisco.interval) if (!match("interval", &cisco.interval, 1, 100)) continue; if (!cisco.timeout) if (!match("timeout", &cisco.timeout, 1, 100)) continue; error("Invalid parameter: %s\n", argv[0]); } if (!cisco.interval) cisco.interval = 10; if (!cisco.timeout) cisco.timeout = 25; req.ifr_settings.data_length = sizeof(cisco); req.ifr_settings.data = &cisco; if (ioctl(sock, SIOCDEVICE, &req)) error("Unable to set Cisco HDLC protocol information: %s\n", strerror(errno)); } static void set_proto(void) { if (checktab(protos, &req.ifr_settings.type)) return; switch(req.ifr_settings.type) { case IF_PROTO_HDLC: set_proto_hdlc(); break; case IF_PROTO_CISCO: set_proto_cisco(); break; case IF_PROTO_FR: set_proto_fr(); break; case IF_PROTO_PPP: case IF_PROTO_X25: req.ifr_settings.data_length = 0; if (ioctl(sock, SIOCDEVICE, &req)) error("Unable to set %s protocol information: %s\n", req.ifr_settings.type == IF_PROTO_PPP ? "PPP" : "X.25", strerror(errno)); break; default: error("Unknown protocol %u\n", req.ifr_settings.type); } if (argc > 0) error("Unexpected parameter: %s\n", argv[0]); close(sock); exit(0); } static void set_pvc(void) { char *op = argv[0]; parsertab ops[] = {{ "create", IF_PROTO_FR_ADD_PVC