1/* 2 * Channel configuration utility for Cronyx serial adapters. 3 * 4 * Copyright (C) 1997-2002 Cronyx Engineering. 5 * Author: Serge Vakulenko, <vak@cronyx.ru> 6 * 7 * Copyright (C) 1999-2005 Cronyx Engineering. 8 * Author: Roman Kurakin, <rik@cronyx.ru> 9 * 10 * This software is distributed with NO WARRANTIES, not even the implied 11 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * Authors grant any other persons or organisations permission to use 14 * or modify this software as long as this message is kept with the software, 15 * all derivative works or modified versions. 16 * 17 * Cronyx Id: sconfig.c,v 1.4.2.2 2005/11/09 13:01:35 rik Exp $ 18 */ 19 20#include <sys/cdefs.h> 21__FBSDID("$FreeBSD: stable/11/sbin/sconfig/sconfig.c 358078 2020-02-18 18:15:33Z dim $"); 22 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26#include <unistd.h> 27#include <fcntl.h> 28#include <errno.h> 29#include <ctype.h> 30#include <sys/ioctl.h> 31#include <sys/types.h> 32#include <sys/stat.h> 33#include <sys/socket.h> 34#include <net/if.h> 35#include <machine/cserial.h> 36 37#define MAXCHAN 128 38 39int vflag, eflag, sflag, mflag, cflag, fflag, iflag, aflag, xflag; 40int tflag, uflag; 41char mask[64]; 42int adapter_type; /* 0-sigma, 1-tau, 2-taupci, 3-tau32 */ 43char chan_name[16]; 44 45static void 46usage (void) 47{ 48 printf( 49"Serial Adapter Configuration Utility\n" 50"Copyright (C) 1998-2005 Cronyx Engineering.\n" 51"See also man sconfig (8)\n" 52"Usage:\n" 53"\tsconfig [-aimsxeftuc] [device [parameters ...]]\n" 54"\n" 55"Options:\n" 56"\t<no options>\t\t -- print channel options\n" 57"\t-a\t\t\t -- print all settings of the channel\n" 58"\t-i\t\t\t -- print network interface status\n" 59"\t-m\t\t\t -- print modem signal status\n" 60"\t-s\t\t\t -- print channel statistics\n" 61"\t-x\t\t\t -- print extended channel statistics\n" 62"\t-e\t\t\t -- print short E1/G703 statistics\n" 63"\t-f\t\t\t -- print full E1/G703 statistics\n" 64"\t-t\t\t\t -- print short E3/T3/STS-1 statistics\n" 65"\t-u\t\t\t -- print full E3/T3/STS-1 statistics\n" 66"\t-c\t\t\t -- clear statistics\n" 67"\nParameters:\n" 68"\t<number>\t\t -- baud rate, internal clock\n" 69"\textclock\t\t -- external clock (default)\n" 70"\nProtocol options:\n" 71"\tasync\t\t\t -- asynchronous protocol\n" 72#ifdef __linux__ 73"\tsync\t\t\t -- synchronous protocol\n" 74#endif 75"\tcisco\t\t\t -- Cisco/HDLC protocol\n" 76"\tfr\t\t\t -- Frame Relay protocol\n" 77#ifdef __linux__ 78"\t dlci<number>\t -- Add new DLCI\n" 79#endif 80"\tppp\t\t\t -- PPP protocol\n" 81#ifdef __linux__ 82"\trbrg\t\t\t -- Remote bridge\n" 83"\traw\t\t\t -- raw HDLC protocol\n" 84"\tpacket\t\t\t -- packetized HDLC protocol\n" 85"\tidle\t\t\t -- no protocol\n" 86#else 87"\t keepalive={on,of}\t -- Enable/disable keepalive\n" 88#endif 89"\nInterface options:\n" 90"\tport={rs232,v35,rs449}\t -- port type (for old models of Sigma)\n" 91"\tcfg={A,B,C}\t\t -- adapter configuration\n" 92"\tloop={on,off}\t\t -- internal loopback\n" 93"\trloop={on,off}\t\t -- remote loopback\n" 94"\tdpll={on,off}\t\t -- DPLL mode\n" 95"\tnrzi={on,off}\t\t -- NRZI encoding\n" 96"\tinvclk={on,off}\t\t -- invert receive and transmit clock\n" 97"\tinvrclk={on,off}\t -- invert receive clock\n" 98"\tinvtclk={on,off}\t -- invert transmit clock\n" 99"\thigain={on,off}\t\t -- E1 high non linear input sensitivity \n\t\t\t\t (long line)\n" 100"\tmonitor={on,off}\t -- E1 high linear input sensitivity \n\t\t\t\t (interception mode)\n" 101"\tphony={on,off}\t\t -- E1 telepnony mode\n" 102"\tunfram={on,off}\t\t -- E1 unframed mode\n" 103"\tscrambler={on,off}\t -- G.703 scrambling mode\n" 104"\tuse16={on,off}\t\t -- E1 timeslot 16 usage\n" 105"\tcrc4={on,off}\t\t -- E1 CRC4 mode\n" 106#ifdef __linux__ 107"\tami={on,off}\t\t -- E1 AMI or HDB3 line code\n" 108"\tmtu={size}\t\t -- set MTU in bytes\n" 109#endif 110"\tsyn={int,rcv,rcvX}\t -- G.703 transmit clock\n" 111"\tts=...\t\t\t -- E1 timeslots\n" 112"\tpass=...\t\t -- E1 subchannel timeslots\n" 113"\tdir=<num>\t\t -- connect channel to link<num>\n" 114/*"\trqken={size}\t\t -- set receive queue length in packets\n"*/ 115/*"\tcablen={on,off}\t\t -- T3/STS-1 high transmitter output for long cable\n"*/ 116"\tdebug={0,1,2}\t\t -- enable/disable debug messages\n" 117 ); 118 exit (0); 119} 120 121static unsigned long 122scan_timeslots (char *s) 123{ 124 char *e; 125 long v; 126 int i; 127 unsigned long ts, lastv; 128 129 ts = lastv = 0; 130 for (;;) { 131 v = strtol (s, &e, 10); 132 if (e == s) 133 break; 134 if (*e == '-') { 135 lastv = v; 136 s = e+1; 137 continue; 138 } 139 if (*e == ',') 140 ++e; 141 142 if (lastv) 143 for (i=lastv; i<v; ++i) 144 ts |= 1L << i; 145 ts |= 1L << v; 146 147 lastv = 0; 148 s = e; 149 } 150 return ts; 151} 152 153static int 154ppp_ok (void) 155{ 156#ifdef __linux__ 157 int s, p; 158 struct ifreq ifr; 159 char pttyname[32]; 160 char *p1, *p2; 161 int i, j; 162 int ppp_disc = N_PPP; 163 164 /* 165 * Open a socket for doing the ioctl operations. 166 */ 167 s = socket (AF_INET, SOCK_DGRAM, 0); 168 if (s < 0) { 169 fprintf (stderr, "Error opening socket.\n"); 170 return 0; 171 } 172 strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); 173 if (ioctl (s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0) { 174 /* Ok. */ 175 close (s); 176 return 1; 177 } 178 close (s); 179 180 /* open pseudo-tty and try to set PPP discipline */ 181 sprintf (pttyname, "/dev/ptyXX"); 182 p1 = &pttyname[8]; 183 p2 = &pttyname[9]; 184 for (i=0; i<16; i++) { 185 struct stat stb; 186 187 *p1 = "pqrstuvwxyzabcde"[i]; 188 *p2 = '0'; 189 if (stat (pttyname, &stb) < 0) 190 continue; 191 for (j=0; j<16; j++) { 192 *p2 = "0123456789abcdef"[j]; 193 p = open (pttyname, 2); 194 if (p > 0) { 195 if (ioctl (p, TIOCSETD, &ppp_disc) < 0) { 196 fprintf (stderr, "No PPP discipline in kernel.\n"); 197 close (p); 198 return 0; 199 } 200 close (p); 201 return 1; 202 } 203 } 204 } 205 fprintf (stderr, "Cannot get pseudo-tty.\n"); 206 return 0; 207#else 208 return 1; 209#endif 210} 211 212static char * 213format_timeslots (unsigned long s) 214{ 215 static char buf [100]; 216 char *p = buf; 217 int i; 218 219 for (i=1; i<32; ++i) 220 if ((s >> i) & 1) { 221 int prev = (i > 1) & (s >> (i-1)); 222 int next = (i < 31) & (s >> (i+1)); 223 224 if (prev) { 225 if (next) 226 continue; 227 *p++ = '-'; 228 } else if (p > buf) 229 *p++ = ','; 230 231 if (i >= 10) 232 *p++ = '0' + i / 10; 233 *p++ = '0' + i % 10; 234 } 235 *p = 0; 236 return buf; 237} 238 239static void 240print_modems (int fd, int need_header) 241{ 242 int status; 243 244 if (ioctl (fd, TIOCMGET, &status) < 0) { 245 perror ("getting modem status"); 246 return; 247 } 248 if (need_header) 249 printf ("Channel\tLE\tDTR\tDSR\tRTS\tCTS\tCD\n"); 250 printf ("%s\t%s\t%s\t%s\t%s\t%s\t%s\n", chan_name, 251 status & TIOCM_LE ? "On" : "-", 252 status & TIOCM_DTR ? "On" : "-", 253 status & TIOCM_DSR ? "On" : "-", 254 status & TIOCM_RTS ? "On" : "-", 255 status & TIOCM_CTS ? "On" : "-", 256 status & TIOCM_CD ? "On" : "-"); 257} 258 259static void 260#ifdef __linux__ 261print_ifconfig (int fd) 262#else 263print_ifconfig (int fd __unused) 264#endif 265{ 266 char buf [64]; 267#ifdef __linux__ 268 char protocol [8]; 269 270 if (ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0 && 271 strcmp (protocol, "fr") == 0) 272 sprintf (buf, "ifconfig %sd16 2>/dev/null", chan_name); 273 else 274#endif 275 sprintf (buf, "ifconfig %s 2>/dev/null", chan_name); 276 system (buf); 277} 278 279static void 280set_debug_ifconfig (int on) 281{ 282 char buf [64]; 283 sprintf (buf, "ifconfig %s %sdebug 2>/dev/null", chan_name, 284 on ? "" : "-"); 285 system (buf); 286} 287 288static char * 289format_long (unsigned long val) 290{ 291 static char s[32]; 292 int l; 293 l = sprintf (s, "%lu", val); 294 if (l>7 && !sflag) { 295 s[3] = s[2]; 296 s[2] = s[1]; 297 s[1] = '.'; 298 s[4] = 'e'; 299 sprintf (s + 5, "%02d", l-1); 300 } 301 return s; 302} 303 304static void 305print_stats (int fd, int need_header) 306{ 307 struct serial_statistics st; 308 unsigned long sarr [9]; 309 int i; 310 311 if (ioctl (fd, SERIAL_GETSTAT, &st) < 0) { 312 perror ("getting statistics"); 313 return; 314 } 315 if (need_header) { 316 if (sflag) { 317 printf (" ------------Receive----------- " 318 "------------Transmit----------\n"); 319 printf ("Channel Interrupts Packets Errors " 320 "Interrupts Packets Errors\n"); 321 } 322 else { 323 printf (" --------Receive--------------- " 324 "--------Transmit-------------- Modem\n"); 325 printf ("Channel Intrs Bytes Packets Errors " 326 "Intrs Bytes Packets Errors Intrs\n"); 327 } 328 } 329 330 sarr [0] = st.rintr; 331 sarr [1] = st.ibytes; 332 sarr [2] = st.ipkts; 333 sarr [3] = st.ierrs; 334 sarr [4] = st.tintr; 335 sarr [5] = st.obytes; 336 sarr [6] = st.opkts; 337 sarr [7] = st.oerrs; 338 sarr [8] = st.mintr; 339 printf ("%s", chan_name); 340 if (sflag) { 341 printf ("\t%-12lu%-12lu%-12lu%-12lu%-12lu%-12lu", sarr[0], 342 sarr[2], sarr[3], sarr[4], sarr[6], sarr[7]); 343 } else { 344 for (i = 0; i < 9; i++) 345 printf ("\t%s", format_long (sarr [i])); 346 printf ("\n"); 347 } 348} 349 350static void 351clear_stats (int fd) 352{ 353 if (ioctl (fd, SERIAL_CLRSTAT, 0) < 0) { 354 perror ("clearing statistics"); 355 exit (-1); 356 } 357} 358 359static char * 360format_e1_status (unsigned long status) 361{ 362 static char buf [80]; 363 364 if (status == 0) 365 return "n/a"; 366 if (status & E1_NOALARM) 367 return "Ok"; 368 buf[0] = 0; 369 if (status & E1_LOS) strcat (buf, ",LOS"); 370 if (status & E1_AIS) strcat (buf, ",AIS"); 371 if (status & E1_LOF) strcat (buf, ",LOF"); 372 if (status & E1_LOMF) strcat (buf, ",LOMF"); 373 if (status & E1_CRC4E) strcat (buf, ",CRC4E"); 374 if (status & E1_FARLOF) strcat (buf, ",FARLOF"); 375 if (status & E1_AIS16) strcat (buf, ",AIS16"); 376 if (status & E1_FARLOMF) strcat (buf, ",FARLOMF"); 377/* if (status & E1_TSTREQ) strcat (buf, ",TSTREQ");*/ 378/* if (status & E1_TSTERR) strcat (buf, ",TSTERR");*/ 379 if (buf[0] == ',') 380 return buf+1; 381 return "Unknown"; 382} 383 384static void 385print_frac (int leftalign, unsigned long numerator, unsigned long divider) 386{ 387 int n; 388 389 if (numerator < 1 || divider < 1) { 390 printf (leftalign ? "/- " : " -"); 391 return; 392 } 393 n = (int) (0.5 + 1000.0 * numerator / divider); 394 if (n < 1000) { 395 printf (leftalign ? "/.%-3d" : " .%03d", n); 396 return; 397 } 398 putchar (leftalign ? '/' : ' '); 399 400 if (n >= 1000000) n = (n+500) / 1000 * 1000; 401 else if (n >= 100000) n = (n+50) / 100 * 100; 402 else if (n >= 10000) n = (n+5) / 10 * 10; 403 404 switch (n) { 405 case 1000: printf (".999"); return; 406 case 10000: n = 9990; break; 407 case 100000: n = 99900; break; 408 case 1000000: n = 999000; break; 409 } 410 if (n < 10000) printf ("%d.%d", n/1000, n/10%100); 411 else if (n < 100000) printf ("%d.%d", n/1000, n/100%10); 412 else if (n < 1000000) printf ("%d.", n/1000); 413 else printf ("%d", n/1000); 414} 415 416static void 417print_e1_stats (int fd, int need_header) 418{ 419 struct e1_statistics st; 420 int i, maxi; 421 422 if (need_header) 423 printf ("Chan\t Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n"); 424 425 if (ioctl (fd, SERIAL_GETESTAT, &st) < 0) 426 return; 427 printf ("%s\t", chan_name); 428 429 /* Unavailable seconds, degraded minutes */ 430 print_frac (0, st.currnt.uas, st.cursec); 431 print_frac (1, 60 * st.currnt.dm, st.cursec); 432 433 /* Bipolar violations, frame sync errors */ 434 print_frac (0, st.currnt.bpv, st.cursec); 435 print_frac (1, st.currnt.fse, st.cursec); 436 437 /* CRC errors, remote CRC errors (E-bit) */ 438 print_frac (0, st.currnt.crce, st.cursec); 439 print_frac (1, st.currnt.rcrce, st.cursec); 440 441 /* Errored seconds, line errored seconds */ 442 print_frac (0, st.currnt.es, st.cursec); 443 print_frac (1, st.currnt.les, st.cursec); 444 445 /* Severely errored seconds, bursty errored seconds */ 446 print_frac (0, st.currnt.ses, st.cursec); 447 print_frac (1, st.currnt.bes, st.cursec); 448 449 /* Out of frame seconds, controlled slip seconds */ 450 print_frac (0, st.currnt.oofs, st.cursec); 451 print_frac (1, st.currnt.css, st.cursec); 452 453 printf (" %s\n", format_e1_status (st.status)); 454 455 if (fflag) { 456 /* Print total statistics. */ 457 printf ("\t"); 458 print_frac (0, st.total.uas, st.totsec); 459 print_frac (1, 60 * st.total.dm, st.totsec); 460 461 print_frac (0, st.total.bpv, st.totsec); 462 print_frac (1, st.total.fse, st.totsec); 463 464 print_frac (0, st.total.crce, st.totsec); 465 print_frac (1, st.total.rcrce, st.totsec); 466 467 print_frac (0, st.total.es, st.totsec); 468 print_frac (1, st.total.les, st.totsec); 469 470 print_frac (0, st.total.ses, st.totsec); 471 print_frac (1, st.total.bes, st.totsec); 472 473 print_frac (0, st.total.oofs, st.totsec); 474 print_frac (1, st.total.css, st.totsec); 475 476 printf (" -- Total\n"); 477 478 /* Print 24-hour history. */ 479 maxi = (st.totsec - st.cursec) / 900; 480 if (maxi > 48) 481 maxi = 48; 482 for (i=0; i<maxi; ++i) { 483 printf (" "); 484 print_frac (0, st.interval[i].uas, 15*60); 485 print_frac (1, 60 * st.interval[i].dm, 15*60); 486 487 print_frac (0, st.interval[i].bpv, 15*60); 488 print_frac (1, st.interval[i].fse, 15*60); 489 490 print_frac (0, st.interval[i].crce, 15*60); 491 print_frac (1, st.interval[i].rcrce, 15*60); 492 493 print_frac (0, st.interval[i].es, 15*60); 494 print_frac (1, st.interval[i].les, 15*60); 495 496 print_frac (0, st.interval[i].ses, 15*60); 497 print_frac (1, st.interval[i].bes, 15*60); 498 499 print_frac (0, st.interval[i].oofs, 15*60); 500 print_frac (1, st.interval[i].css, 15*60); 501 502 if (i < 3) 503 printf (" -- %dm\n", (i+1)*15); 504 else 505 printf (" -- %dh %dm\n", (i+1)/4, (i+1)%4*15); 506 } 507 } 508} 509 510static char * 511format_e3_status (unsigned long status) 512{ 513 static char buf [80]; 514 515 buf[0] = 0; 516 if (status & E3_LOS) strcat (buf, ",LOS"); 517 if (status & E3_TXE) strcat (buf, ",XMIT"); 518 if (buf[0] == ',') 519 return buf+1; 520 return "Ok"; 521} 522 523static char * 524format_e3_cv (unsigned long cv, unsigned long baud, unsigned long atime) 525{ 526 static char buf[80]; 527 528 if (!cv || !baud || !atime) 529 sprintf (buf, " - "); 530 else 531 sprintf (buf, "%10lu (%.1e)", cv, (double)cv/baud/atime); 532 return buf; 533} 534 535static void 536print_e3_stats (int fd, int need_header) 537{ 538 struct e3_statistics st; 539 int i, maxi; 540 long baud; 541 542 if (need_header) 543 printf ("Chan\t--Code Violations---\t\t\t\t\t ----Status----\n"); 544 545 if (ioctl (fd, SERIAL_GETE3STAT, &st) < 0 || 546 ioctl (fd, SERIAL_GETBAUD, &baud) < 0) 547 return; 548 549 if (!st.cursec) 550 st.cursec = 1; 551 552 printf ("%s\t%s\t\t\t\t\t", chan_name, 553 format_e3_cv (st.ccv, baud, st.cursec)); 554 555 printf (" %s\n", format_e3_status (st.status)); 556 557 558 if (uflag) { 559 /* Print total statistics. */ 560 printf ("\t%s\t\t\t\t\t", 561 format_e3_cv (st.tcv, baud, st.totsec)); 562 printf (" -- Total\n"); 563 564 /* Print 24-hour history. */ 565 maxi = (st.totsec - st.cursec) / 900; 566 if (maxi > 48) 567 maxi = 48; 568 for (i=0; i<maxi; ++i) { 569 printf ("\t%s\t\t\t\t\t", 570 format_e3_cv (st.icv[i], baud, 15*60)); 571 if (i < 3) 572 printf (" -- %2dm\n", (i+1)*15); 573 else 574 printf (" -- %2dh %2dm\n", (i+1)/4, (i+1)%4*15); 575 } 576 } 577} 578 579static void 580print_chan (int fd) 581{ 582 char protocol [8]; 583 char cfg; 584 int loop, dpll, nrzi, invclk, clk, higain, phony, use16, crc4; 585 int level, keepalive, debug, port, invrclk, invtclk, unfram, monitor; 586 int cable, dir, scrambler, ami, mtu; 587 int cablen, rloop, rqlen; 588 long baud, timeslots, subchan; 589 int protocol_valid, baud_valid, loop_valid, use16_valid, crc4_valid; 590 int dpll_valid, nrzi_valid, invclk_valid, clk_valid, phony_valid; 591 int timeslots_valid, subchan_valid, higain_valid, level_valid; 592 int keepalive_valid, debug_valid, cfg_valid, port_valid; 593 int invrclk_valid, invtclk_valid, unfram_valid, monitor_valid; 594 int cable_valid, dir_valid, scrambler_valid, ami_valid, mtu_valid; 595 int cablen_valid, rloop_valid, rqlen_valid; 596 597 protocol_valid = ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0; 598 cfg_valid = ioctl (fd, SERIAL_GETCFG, &cfg) >= 0; 599 baud_valid = ioctl (fd, SERIAL_GETBAUD, &baud) >= 0; 600 loop_valid = ioctl (fd, SERIAL_GETLOOP, &loop) >= 0; 601 dpll_valid = ioctl (fd, SERIAL_GETDPLL, &dpll) >= 0; 602 nrzi_valid = ioctl (fd, SERIAL_GETNRZI, &nrzi) >= 0; 603 invclk_valid = ioctl (fd, SERIAL_GETINVCLK, &invclk) >= 0; 604 invrclk_valid = ioctl (fd, SERIAL_GETINVRCLK, &invrclk) >= 0; 605 invtclk_valid = ioctl (fd, SERIAL_GETINVTCLK, &invtclk) >= 0; 606 clk_valid = ioctl (fd, SERIAL_GETCLK, &clk) >= 0; 607 timeslots_valid = ioctl (fd, SERIAL_GETTIMESLOTS, ×lots) >= 0; 608 subchan_valid = ioctl (fd, SERIAL_GETSUBCHAN, &subchan) >= 0; 609 higain_valid = ioctl (fd, SERIAL_GETHIGAIN, &higain) >= 0; 610 phony_valid = ioctl (fd, SERIAL_GETPHONY, &phony) >= 0; 611 unfram_valid = ioctl (fd, SERIAL_GETUNFRAM, &unfram) >= 0; 612 monitor_valid = ioctl (fd, SERIAL_GETMONITOR, &monitor) >= 0; 613 use16_valid = ioctl (fd, SERIAL_GETUSE16, &use16) >= 0; 614 crc4_valid = ioctl (fd, SERIAL_GETCRC4, &crc4) >= 0; 615 ami_valid = ioctl (fd, SERIAL_GETLCODE, &ami) >= 0; 616 level_valid = ioctl (fd, SERIAL_GETLEVEL, &level) >= 0; 617 keepalive_valid = ioctl (fd, SERIAL_GETKEEPALIVE, &keepalive) >= 0; 618 debug_valid = ioctl (fd, SERIAL_GETDEBUG, &debug) >= 0; 619 port_valid = ioctl (fd, SERIAL_GETPORT, &port) >= 0; 620 cable_valid = ioctl (fd, SERIAL_GETCABLE, &cable) >= 0; 621 dir_valid = ioctl (fd, SERIAL_GETDIR, &dir) >= 0; 622 scrambler_valid = ioctl (fd, SERIAL_GETSCRAMBLER, &scrambler) >= 0; 623 cablen_valid = ioctl (fd, SERIAL_GETCABLEN, &cablen) >= 0; 624 rloop_valid = ioctl (fd, SERIAL_GETRLOOP, &rloop) >= 0; 625 mtu_valid = ioctl (fd, SERIAL_GETMTU, &mtu) >= 0; 626 rqlen_valid = ioctl (fd, SERIAL_GETRQLEN, &rqlen) >= 0; 627 628 printf ("%s", chan_name); 629 if (port_valid) 630 switch (port) { 631 case 0: printf (" (rs232)"); break; 632 case 1: printf (" (v35)"); break; 633 case 2: printf (" (rs530)"); break; 634 } 635 else if (cable_valid) 636 switch (cable) { 637 case 0: printf (" (rs232)"); break; 638 case 1: printf (" (v35)"); break; 639 case 2: printf (" (rs530)"); break; 640 case 3: printf (" (x21)"); break; 641 case 4: printf (" (rs485)"); break; 642 case 9: printf (" (no cable)"); break; 643 } 644 if (debug_valid && debug) 645 printf (" debug=%d", debug); 646 if (protocol_valid && *protocol) 647 printf (" %.8s", protocol); 648 else 649 printf (" idle"); 650 if (cablen_valid) 651 printf (" cablen=%s", cablen ? "on" : "off"); 652 if (keepalive_valid) 653 printf (" keepalive=%s", keepalive ? "on" : "off"); 654 655 if (cfg_valid) 656 switch (cfg) { 657 case 'a' : printf (" cfg=A"); break; 658 case 'b' : printf (" cfg=B"); break; 659 case 'c' : printf (" cfg=C"); break; 660 case 'd' : printf (" cfg=D"); break; 661 default : printf (" cfg=unknown"); 662 } 663 if (dir_valid) 664 printf (" dir=%d", dir); 665 666 if (baud_valid) { 667 if (baud) 668 printf (" %ld", baud); 669 else 670 printf (" extclock"); 671 } 672 if (mtu_valid) 673 printf (" mtu=%d", mtu); 674 675 if (aflag && rqlen_valid) 676 printf (" rqlen=%d", rqlen); 677 678 if (clk_valid) 679 switch (clk) { 680 case E1CLK_INTERNAL: printf (" syn=int"); break; 681 case E1CLK_RECEIVE: printf (" syn=rcv"); break; 682 case E1CLK_RECEIVE_CHAN0: printf (" syn=rcv0"); break; 683 case E1CLK_RECEIVE_CHAN1: printf (" syn=rcv1"); break; 684 case E1CLK_RECEIVE_CHAN2: printf (" syn=rcv2"); break; 685 case E1CLK_RECEIVE_CHAN3: printf (" syn=rcv3"); break; 686 default: printf (" syn=%d", clk); break; 687 } 688 689 if (dpll_valid) 690 printf (" dpll=%s", dpll ? "on" : "off"); 691 if (nrzi_valid) 692 printf (" nrzi=%s", nrzi ? "on" : "off"); 693 if (invclk_valid) 694 printf (" invclk=%s", invclk ? "on" : "off"); 695 if (invrclk_valid) 696 printf (" invrclk=%s", invrclk ? "on" : "off"); 697 if (invtclk_valid) 698 printf (" invtclk=%s", invtclk ? "on" : "off"); 699 if (unfram_valid) 700 printf (" unfram=%s", unfram ? "on" : "off"); 701 if (use16_valid) 702 printf (" use16=%s", use16 ? "on" : "off"); 703 if (aflag) { 704 if (crc4_valid) 705 printf (" crc4=%s", crc4 ? "on" : "off"); 706 if (higain_valid) 707 printf (" higain=%s", higain ? "on" : "off"); 708 if (monitor_valid) 709 printf (" monitor=%s", monitor ? "on" : "off"); 710 if (phony_valid) 711 printf (" phony=%s", phony ? "on" : "off"); 712 if (scrambler_valid) 713 printf (" scrambler=%s", scrambler ? "on" : "off"); 714 if (loop_valid) 715 printf (" loop=%s", loop ? "on" : "off"); 716 if (rloop_valid) 717 printf (" rloop=%s", rloop ? "on" : "off"); 718 if (ami_valid) 719 printf (" ami=%s", ami ? "on" : "off"); 720 } 721 if (timeslots_valid) 722 printf (" ts=%s", format_timeslots (timeslots)); 723 if (subchan_valid) 724 printf (" pass=%s", format_timeslots (subchan)); 725 if (level_valid) 726 printf (" (level=-%.1fdB)", level / 10.0); 727 printf ("\n"); 728} 729 730static void 731setup_chan (int fd, int argc, char **argv) 732{ 733 int i, mode, loop, nrzi, dpll, invclk, phony, use16, crc4, unfram, ami; 734 int higain, clk, keepalive, debug, port, dlci, invrclk, invtclk; 735 int monitor, dir, scrambler, rloop, cablen; 736 int mode_valid; 737 long baud, timeslots, mtu, rqlen; 738 739 for (i=0; i<argc; ++i) { 740 if (argv[i][0] >= '0' && argv[i][0] <= '9') { 741 baud = strtol (argv[i], 0, 10); 742 ioctl (fd, SERIAL_SETBAUD, &baud); 743 } else if (strcasecmp ("extclock", argv[i]) == 0) { 744 baud = 0; 745 ioctl (fd, SERIAL_SETBAUD, &baud); 746 } else if (strncasecmp ("cfg=", argv[i], 4) == 0) { 747 if (strncasecmp ("a", argv[i]+4, 1) == 0) 748 ioctl (fd, SERIAL_SETCFG, "a"); 749 else if (strncasecmp ("b", argv[i]+4, 1) == 0) 750 ioctl (fd, SERIAL_SETCFG, "b"); 751 else if (strncasecmp ("c", argv[i]+4, 1) == 0) 752 ioctl (fd, SERIAL_SETCFG, "c"); 753 else if (strncasecmp ("d", argv[i]+4, 1) == 0) 754 ioctl (fd, SERIAL_SETCFG, "d"); 755 else { 756 fprintf (stderr, "invalid cfg\n"); 757 exit (-1); 758 } 759 } else if (strcasecmp ("idle", argv[i]) == 0) 760 ioctl (fd, SERIAL_SETPROTO, "\0\0\0\0\0\0\0"); 761 else if (strcasecmp ("async", argv[i]) == 0) { 762 mode = SERIAL_ASYNC; 763 if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0) 764 ioctl (fd, SERIAL_SETPROTO, "async\0\0"); 765 } else if (strcasecmp ("sync", argv[i]) == 0) { 766 mode = SERIAL_HDLC; 767 if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0) 768 ioctl (fd, SERIAL_SETPROTO, "sync\0\0\0"); 769 } else if (strcasecmp ("cisco", argv[i]) == 0) { 770 mode = SERIAL_HDLC; 771 ioctl (fd, SERIAL_SETMODE, &mode); 772 ioctl (fd, SERIAL_SETPROTO, "cisco\0\0"); 773 } else if (strcasecmp ("rbrg", argv[i]) == 0) { 774 mode = SERIAL_HDLC; 775 ioctl (fd, SERIAL_SETMODE, &mode); 776 ioctl (fd, SERIAL_SETPROTO, "rbrg\0\0\0"); 777 } else if (strcasecmp ("raw", argv[i]) == 0) { 778 mode = SERIAL_HDLC; 779 ioctl (fd, SERIAL_SETMODE, &mode); 780 ioctl (fd, SERIAL_SETPROTO, "raw\0\0\0\0"); 781 } else if (strcasecmp ("packet", argv[i]) == 0) { 782 mode = SERIAL_HDLC; 783 ioctl (fd, SERIAL_SETMODE, &mode); 784 ioctl (fd, SERIAL_SETPROTO, "packet\0"); 785 } else if (strcasecmp ("ppp", argv[i]) == 0) { 786 /* check that ppp line discipline is present */ 787 if (ppp_ok ()) { 788 mode = SERIAL_HDLC; 789 ioctl (fd, SERIAL_SETMODE, &mode); 790 ioctl (fd, SERIAL_SETPROTO, "ppp\0\0\0\0"); 791 } 792 } else if (strncasecmp ("keepalive=", argv[i], 10) == 0) { 793 keepalive = (strcasecmp ("on", argv[i] + 10) == 0); 794 ioctl (fd, SERIAL_SETKEEPALIVE, &keepalive); 795 } else if (strcasecmp ("fr", argv[i]) == 0) { 796 mode = SERIAL_HDLC; 797 ioctl (fd, SERIAL_SETMODE, &mode); 798 ioctl (fd, SERIAL_SETPROTO, "fr\0\0\0\0\0"); 799 } else if (strcasecmp ("zaptel", argv[i]) == 0) { 800 mode = SERIAL_HDLC; 801 ioctl (fd, SERIAL_SETMODE, &mode); 802 ioctl (fd, SERIAL_SETPROTO, "zaptel\0"); 803 } else if (strncasecmp ("debug=", argv[i], 6) == 0) { 804 debug = strtol (argv[i]+6, 0, 10); 805 mode_valid = ioctl (fd, SERIAL_GETMODE, &mode) >= 0; 806 if (!mode_valid || mode != SERIAL_ASYNC) { 807 if (debug == 0) { 808 set_debug_ifconfig(0); 809 } else { 810 ioctl (fd, SERIAL_SETDEBUG, &debug); 811 set_debug_ifconfig(1); 812 } 813 } else { 814 ioctl (fd, SERIAL_SETDEBUG, &debug); 815 } 816 } else if (strncasecmp ("loop=", argv[i], 5) == 0) { 817 loop = (strcasecmp ("on", argv[i] + 5) == 0); 818 ioctl (fd, SERIAL_SETLOOP, &loop); 819 } else if (strncasecmp ("rloop=", argv[i], 6) == 0) { 820 rloop = (strcasecmp ("on", argv[i] + 6) == 0); 821 ioctl (fd, SERIAL_SETRLOOP, &rloop); 822 } else if (strncasecmp ("dpll=", argv[i], 5) == 0) { 823 dpll = (strcasecmp ("on", argv[i] + 5) == 0); 824 ioctl (fd, SERIAL_SETDPLL, &dpll); 825 } else if (strncasecmp ("nrzi=", argv[i], 5) == 0) { 826 nrzi = (strcasecmp ("on", argv[i] + 5) == 0); 827 ioctl (fd, SERIAL_SETNRZI, &nrzi); 828 } else if (strncasecmp ("invclk=", argv[i], 7) == 0) { 829 invclk = (strcasecmp ("on", argv[i] + 7) == 0); 830 ioctl (fd, SERIAL_SETINVCLK, &invclk); 831 } else if (strncasecmp ("invrclk=", argv[i], 8) == 0) { 832 invrclk = (strcasecmp ("on", argv[i] + 8) == 0); 833 ioctl (fd, SERIAL_SETINVRCLK, &invrclk); 834 } else if (strncasecmp ("invtclk=", argv[i], 8) == 0) { 835 invtclk = (strcasecmp ("on", argv[i] + 8) == 0); 836 ioctl (fd, SERIAL_SETINVTCLK, &invtclk); 837 } else if (strncasecmp ("higain=", argv[i], 7) == 0) { 838 higain = (strcasecmp ("on", argv[i] + 7) == 0); 839 ioctl (fd, SERIAL_SETHIGAIN, &higain); 840 } else if (strncasecmp ("phony=", argv[i], 6) == 0) { 841 phony = (strcasecmp ("on", argv[i] + 6) == 0); 842 ioctl (fd, SERIAL_SETPHONY, &phony); 843 } else if (strncasecmp ("unfram=", argv[i], 7) == 0) { 844 unfram = (strcasecmp ("on", argv[i] + 7) == 0); 845 ioctl (fd, SERIAL_SETUNFRAM, &unfram); 846 } else if (strncasecmp ("scrambler=", argv[i], 10) == 0) { 847 scrambler = (strcasecmp ("on", argv[i] + 10) == 0); 848 ioctl (fd, SERIAL_SETSCRAMBLER, &scrambler); 849 } else if (strncasecmp ("monitor=", argv[i], 8) == 0) { 850 monitor = (strcasecmp ("on", argv[i] + 8) == 0); 851 ioctl (fd, SERIAL_SETMONITOR, &monitor); 852 } else if (strncasecmp ("use16=", argv[i], 6) == 0) { 853 use16 = (strcasecmp ("on", argv[i] + 6) == 0); 854 ioctl (fd, SERIAL_SETUSE16, &use16); 855 } else if (strncasecmp ("crc4=", argv[i], 5) == 0) { 856 crc4 = (strcasecmp ("on", argv[i] + 5) == 0); 857 ioctl (fd, SERIAL_SETCRC4, &crc4); 858 } else if (strncasecmp ("ami=", argv[i], 4) == 0) { 859 ami = (strcasecmp ("on", argv[i] + 4) == 0); 860 ioctl (fd, SERIAL_SETLCODE, &ami); 861 } else if (strncasecmp ("mtu=", argv[i], 4) == 0) { 862 mtu = strtol (argv[i] + 4, 0, 10); 863 ioctl (fd, SERIAL_SETMTU, &mtu); 864 } else if (strncasecmp ("rqlen=", argv[i], 6) == 0) { 865 rqlen = strtol (argv[i] + 6, 0, 10); 866 ioctl (fd, SERIAL_SETRQLEN, &rqlen); 867 } else if (strcasecmp ("syn=int", argv[i]) == 0) { 868 clk = E1CLK_INTERNAL; 869 ioctl (fd, SERIAL_SETCLK, &clk); 870 } else if (strcasecmp ("syn=rcv", argv[i]) == 0) { 871 clk = E1CLK_RECEIVE; 872 ioctl (fd, SERIAL_SETCLK, &clk); 873 } else if (strcasecmp ("syn=rcv0", argv[i]) == 0) { 874 clk = E1CLK_RECEIVE_CHAN0; 875 ioctl (fd, SERIAL_SETCLK, &clk); 876 } else if (strcasecmp ("syn=rcv1", argv[i]) == 0) { 877 clk = E1CLK_RECEIVE_CHAN1; 878 ioctl (fd, SERIAL_SETCLK, &clk); 879 } else if (strcasecmp ("syn=rcv2", argv[i]) == 0) { 880 clk = E1CLK_RECEIVE_CHAN2; 881 ioctl (fd, SERIAL_SETCLK, &clk); 882 } else if (strcasecmp ("syn=rcv3", argv[i]) == 0) { 883 clk = E1CLK_RECEIVE_CHAN3; 884 ioctl (fd, SERIAL_SETCLK, &clk); 885 } else if (strncasecmp ("ts=", argv[i], 3) == 0) { 886 timeslots = scan_timeslots (argv[i] + 3); 887 ioctl (fd, SERIAL_SETTIMESLOTS, ×lots); 888 } else if (strncasecmp ("pass=", argv[i], 5) == 0) { 889 timeslots = scan_timeslots (argv[i] + 5); 890 ioctl (fd, SERIAL_SETSUBCHAN, ×lots); 891 } else if (strncasecmp ("dlci", argv[i], 4) == 0) { 892 dlci = strtol (argv[i]+4, 0, 10); 893 ioctl (fd, SERIAL_ADDDLCI, &dlci); 894 } else if (strncasecmp ("dir=", argv[i], 4) == 0) { 895 dir = strtol (argv[i]+4, 0, 10); 896 ioctl (fd, SERIAL_SETDIR, &dir); 897 } else if (strncasecmp ("port=", argv[i], 5) == 0) { 898 if (strncasecmp ("rs232", argv[i]+5, 5) == 0) { 899 port = 0; 900 ioctl (fd, SERIAL_SETPORT, &port); 901 } else if (strncasecmp ("v35", argv[i]+5, 3) == 0) { 902 port = 1; 903 ioctl (fd, SERIAL_SETPORT, &port); 904 } else if (strncasecmp ("rs449", argv[i]+5, 5) == 0) { 905 port = 2; 906 ioctl (fd, SERIAL_SETPORT, &port); 907 } else { 908 fprintf (stderr, "invalid port type\n"); 909 exit (-1); 910 } 911#if 1 912 } else if (strcasecmp ("reset", argv[i]) == 0) { 913 ioctl (fd, SERIAL_RESET, 0); 914 } else if (strcasecmp ("hwreset", argv[i]) == 0) { 915 ioctl (fd, SERIAL_HARDRESET, 0); 916#endif 917 } else if (strncasecmp ("cablen=", argv[i], 7) == 0) { 918 loop = (strcasecmp ("on", argv[i] + 7) == 0); 919 ioctl (fd, SERIAL_SETCABLEN, &cablen); 920 } 921 } 922} 923 924static void 925get_mask (void) 926{ 927#ifdef __linux__ 928 int fd; 929 930 fd = open ("/dev/serial/ctl0", 0); 931 if (fd < 0) { 932 perror ("/dev/serial/ctl0"); 933 exit (-1); 934 } 935 if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) { 936 perror ("getting list of channels"); 937 exit (-1); 938 } 939 close (fd); 940#else 941 int fd, fd1, fd2, fd3, i; 942 char buf [80]; 943 944 for (i=0, fd=-1; i<12 && fd<0; i++) { 945 sprintf (buf, "/dev/cx%d", i*4); 946 fd = open (buf, 0); 947 } 948 949 for (i=0, fd1=-1; i<3 && fd1<0; i++) { 950 sprintf (buf, "/dev/ct%d", i*2); 951 fd1 = open (buf, 0); 952 } 953 954 for (i=0, fd2=-1; i<3 && fd2<0; i++) { 955 sprintf (buf, "/dev/cp%d", i*4); 956 fd2 = open (buf, 0); 957 } 958 959 /* Try only one */ 960 for (i=0, fd3=-1; i<1 && fd3<0; i++) { 961 sprintf (buf, "/dev/ce%d", i*4); 962 fd3 = open (buf, 0); 963 } 964 965 if ((fd < 0) && (fd1 < 0) && (fd2 < 0) && (fd3 < 0)) { 966 fprintf (stderr, "No Cronyx adapters installed\n"); 967 exit (-1); 968 } 969 970 if (fd >= 0) { 971 if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) { 972 perror ("getting list of channels"); 973 exit (-1); 974 } 975 close (fd); 976 } 977 978 if (fd1 >= 0) { 979 if (ioctl (fd1, SERIAL_GETREGISTERED, (mask+16)) < 0) { 980 perror ("getting list of channels"); 981 exit (-1); 982 } 983 close (fd1); 984 } 985 986 if (fd2 >= 0) { 987 if (ioctl (fd2, SERIAL_GETREGISTERED, (mask+32)) < 0) { 988 perror ("getting list of channels"); 989 exit (-1); 990 } 991 close (fd2); 992 } 993 994 if (fd3 >= 0) { 995 if (ioctl (fd3, SERIAL_GETREGISTERED, (mask+48)) < 0) { 996 perror ("getting list of channels"); 997 exit (-1); 998 } 999 close (fd3); 1000 } 1001#endif 1002} 1003 1004static int 1005open_chan_ctl (int num) 1006{ 1007 char device [80]; 1008 int fd; 1009 1010#ifdef __linux__ 1011 sprintf (device, "/dev/serial/ctl%d", num); 1012#else 1013 switch (adapter_type) { 1014 case 0: 1015 sprintf (device, "/dev/cx%d", num); 1016 break; 1017 case 1: 1018 sprintf (device, "/dev/ct%d", num); 1019 break; 1020 case 2: 1021 sprintf (device, "/dev/cp%d", num); 1022 break; 1023 case 3: 1024 sprintf (device, "/dev/ce%d", num); 1025 break; 1026 } 1027#endif 1028 fd = open (device, 0); 1029 if (fd < 0) { 1030 if (errno == ENODEV) 1031 fprintf (stderr, "chan%d: not configured\n", num); 1032 else 1033 perror (device); 1034 exit (-1); 1035 } 1036#ifdef __linux__ 1037 if (ioctl (fd, SERIAL_GETNAME, &chan_name) < 0) 1038 sprintf (chan_name, "chan%d", num); 1039#else 1040 switch (adapter_type) { 1041 case 0: sprintf (chan_name, "cx%d", num); break; 1042 case 1: sprintf (chan_name, "ct%d", num); break; 1043 case 2: sprintf (chan_name, "cp%d", num); break; 1044 case 3: sprintf (chan_name, "ce%d", num); break; 1045 } 1046#endif 1047 return fd; 1048} 1049 1050int 1051main (int argc, char **argv) 1052{ 1053 char *p; 1054 int fd, need_header, chan_num; 1055 1056 if (argc > 1 && strcmp(argv[1], "help") == 0) 1057 usage(); 1058 1059 for (;;) { 1060 switch (getopt (argc, argv, "mseftucviax")) { 1061 case -1: 1062 break; 1063 case 'a': 1064 ++aflag; 1065 continue; 1066 case 'm': 1067 ++mflag; 1068 continue; 1069 case 's': 1070 ++sflag; 1071 continue; 1072 case 'e': 1073 ++eflag; 1074 continue; 1075 case 'f': 1076 ++eflag; 1077 ++fflag; 1078 continue; 1079 case 't': 1080 ++tflag; 1081 continue; 1082 case 'u': 1083 ++tflag; 1084 ++uflag; 1085 continue; 1086 case 'c': 1087 ++cflag; 1088 continue; 1089 case 'v': 1090 ++vflag; 1091 continue; 1092 case 'i': 1093 ++iflag; 1094 continue; 1095 case 'x': 1096 ++xflag; 1097 continue; 1098 default: 1099 usage(); 1100 } 1101 break; 1102 } 1103 argc -= optind; 1104 argv += optind; 1105 1106 if (argc <= 0) { 1107 get_mask (); 1108 need_header = 1; 1109 adapter_type = 0; 1110#ifndef __linux__ 1111 for (; adapter_type < 4; ++adapter_type) 1112#endif 1113 { 1114 for (chan_num=0; chan_num<MAXCHAN; ++chan_num) 1115 if (mask[adapter_type*16+chan_num/8] & 1 << (chan_num & 7)) { 1116 fd = open_chan_ctl (chan_num); 1117 if (vflag) { 1118#ifdef __linux__ 1119 char buf[256]; 1120 if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0) { 1121 printf ("Version: %s\n", buf); 1122 close (fd); 1123 return (0); 1124 } 1125#endif 1126 } 1127 if (iflag) { 1128 print_chan (fd); 1129 print_ifconfig (fd); 1130 } else if (sflag||xflag) 1131 print_stats (fd, need_header); 1132 else if (mflag) 1133 print_modems (fd, need_header); 1134 else if (eflag) 1135 print_e1_stats (fd, need_header); 1136 else if (tflag) 1137 print_e3_stats (fd, need_header); 1138 else if (cflag) 1139 clear_stats (fd); 1140 else 1141 print_chan (fd); 1142 close (fd); 1143 need_header = 0; 1144 } 1145 } 1146 return (0); 1147 } 1148 1149 p = argv[0] + strlen (argv[0]); 1150 while (p > argv[0] && p[-1] >= '0' && p[-1] <= '9') 1151 --p; 1152 chan_num = strtol (p, 0, 10); 1153#ifndef __linux__ 1154 if (strncasecmp ("cx", argv[0], 2)==0) 1155 adapter_type = 0; 1156 else if (strncasecmp ("ct", argv[0], 2)==0) 1157 adapter_type = 1; 1158 else if (strncasecmp ("cp", argv[0], 2)==0) 1159 adapter_type = 2; 1160 else if (strncasecmp ("ce", argv[0], 2)==0) 1161 adapter_type = 3; 1162 else { 1163 fprintf (stderr, "Wrong channel name\n"); 1164 exit (-1); 1165 } 1166#endif 1167 argc--; 1168 argv++; 1169 1170 fd = open_chan_ctl (chan_num); 1171 if (vflag) { 1172#ifdef __linux__ 1173 char buf[256]; 1174 if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0) 1175 printf ("Version: %s\n", buf); 1176#endif 1177 } 1178 if (iflag) { 1179 print_chan (fd); 1180 print_ifconfig (fd); 1181 close (fd); 1182 return (0); 1183 } 1184 if (sflag||xflag) { 1185 print_stats (fd, 1); 1186 close (fd); 1187 return (0); 1188 } 1189 if (mflag) { 1190 print_modems (fd, 1); 1191 close (fd); 1192 return (0); 1193 } 1194 if (eflag) { 1195 print_e1_stats (fd, 1); 1196 close (fd); 1197 return (0); 1198 } 1199 if (tflag) { 1200 print_e3_stats (fd, 1); 1201 close (fd); 1202 return (0); 1203 } 1204 if (cflag) { 1205 clear_stats (fd); 1206 close (fd); 1207 return (0); 1208 } 1209 if (argc > 0) 1210 setup_chan (fd, argc, argv); 1211 else 1212 print_chan (fd); 1213 close (fd); 1214 return (0); 1215} 1216