1 /*
2 * ser2net - A program for allowing telnet connection to serial ports
3 * Copyright (C) 2001 Corey Minyard <minyard@acm.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /* This code handles generating the configuration for the serial port. */
21 #include <unistd.h>
22 #include <termios.h>
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <signal.h>
31 #include <errno.h>
32 #include <syslog.h>
33
34 #include "ser2net.h"
35 #include "selector.h"
36 #include "utils.h"
37 #include "dataxfer.h"
38 #include "devio.h"
39
40 #include <assert.h>
41
42 struct devcfg_data {
43 /* Information about the terminal device. */
44 char *devname; /* The full path to the device */
45 int devfd; /* The file descriptor for the
46 device, only valid if the
47 TCP port is open. */
48 struct termios termctl;
49
50 void (*shutdown_done)(struct devio *);
51
52 int default_bps;
53 int default_data_size;
54 int default_stop_bits;
55 int default_parity_on;
56 int current_bps;
57 int current_data_size;
58 int current_stop_bits;
59 int current_parity_on;
60
61 /* Holds whether break is on or not. */
62 int break_set;
63
64 /* Disable break-commands */
65 int disablebreak;
66
67 #if HAVE_DECL_TIOCSRS485
68 struct serial_rs485 *conf;
69 #endif
70 };
71
72 static struct baud_rates_s {
73 int real_rate;
74 int val;
75 int cisco_ios_val;
76 } baud_rates[] =
77 {
78 { 50, B50, -1 },
79 { 75, B75, -1 },
80 { 110, B110, -1 },
81 { 134, B134, -1 },
82 { 150, B150, -1 },
83 { 200, B200, -1 },
84 { 300, B300, 3 },
85 { 600, B600 , 4},
86 { 1200, B1200, 5 },
87 { 1800, B1800, -1 },
88 { 2400, B2400, 6 },
89 { 4800, B4800, 7 },
90 { 9600, B9600, 8 },
91 /* We don't support 14400 baud */
92 { 19200, B19200, 10 },
93 /* We don't support 28800 baud */
94 { 38400, B38400, 12 },
95 { 57600, B57600, 13 },
96 { 115200, B115200, 14 },
97 { 230400, B230400, 15 },
98 /* We don't support 460800 baud */
99 };
100 #define BAUD_RATES_LEN ((sizeof(baud_rates) / sizeof(struct baud_rates_s)))
101
102 static int
get_baud_rate(int rate,int * val,int cisco,int * bps)103 get_baud_rate(int rate, int *val, int cisco, int *bps)
104 {
105 unsigned int i;
106 for (i = 0; i < BAUD_RATES_LEN; i++) {
107 if (cisco) {
108 if (rate == baud_rates[i].cisco_ios_val) {
109 *val = baud_rates[i].val;
110 *bps = baud_rates[i].real_rate;
111 return 1;
112 }
113 } else {
114 if (rate == baud_rates[i].real_rate) {
115 *val = baud_rates[i].val;
116 *bps = baud_rates[i].real_rate;
117 return 1;
118 }
119 }
120 }
121
122 return 0;
123 }
124
125 static void
get_rate_from_baud_rate(int baud_rate,int * val,int cisco)126 get_rate_from_baud_rate(int baud_rate, int *val, int cisco)
127 {
128 unsigned int i;
129 for (i = 0; i < BAUD_RATES_LEN; i++) {
130 if (baud_rate == baud_rates[i].val) {
131 if (cisco) {
132 if (baud_rates[i].cisco_ios_val < 0)
133 /* We are at a baud rate unsupported by the
134 enumeration, just return zero. */
135 *val = 0;
136 else
137 *val = baud_rates[i].cisco_ios_val;
138 } else {
139 *val = baud_rates[i].real_rate;
140 }
141 return;
142 }
143 }
144 }
145
146 #ifdef USE_UUCP_LOCKING
147 static char *uucp_lck_dir = "/var/spool/lock/";
148 static char *dev_prefix = "/dev/";
149
150 static int
uucp_fname_lock_size(char * devname)151 uucp_fname_lock_size(char *devname)
152 {
153 int dev_prefix_len = strlen(dev_prefix);
154
155 if (strncmp(dev_prefix, devname, dev_prefix_len) == 0)
156 devname += dev_prefix_len;
157
158 /*
159 * Format is "/var/lock/LCK..<devname>". The 6 is for
160 * the "LCK.." and the final nil char.
161 */
162 return 6 + strlen(uucp_lck_dir) + strlen(devname);
163 }
164
165 static void
uucp_fname_lock(char * buf,char * devname)166 uucp_fname_lock(char *buf, char *devname)
167 {
168 int i, dev_prefix_len = strlen(dev_prefix);
169
170 if (strncmp(dev_prefix, devname, dev_prefix_len) == 0)
171 devname += dev_prefix_len;
172
173 sprintf(buf, "%sLCK..%s", uucp_lck_dir, devname);
174 for (i = strlen(uucp_lck_dir); buf[i]; i++) {
175 if (buf[i] == '/')
176 buf[i] = '_';
177 }
178 }
179
180 static void
uucp_rm_lock(char * devname)181 uucp_rm_lock(char *devname)
182 {
183 char *lck_file;
184
185 if (!uucp_locking_enabled) return;
186
187 lck_file = malloc(uucp_fname_lock_size(devname));
188 if (lck_file == NULL) {
189 return;
190 }
191 uucp_fname_lock(lck_file, devname);
192 unlink(lck_file);
193 free(lck_file);
194 }
195
196 /* return 0=OK, -1=error, 1=locked by other proces */
197 static int
uucp_mk_lock(char * devname)198 uucp_mk_lock(char *devname)
199 {
200 struct stat stt;
201 int pid = -1;
202
203 if (!uucp_locking_enabled)
204 return 0;
205
206 if (stat(uucp_lck_dir, &stt) == 0) { /* is lock file directory present? */
207 char *lck_file;
208 union {
209 uint32_t ival;
210 char str[64];
211 } buf;
212 int fd;
213
214 lck_file = malloc(uucp_fname_lock_size(devname));
215 if (lck_file == NULL)
216 return -1;
217
218 uucp_fname_lock(lck_file, devname);
219
220 pid = 0;
221 if ((fd = open(lck_file, O_RDONLY)) >= 0) {
222 int n;
223
224 n = read(fd, &buf, sizeof(buf) - 1);
225 close(fd);
226 if (n == 4) /* Kermit-style lockfile. */
227 pid = buf.ival;
228 else if (n > 0) { /* Ascii lockfile. */
229 buf.str[n] = '\0';
230 sscanf(buf.str, "%10d", &pid);
231 }
232
233 if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) {
234 /* death lockfile - remove it */
235 unlink(lck_file);
236 pid = 0;
237 } else
238 pid = 1;
239
240 }
241
242 if (pid == 0) {
243 int mask;
244
245 mask = umask(022);
246 fd = open(lck_file, O_WRONLY | O_CREAT | O_EXCL, 0666);
247 umask(mask);
248 if (fd >= 0) {
249 ssize_t rv;
250
251 snprintf(buf.str, sizeof(buf), "%10ld\n",
252 (long)getpid());
253 rv = write_full(fd, buf.str, strlen(buf.str));
254 close(fd);
255 if (rv < 0) {
256 pid = -1;
257 unlink(lck_file);
258 }
259 } else {
260 pid = -1;
261 }
262 }
263
264 free(lck_file);
265 }
266
267 return pid;
268 }
269 #else
uucp_rm_lock(char * devname)270 static void uucp_rm_lock(char *devname) { }
uucp_mk_lock(char * devname)271 static int uucp_mk_lock(char *devname)
272 {
273 return 0;
274 }
275 #endif /* USE_UUCP_LOCKING */
276
277 #ifdef __CYGWIN__
cfmakeraw(struct termios * termios_p)278 static void cfmakeraw(struct termios *termios_p) {
279 termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
280 termios_p->c_oflag &= ~OPOST;
281 termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
282 termios_p->c_cflag &= ~(CSIZE|PARENB);
283 termios_p->c_cflag |= CS8;
284 }
285 #endif
286
287 static int
set_termios_from_speed(struct devcfg_data * d,struct termios * termctl,int speed)288 set_termios_from_speed(struct devcfg_data *d, struct termios *termctl,
289 int speed)
290 {
291 switch (speed) {
292 case 300:
293 cfsetospeed(termctl, B300);
294 cfsetispeed(termctl, B300);
295 break;
296
297 case 600:
298 cfsetospeed(termctl, B600);
299 cfsetispeed(termctl, B600);
300 break;
301
302 case 1200:
303 cfsetospeed(termctl, B1200);
304 cfsetispeed(termctl, B1200);
305 break;
306
307 case 2400:
308 cfsetospeed(termctl, B2400);
309 cfsetispeed(termctl, B2400);
310 break;
311
312 case 4800:
313 cfsetospeed(termctl, B4800);
314 cfsetispeed(termctl, B4800);
315 break;
316
317 case 9600:
318 cfsetospeed(termctl, B9600);
319 cfsetispeed(termctl, B9600);
320 break;
321
322 case 19200:
323 cfsetospeed(termctl, B19200);
324 cfsetispeed(termctl, B19200);
325 break;
326
327 case 38400:
328 cfsetospeed(termctl, B38400);
329 cfsetispeed(termctl, B38400);
330 break;
331
332 case 57600:
333 cfsetospeed(termctl, B57600);
334 cfsetispeed(termctl, B57600);
335 break;
336
337 case 115200:
338 cfsetospeed(termctl, B115200);
339 cfsetispeed(termctl, B115200);
340 break;
341
342 #ifdef B230400
343 case 230400:
344 cfsetospeed(termctl, B230400);
345 cfsetispeed(termctl, B230400);
346 break;
347 #endif
348 #ifdef B460800
349 case 460800:
350 cfsetospeed(termctl, B460800);
351 cfsetispeed(termctl, B460800);
352 break;
353 #endif
354 #ifdef B500000
355 case 500000:
356 cfsetospeed(termctl, B500000);
357 cfsetispeed(termctl, B500000);
358 break;
359 #endif
360 #ifdef B576000
361 case 576000:
362 cfsetospeed(termctl, B576000);
363 cfsetispeed(termctl, B576000);
364 break;
365 #endif
366 #ifdef B921600
367 case 921600:
368 cfsetospeed(termctl, B921600);
369 cfsetispeed(termctl, B921600);
370 break;
371 #endif
372 #ifdef B1000000
373 case 1000000:
374 cfsetospeed(termctl, B1000000);
375 cfsetispeed(termctl, B1000000);
376 break;
377 #endif
378 #ifdef B1152000
379 case 1152000:
380 cfsetospeed(termctl, B1152000);
381 cfsetispeed(termctl, B1152000);
382 break;
383 #endif
384 #ifdef B1500000
385 case 1500000:
386 cfsetospeed(termctl, B1500000);
387 cfsetispeed(termctl, B1500000);
388 break;
389 #endif
390 #ifdef B2000000
391 case 2000000:
392 cfsetospeed(termctl, B2000000);
393 cfsetispeed(termctl, B2000000);
394 break;
395 #endif
396 #ifdef B2500000
397 case 2500000:
398 cfsetospeed(termctl, B2500000);
399 cfsetispeed(termctl, B2500000);
400 break;
401 #endif
402 #ifdef B3000000
403 case 3000000:
404 cfsetospeed(termctl, B3000000);
405 cfsetispeed(termctl, B3000000);
406 break;
407 #endif
408 #ifdef B3500000
409 case 3500000:
410 cfsetospeed(termctl, B3500000);
411 cfsetispeed(termctl, B3500000);
412 break;
413 #endif
414 #ifdef B4000000
415 case 4000000:
416 cfsetospeed(termctl, B4000000);
417 cfsetispeed(termctl, B4000000);
418 break;
419 #endif
420 default:
421 return -1;
422 }
423
424 d->default_bps = speed;
425 return 0;
426 }
427
428 static void
set_termios_parity(struct devcfg_data * d,struct termios * termctl,enum parity_vals val)429 set_termios_parity(struct devcfg_data *d, struct termios *termctl,
430 enum parity_vals val)
431 {
432 switch (val) {
433 case PARITY_NONE:
434 termctl->c_cflag &= ~(PARENB);
435 break;
436 case PARITY_EVEN:
437 case PARITY_SPACE:
438 termctl->c_cflag |= PARENB;
439 termctl->c_cflag &= ~(PARODD);
440 #ifdef CMSPAR
441 if (val == PARITY_SPACE)
442 termctl->c_cflag |= CMSPAR;
443 #endif
444 break;
445 case PARITY_ODD:
446 case PARITY_MARK:
447 termctl->c_cflag |= PARENB | PARODD;
448 #ifdef CMSPAR
449 if (val == PARITY_MARK)
450 termctl->c_cflag |= CMSPAR;
451 #endif
452 break;
453 }
454 d->default_parity_on = val != PARITY_NONE;
455 }
456
457 static void
set_termios_xonoff(struct termios * termctl,int enabled)458 set_termios_xonoff(struct termios *termctl, int enabled)
459 {
460 if (enabled) {
461 termctl->c_iflag |= (IXON | IXOFF | IXANY);
462 termctl->c_cc[VSTART] = 17;
463 termctl->c_cc[VSTOP] = 19;
464 } else {
465 termctl->c_iflag &= ~(IXON | IXOFF | IXANY);
466 }
467 }
468
469 static void
set_termios_rtscts(struct termios * termctl,int enabled)470 set_termios_rtscts(struct termios *termctl, int enabled)
471 {
472 if (enabled)
473 termctl->c_cflag |= CRTSCTS;
474 else
475 termctl->c_cflag &= ~CRTSCTS;
476 }
477
478 static void
set_termios_datasize(struct devcfg_data * d,struct termios * termctl,int size)479 set_termios_datasize(struct devcfg_data *d, struct termios *termctl, int size)
480 {
481 termctl->c_cflag &= ~CSIZE;
482 switch (size) {
483 case 5: termctl->c_cflag |= CS5; break;
484 case 6: termctl->c_cflag |= CS6; break;
485 case 7: termctl->c_cflag |= CS7; break;
486 case 8: termctl->c_cflag |= CS8; break;
487 }
488 d->default_data_size = size;
489 }
490
491 /* Initialize a serial port control structure for the first time.
492 This should only be called when the port is created. It sets the
493 port to the default 9600N81. */
494 static void
devinit(struct devcfg_data * d,struct termios * termctl)495 devinit(struct devcfg_data *d, struct termios *termctl)
496 {
497 cfmakeraw(termctl);
498
499 set_termios_from_speed(d, termctl, find_default_int("speed"));
500 set_termios_datasize(d, termctl, find_default_int("databits"));
501 d->default_stop_bits = find_default_int("stopbits");
502 if (d->default_stop_bits == 1)
503 termctl->c_cflag &= ~(CSTOPB);
504 else
505 termctl->c_cflag |= CSTOPB;
506
507 set_termios_parity(d, termctl, find_default_int("parity"));
508 set_termios_xonoff(termctl, find_default_int("xonxoff"));
509 set_termios_rtscts(termctl, find_default_int("rtscts"));
510
511 if (find_default_int("local"))
512 termctl->c_cflag |= CLOCAL;
513 else
514 termctl->c_cflag &= ~CLOCAL;
515
516 if (find_default_int("hangup_when_done"))
517 termctl->c_cflag &= HUPCL;
518 else
519 termctl->c_cflag &= ~HUPCL;
520
521 d->disablebreak = find_default_int("nobreak");
522
523 termctl->c_cflag |= CREAD;
524 termctl->c_iflag |= IGNBRK;
525 }
526
527 /* Configure a serial port control structure based upon input strings
528 in instr. These strings are described in the man page for this
529 program. */
530 static int
devconfig(struct devcfg_data * d,struct absout * eout,const char * instr,int (* otherconfig)(void * data,struct absout * eout,const char * item),void * data)531 devconfig(struct devcfg_data *d, struct absout *eout, const char *instr,
532 int (*otherconfig)(void *data, struct absout *eout, const char *item),
533 void *data)
534 {
535 struct termios *termctl = &d->termctl;
536 char *str;
537 char *pos;
538 char *strtok_data;
539 int rv = 0, val;
540
541 devinit(d, termctl);
542
543 str = strdup(instr);
544 if (str == NULL) {
545 return -1;
546 }
547
548 pos = strtok_r(str, " \t", &strtok_data);
549 while (pos != NULL) {
550 if ((val = speedstr_to_speed(pos)) != -1) {
551 rv = set_termios_from_speed(d, termctl, val);
552 if (rv) {
553 eout->out(eout, "Invalid baud rate: %d\n", d->default_bps);
554 goto out;
555 }
556 } else if (strcmp(pos, "1STOPBIT") == 0) {
557 termctl->c_cflag &= ~(CSTOPB);
558 d->default_stop_bits = 1;
559 } else if (strcmp(pos, "2STOPBITS") == 0) {
560 termctl->c_cflag |= CSTOPB;
561 d->default_stop_bits = 2;
562 } else if (strcmp(pos, "5DATABITS") == 0) {
563 set_termios_datasize(d, termctl, 5);
564 } else if (strcmp(pos, "6DATABITS") == 0) {
565 set_termios_datasize(d, termctl, 6);
566 } else if (strcmp(pos, "7DATABITS") == 0) {
567 set_termios_datasize(d, termctl, 7);
568 } else if (strcmp(pos, "8DATABITS") == 0) {
569 set_termios_datasize(d, termctl, 8);
570 } else if ((val = lookup_parity(pos)) != -1) {
571 set_termios_parity(d, termctl, val);
572 } else if (strcmp(pos, "XONXOFF") == 0) {
573 set_termios_xonoff(termctl, 1);
574 } else if (strcmp(pos, "-XONXOFF") == 0) {
575 set_termios_xonoff(termctl, 0);
576 } else if (strcmp(pos, "RTSCTS") == 0) {
577 set_termios_rtscts(termctl, 1);
578 } else if (strcmp(pos, "-RTSCTS") == 0) {
579 set_termios_rtscts(termctl, 0);
580 } else if (strcmp(pos, "LOCAL") == 0) {
581 termctl->c_cflag |= CLOCAL;
582 } else if (strcmp(pos, "-LOCAL") == 0) {
583 termctl->c_cflag &= ~CLOCAL;
584 } else if (strcmp(pos, "HANGUP_WHEN_DONE") == 0) {
585 termctl->c_cflag |= HUPCL;
586 } else if (strcmp(pos, "-HANGUP_WHEN_DONE") == 0) {
587 termctl->c_cflag &= ~HUPCL;
588 } else if (strcmp(pos, "NOBREAK") == 0) {
589 d->disablebreak = 1;
590 } else if (strcmp(pos, "-NOBREAK") == 0) {
591 d->disablebreak = 0;
592 } else {
593 if (otherconfig(data, eout, pos) == -1)
594 goto out;
595 }
596
597 pos = strtok_r(NULL, " \t", &strtok_data);
598 }
599
600 #if HAVE_DECL_TIOCSRS485
601 d->conf = get_rs485_conf(data);
602 #endif
603 out:
604 free(str);
605 return rv;
606 }
607
608 static char *
baud_string(int speed)609 baud_string(int speed)
610 {
611 char *str;
612 switch (speed) {
613 case B300: str = "300"; break;
614 case B600: str = "600"; break;
615 case B1200: str = "1200"; break;
616 case B2400: str = "2400"; break;
617 case B4800: str = "4800"; break;
618 case B9600: str = "9600"; break;
619 case B19200: str = "19200"; break;
620 case B38400: str = "38400"; break;
621 case B57600: str = "57600"; break;
622 case B115200: str = "115200"; break;
623 #ifdef B230400
624 case B230400: str = "230400"; break;
625 #endif
626 #ifdef B460800
627 case B460800: str = "460800"; break;
628 #endif
629 #ifdef B500000
630 case B500000: str = "500000"; break;
631 #endif
632 #ifdef B576000
633 case B576000: str = "576000"; break;
634 #endif
635 #ifdef B921600
636 case B921600: str = "921600"; break;
637 #endif
638 #ifdef B1000000
639 case B1000000: str = "1000000"; break;
640 #endif
641 #ifdef B1152000
642 case B1152000: str = "1152000"; break;
643 #endif
644 #ifdef B1500000
645 case B1500000: str = "1500000"; break;
646 #endif
647 #ifdef B2000000
648 case B2000000: str = "2000000"; break;
649 #endif
650 #ifdef B2500000
651 case B2500000: str = "2500000"; break;
652 #endif
653 #ifdef B3000000
654 case B3000000: str = "3000000"; break;
655 #endif
656 #ifdef B3500000
657 case B3500000: str = "3500000"; break;
658 #endif
659 #ifdef B4000000
660 case B4000000: str = "4000000"; break;
661 #endif
662 default: str = "unknown speed";
663 }
664 return str;
665 }
666
667 static void
devcfg_serparm_to_str(struct devio * io,char * str,int strlen)668 devcfg_serparm_to_str(struct devio *io, char *str, int strlen)
669 {
670 struct devcfg_data *d = io->my_data;
671 struct termios *termctl = &d->termctl;
672 speed_t speed = cfgetospeed(termctl);
673 int stopbits = termctl->c_cflag & CSTOPB;
674 int databits = termctl->c_cflag & CSIZE;
675 int parity_enabled = termctl->c_cflag & PARENB;
676 int parity = termctl->c_cflag & PARODD;
677 char *sstr;
678 char pchar, schar, dchar;
679
680 sstr = baud_string(speed);
681
682 if (stopbits)
683 schar = '2';
684 else
685 schar = '1';
686
687 switch (databits) {
688 case CS7: dchar = '7'; break;
689 case CS8: dchar = '8'; break;
690 default: dchar = '?';
691 }
692
693 if (parity_enabled) {
694 if (parity) {
695 pchar = 'O';
696 } else {
697 pchar = 'E';
698 }
699 } else {
700 pchar = 'N';
701 }
702
703 snprintf(str, strlen, "%s %c%c%c", sstr, pchar, dchar, schar);
704 }
705
706 /* Send the serial port device configuration to the control port. */
707 static void
devcfg_show_devcfg(struct devio * io,struct absout * out)708 devcfg_show_devcfg(struct devio *io, struct absout *out)
709 {
710 struct devcfg_data *d = io->my_data;
711 struct termios *termctl = &d->termctl;
712
713 speed_t speed = cfgetospeed(termctl);
714 int stopbits = termctl->c_cflag & CSTOPB;
715 int databits = termctl->c_cflag & CSIZE;
716 int parity_enabled = termctl->c_cflag & PARENB;
717 int parity = termctl->c_cflag & PARODD;
718 int xon = termctl->c_iflag & IXON;
719 int xoff = termctl->c_iflag & IXOFF;
720 int xany = termctl->c_iflag & IXANY;
721 int flow_rtscts = termctl->c_cflag & CRTSCTS;
722 int clocal = termctl->c_cflag & CLOCAL;
723 int hangup_when_done = termctl->c_cflag & HUPCL;
724 char *str;
725
726 out->out(out, "%s ", baud_string(speed));
727
728 if (xon && xoff && xany) {
729 out->out(out, "XONXOFF ");
730 }
731
732 if (flow_rtscts) {
733 out->out(out, "RTSCTS ");
734 }
735
736 if (clocal) {
737 out->out(out, "LOCAL ");
738 }
739
740 if (hangup_when_done) {
741 out->out(out, "HANGUP_WHEN_DONE ");
742 }
743
744 if (stopbits) {
745 str = "2STOPBITS";
746 } else {
747 str = "1STOPBIT";
748 }
749 out->out(out, "%s ", str);
750
751 switch (databits) {
752 case CS7: str = "7DATABITS"; break;
753 case CS8: str = "8DATABITS"; break;
754 default: str = "unknown databits";
755 }
756 out->out(out, "%s ", str);
757
758 if (parity_enabled) {
759 if (parity) {
760 str = "ODD";
761 } else {
762 str = "EVEN";
763 }
764 } else {
765 str = "NONE";
766 }
767 out->out(out, "%s", str);
768 }
769
770 static int
devcfg_set_devcontrol(struct devio * io,const char * instr)771 devcfg_set_devcontrol(struct devio *io, const char *instr)
772 {
773 struct devcfg_data *d = io->my_data;
774 int fd = d->devfd;
775 int rv = 0;
776 char *str;
777 char *pos;
778 int status;
779 char *strtok_data;
780
781 str = malloc(strlen(instr) + 1);
782 if (str == NULL) {
783 return -1;
784 }
785
786 strcpy(str, instr);
787
788 pos = strtok_r(str, " \t", &strtok_data);
789 while (pos != NULL) {
790 if (strcmp(pos, "RTSHI") == 0) {
791 ioctl(fd, TIOCMGET, &status);
792 status |= TIOCM_RTS;
793 ioctl(fd, TIOCMSET, &status);
794 } else if (strcmp(pos, "RTSLO") == 0) {
795 ioctl(fd, TIOCMGET, &status);
796 status &= ~TIOCM_RTS;
797 ioctl(fd, TIOCMSET, &status);
798 } else if (strcmp(pos, "DTRHI") == 0) {
799 ioctl(fd, TIOCMGET, &status);
800 status |= TIOCM_DTR;
801 ioctl(fd, TIOCMSET, &status);
802 } else if (strcmp(pos, "DTRLO") == 0) {
803 ioctl(fd, TIOCMGET, &status);
804 status &= ~TIOCM_DTR; /* AKA drop DTR */
805 ioctl(fd, TIOCMSET, &status);
806 } else {
807 rv = -1;
808 goto out;
809 }
810
811 pos = strtok_r(NULL, " \t", &strtok_data);
812 }
813
814 out:
815 free(str);
816 return rv;
817 }
818
819 static void
devcfg_show_devcontrol(struct devio * io,struct absout * out)820 devcfg_show_devcontrol(struct devio *io, struct absout *out)
821 {
822 struct devcfg_data *d = io->my_data;
823 char *str;
824 int status;
825
826 ioctl(d->devfd, TIOCMGET, &status);
827
828 if (status & TIOCM_RTS) {
829 str = "RTSHI";
830 } else {
831 str = "RTSLO";
832 }
833 out->out(out, "%s ", str);
834
835 if (status & TIOCM_DTR) {
836 str = "DTRHI";
837 } else {
838 str = "DTRLO";
839 }
840 out->out(out, "%s ", str);
841 }
842
843 static void
do_read(int fd,void * data)844 do_read(int fd, void *data)
845 {
846 struct devio *io = data;
847 io->read_handler(io);
848 }
849
850 static void
do_write(int fd,void * data)851 do_write(int fd, void *data)
852 {
853 struct devio *io = data;
854 io->write_handler(io);
855 }
856
857 static void
do_except(int fd,void * data)858 do_except(int fd, void *data)
859 {
860 struct devio *io = data;
861 io->except_handler(io);
862 }
863
calc_bpc(struct devcfg_data * d)864 static int calc_bpc(struct devcfg_data *d)
865 {
866 return d->current_data_size + d->current_stop_bits +
867 d->current_parity_on + 1;
868 }
869
870 static void
devfd_fd_cleared(int fd,void * cb_data)871 devfd_fd_cleared(int fd, void *cb_data)
872 {
873 struct devio *io = cb_data;
874 struct devcfg_data *d = io->my_data;
875 void (*shutdown_done)(struct devio *) = d->shutdown_done;
876 struct termios termio;
877
878 /* Disable flow control to avoid a long shutdown. */
879 if (tcgetattr(d->devfd, &termio) != -1) {
880 termio.c_iflag &= ~(IXON | IXOFF);
881 termio.c_cflag &= ~CRTSCTS;
882 tcsetattr(d->devfd, TCSANOW, &termio);
883 }
884 tcflush(d->devfd, TCOFLUSH);
885 close(d->devfd);
886 d->devfd = -1;
887 uucp_rm_lock(io->devname);
888 shutdown_done(io);
889 }
890
devcfg_setup(struct devio * io,const char * name,const char ** errstr,int * bps,int * bpc)891 static int devcfg_setup(struct devio *io, const char *name, const char **errstr,
892 int *bps, int *bpc)
893 {
894 struct devcfg_data *d = io->my_data;
895 int options;
896 int rv;
897
898 rv = uucp_mk_lock(io->devname);
899 if (rv > 0 ) {
900 *errstr = "Port already in use by another process\r\n";
901 return -1;
902 } else if (rv < 0) {
903 *errstr = "Error creating port lock file\r\n";
904 return -1;
905 }
906
907 *bps = d->current_bps = d->default_bps;
908 d->current_data_size = d->default_data_size;
909 d->current_stop_bits = d->default_stop_bits;
910 d->current_parity_on = d->default_parity_on;
911 *bpc = calc_bpc(d);
912
913 /* Oct 05 2001 druzus: NOCTTY - don't make
914 device control tty for our process */
915 options = O_NONBLOCK | O_NOCTTY;
916 if (io->read_disabled) {
917 options |= O_WRONLY;
918 } else {
919 options |= O_RDWR;
920 }
921 d->devfd = open(io->devname, options);
922 if (d->devfd == -1) {
923 syslog(LOG_ERR, "Could not open device %s for port %s: %m",
924 io->devname,
925 name);
926 uucp_rm_lock(io->devname);
927 return -1;
928 }
929
930 if (!io->read_disabled && tcsetattr(d->devfd, TCSANOW, &d->termctl) == -1)
931 {
932 close(d->devfd);
933 d->devfd = -1;
934 syslog(LOG_ERR, "Could not set up device %s for port %s: %m",
935 io->devname,
936 name);
937 uucp_rm_lock(io->devname);
938 return -1;
939 }
940
941 /* Turn off BREAK. */
942 if (!io->read_disabled && !d->disablebreak
943 && ioctl(d->devfd, TIOCCBRK) == -1) {
944 /* Probably not critical, but we should at least log something. */
945 syslog(LOG_ERR, "Could not turn off break for device %s port %s: %m",
946 io->devname,
947 name);
948 }
949
950 #if HAVE_DECL_TIOCSRS485
951 if (d->conf) {
952 if (d->conf->flags & SER_RS485_ENABLED) {
953 if (ioctl(d->devfd , TIOCSRS485, d->conf ) < 0) {
954 syslog(LOG_ERR, "Could not set RS485 config for device %s port %s: %m",
955 io->devname,
956 name);
957 return -1;
958 }
959 }
960 }
961 #endif
962
963 sel_set_fd_handlers(ser2net_sel, d->devfd, io,
964 io->read_disabled ? NULL : do_read,
965 do_write, do_except, devfd_fd_cleared);
966 return 0;
967 }
968
devcfg_shutdown(struct devio * io,void (* shutdown_done)(struct devio *))969 static void devcfg_shutdown(struct devio *io,
970 void (*shutdown_done)(struct devio *))
971 {
972 struct devcfg_data *d = io->my_data;
973
974 /* To avoid blocking on close if we have written bytes and are in
975 flow-control, we flush the output queue. */
976 if (d->devfd != -1) {
977 d->shutdown_done = shutdown_done;
978 sel_clear_fd_handlers(ser2net_sel, d->devfd);
979 } else {
980 shutdown_done(io);
981 }
982 }
983
devcfg_read(struct devio * io,void * buf,size_t size)984 static int devcfg_read(struct devio *io, void *buf, size_t size)
985 {
986 struct devcfg_data *d = io->my_data;
987
988 return read(d->devfd, buf, size);
989 }
990
devcfg_write(struct devio * io,void * buf,size_t size)991 static int devcfg_write(struct devio *io, void *buf, size_t size)
992 {
993 struct devcfg_data *d = io->my_data;
994
995 return write(d->devfd, buf, size);
996 }
997
devcfg_read_handler_enable(struct devio * io,int enabled)998 static void devcfg_read_handler_enable(struct devio *io, int enabled)
999 {
1000 struct devcfg_data *d = io->my_data;
1001
1002 sel_set_fd_read_handler(ser2net_sel, d->devfd,
1003 enabled ? SEL_FD_HANDLER_ENABLED :
1004 SEL_FD_HANDLER_DISABLED);
1005 }
1006
devcfg_write_handler_enable(struct devio * io,int enabled)1007 static void devcfg_write_handler_enable(struct devio *io, int enabled)
1008 {
1009 struct devcfg_data *d = io->my_data;
1010
1011 sel_set_fd_write_handler(ser2net_sel, d->devfd,
1012 enabled ? SEL_FD_HANDLER_ENABLED :
1013 SEL_FD_HANDLER_DISABLED);
1014 }
1015
devcfg_except_handler_enable(struct devio * io,int enabled)1016 static void devcfg_except_handler_enable(struct devio *io, int enabled)
1017 {
1018 struct devcfg_data *d = io->my_data;
1019
1020 sel_set_fd_except_handler(ser2net_sel, d->devfd,
1021 enabled ? SEL_FD_HANDLER_ENABLED :
1022 SEL_FD_HANDLER_DISABLED);
1023 }
1024
devcfg_send_break(struct devio * io)1025 static int devcfg_send_break(struct devio *io)
1026 {
1027 struct devcfg_data *d = io->my_data;
1028
1029 tcsendbreak(d->devfd, 0);
1030 return 0;
1031 }
1032
devcfg_get_modem_state(struct devio * io,unsigned char * modemstate)1033 static int devcfg_get_modem_state(struct devio *io, unsigned char *modemstate)
1034 {
1035 struct devcfg_data *d = io->my_data;
1036 int val;
1037
1038 if (ioctl(d->devfd, TIOCMGET, &val) != 0)
1039 return -1;
1040
1041 *modemstate = 0;
1042 if (val & TIOCM_CD)
1043 *modemstate |= 0x80;
1044 if (val & TIOCM_RI)
1045 *modemstate |= 0x40;
1046 if (val & TIOCM_DSR)
1047 *modemstate |= 0x20;
1048 if (val & TIOCM_CTS)
1049 *modemstate |= 0x10;
1050 return 0;
1051 }
1052
devcfg_baud_rate(struct devio * io,int * val,int cisco,int * bps)1053 static int devcfg_baud_rate(struct devio *io, int *val, int cisco, int *bps)
1054 {
1055 struct devcfg_data *d = io->my_data;
1056 struct termios termio;
1057
1058 if (tcgetattr(d->devfd, &termio) == -1) {
1059 *val = 0;
1060 return -1;
1061 }
1062
1063 if ((*val != 0) && (get_baud_rate(*val, val, cisco, bps))) {
1064 /* We have a valid baud rate. */
1065 cfsetispeed(&termio, *val);
1066 cfsetospeed(&termio, *val);
1067 tcsetattr(d->devfd, TCSANOW, &termio);
1068 }
1069
1070 tcgetattr(d->devfd, &termio);
1071 *val = cfgetispeed(&termio);
1072 get_rate_from_baud_rate(*val, val, cisco);
1073
1074 return 0;
1075 }
1076
devcfg_data_size(struct devio * io,unsigned char * val,int * bpc)1077 static int devcfg_data_size(struct devio *io, unsigned char *val, int *bpc)
1078 {
1079 struct devcfg_data *d = io->my_data;
1080 struct termios termio;
1081
1082 if (tcgetattr(d->devfd, &termio) == -1) {
1083 *val = 0;
1084 return -1;
1085 }
1086
1087 if ((*val >= 5) && (*val <= 8)) {
1088 termio.c_cflag &= ~CSIZE;
1089 switch (*val) {
1090 case 5: termio.c_cflag |= CS5; d->current_data_size = 5; break;
1091 case 6: termio.c_cflag |= CS6; d->current_data_size = 6; break;
1092 case 7: termio.c_cflag |= CS7; d->current_data_size = 7; break;
1093 case 8: termio.c_cflag |= CS8; d->current_data_size = 8; break;
1094 }
1095 tcsetattr(d->devfd, TCSANOW, &termio);
1096 }
1097
1098 switch (termio.c_cflag & CSIZE) {
1099 case CS5: *val = 5; break;
1100 case CS6: *val = 6; break;
1101 case CS7: *val = 7; break;
1102 case CS8: *val = 8; break;
1103 default: *val = 0;
1104 }
1105
1106 *bpc = calc_bpc(d);
1107
1108 return 0;
1109 }
1110
devcfg_parity(struct devio * io,unsigned char * val,int * bpc)1111 static int devcfg_parity(struct devio *io, unsigned char *val, int *bpc)
1112 {
1113 struct devcfg_data *d = io->my_data;
1114 struct termios termio;
1115
1116 if (tcgetattr(d->devfd, &termio) == -1) {
1117 *val = 0;
1118 return -1;
1119 }
1120
1121 /* We don't support MARK or SPACE parity. */
1122 if ((*val >= 1) && (*val <= 3)) {
1123 termio.c_cflag &= ~(PARENB | PARODD);
1124 switch (*val) {
1125 case 1: d->current_parity_on = 0; break; /* NONE */
1126 case 2: termio.c_cflag |= PARENB | PARODD; /* ODD */
1127 d->current_parity_on = 1;
1128 break;
1129 case 3: termio.c_cflag |= PARENB; /* EVEN */
1130 d->current_parity_on = 1;
1131 break;
1132 }
1133 tcsetattr(d->devfd, TCSANOW, &termio);
1134 }
1135
1136 if (termio.c_cflag & PARENB) {
1137 if (termio.c_cflag & PARODD)
1138 *val = 2; /* ODD */
1139 else
1140 *val = 3; /* EVEN */
1141 } else
1142 *val = 1; /* NONE */
1143
1144 *bpc = calc_bpc(d);
1145
1146 return 0;
1147 }
1148
devcfg_stop_size(struct devio * io,unsigned char * val,int * bpc)1149 static int devcfg_stop_size(struct devio *io, unsigned char *val, int *bpc)
1150 {
1151 struct devcfg_data *d = io->my_data;
1152 struct termios termio;
1153
1154 if (tcgetattr(d->devfd, &termio) == -1) {
1155 *val = 0;
1156 return -1;
1157 }
1158
1159 if ((*val >= 1) && (*val <= 2)) {
1160 termio.c_cflag &= ~CSTOPB;
1161 switch (*val) {
1162 case 1: d->current_stop_bits = 1; break; /* 1 stop bit */
1163 case 2: d->current_stop_bits = 2; /* 2 stop bits */
1164 termio.c_cflag |= CSTOPB;
1165 break;
1166 }
1167 tcsetattr(d->devfd, TCSANOW, &termio);
1168 }
1169
1170 if (termio.c_cflag & CSTOPB)
1171 *val = 2; /* 2 stop bits. */
1172 else
1173 *val = 1; /* 1 stop bit. */
1174
1175 *bpc = calc_bpc(d);
1176
1177 return 0;
1178 }
1179
devcfg_flow_control(struct devio * io,unsigned char val)1180 static int devcfg_flow_control(struct devio *io, unsigned char val)
1181 {
1182 struct devcfg_data *d = io->my_data;
1183
1184 tcflow(d->devfd, val ? TCIOFF : TCION);
1185 return 0;
1186 }
1187
devcfg_control(struct devio * io,unsigned char * val)1188 static int devcfg_control(struct devio *io, unsigned char *val)
1189 {
1190 struct devcfg_data *d = io->my_data;
1191 struct termios termio;
1192 int ival;
1193
1194 if (tcgetattr(d->devfd, &termio) == -1) {
1195 *val = 0;
1196 return -1;
1197 }
1198
1199 switch (*val) {
1200 case 0:
1201 case 1:
1202 case 2:
1203 case 3:
1204 /* Outbound/both flow control */
1205 if (tcgetattr(d->devfd, &termio) != -1) {
1206 if (*val != 0) {
1207 termio.c_iflag &= ~(IXON | IXOFF);
1208 termio.c_cflag &= ~CRTSCTS;
1209 switch (*val) {
1210 case 1: break; /* NONE */
1211 case 2: termio.c_iflag |= IXON | IXOFF; break;
1212 case 3: termio.c_cflag |= CRTSCTS; break;
1213 }
1214 tcsetattr(d->devfd, TCSANOW, &termio);
1215 }
1216 if (termio.c_cflag & CRTSCTS)
1217 *val = 3;
1218 else if (termio.c_iflag & IXON)
1219 *val = 2;
1220 else
1221 *val = 1;
1222 }
1223 break;
1224
1225 case 13:
1226 case 14:
1227 case 15:
1228 case 16:
1229 case 17:
1230 case 18:
1231 case 19:
1232 /* Inbound flow-control */
1233 if (tcgetattr(d->devfd, &termio) != -1) {
1234 if (*val == 15) {
1235 /* We can only set XON/XOFF independently */
1236 termio.c_iflag |= IXOFF;
1237 tcsetattr(d->devfd, TCSANOW, &termio);
1238 }
1239 if (termio.c_cflag & CRTSCTS)
1240 *val = 16;
1241 else if (termio.c_iflag & IXOFF)
1242 *val = 15;
1243 else
1244 *val = 14;
1245 }
1246 break;
1247
1248 /* Handle BREAK stuff. */
1249 case 6:
1250 if (ioctl(d->devfd, TIOCCBRK) != -1)
1251 d->break_set = 0;
1252 goto read_break_val;
1253
1254 case 5:
1255 if (ioctl(d->devfd, TIOCSBRK) != -1)
1256 d->break_set = 1;
1257 goto read_break_val;
1258
1259 case 4:
1260 read_break_val:
1261 if (d->break_set)
1262 *val = 5;
1263 else
1264 *val = 6;
1265 break;
1266
1267 /* DTR handling */
1268 case 8:
1269 #ifndef __CYGWIN__
1270 ival = TIOCM_DTR;
1271 ioctl(d->devfd, TIOCMBIS, &ival);
1272 #else
1273 ioctl(d->devfd, TIOCMGET, &ival);
1274 ival |= TIOCM_DTR;
1275 ioctl(d->devfd, TIOCMSET, &ival);
1276 #endif
1277 goto read_dtr_val;
1278
1279 case 9:
1280 #ifndef __CYGWIN__
1281 ival = TIOCM_DTR;
1282 ioctl(d->devfd, TIOCMBIC, &ival);
1283 #else
1284 ioctl(d->devfd, TIOCMGET, &ival);
1285 ival &= ~TIOCM_DTR;
1286 ioctl(d->devfd, TIOCMSET, &ival);
1287 #endif
1288 goto read_dtr_val;
1289
1290 case 7:
1291 read_dtr_val:
1292 if (ioctl(d->devfd, TIOCMGET, &ival) == -1)
1293 *val = 7;
1294 else if (ival & TIOCM_DTR)
1295 *val = 8;
1296 else
1297 *val = 9;
1298 break;
1299
1300 /* RTS handling */
1301 case 11:
1302 #ifndef __CYGWIN__
1303 ival = TIOCM_RTS;
1304 ioctl(d->devfd, TIOCMBIS, &ival);
1305 #else
1306 ioctl(d->devfd, TIOCMGET, &ival);
1307 ival |= TIOCM_RTS;
1308 ioctl(d->devfd, TIOCMSET, &ival);
1309 #endif
1310 goto read_rts_val;
1311
1312 case 12:
1313 #ifndef __CYGWIN__
1314 ival = TIOCM_RTS;
1315 ioctl(d->devfd, TIOCMBIC, &ival);
1316 #else
1317 ioctl(d->devfd, TIOCMGET, &ival);
1318 ival &= ~TIOCM_RTS;
1319 ioctl(d->devfd, TIOCMSET, &ival);
1320 #endif
1321 goto read_rts_val;
1322
1323 case 10:
1324 read_rts_val:
1325 if (ioctl(d->devfd, TIOCMGET, &ival) == -1)
1326 *val = 10;
1327 else if (ival & TIOCM_RTS)
1328 *val = 11;
1329 else
1330 *val = 12;
1331 break;
1332
1333 default:
1334 *val = 0;
1335 return -1;
1336 }
1337
1338 return 0;
1339 }
1340
devcfg_flush(struct devio * io,int * val)1341 static int devcfg_flush(struct devio *io, int *val)
1342 {
1343 struct devcfg_data *d = io->my_data;
1344 int ival;
1345
1346 switch (*val) {
1347 case DEVIO_FLUSH_INPUT: ival = TCIFLUSH; goto purge_found;
1348 case DEVIO_FLUSH_OUTPUT: ival = TCOFLUSH; goto purge_found;
1349 case DEVIO_FLUSH_INPUT | DEVIO_FLUSH_OUTPUT:
1350 ival = TCIOFLUSH; goto purge_found;
1351 }
1352 *val = 0;
1353 return -1;
1354 purge_found:
1355 tcflush(d->devfd, ival);
1356 return 0;
1357 }
1358
devcfg_free(struct devio * io)1359 static void devcfg_free(struct devio *io)
1360 {
1361 struct devcfg_data *d = io->my_data;
1362
1363 if (d->devfd != -1)
1364 close(d->devfd);
1365 io->my_data = NULL;
1366 free(d);
1367 }
1368
1369 static int
devcfg_reconfig(struct devio * io,struct absout * eout,const char * instr,int (* otherconfig)(void * data,struct absout * eout,const char * item),void * data)1370 devcfg_reconfig(struct devio *io, struct absout *eout, const char *instr,
1371 int (*otherconfig)(void *data, struct absout *eout,
1372 const char *item),
1373 void *data)
1374 {
1375 struct devcfg_data *d = io->my_data;
1376
1377 return devconfig(d, eout, instr, otherconfig, data);
1378 }
1379
1380 static struct devio_f devcfg_io_f = {
1381 .setup = devcfg_setup,
1382 .shutdown = devcfg_shutdown,
1383 .reconfig = devcfg_reconfig,
1384 .read = devcfg_read,
1385 .write = devcfg_write,
1386 .read_handler_enable = devcfg_read_handler_enable,
1387 .write_handler_enable = devcfg_write_handler_enable,
1388 .except_handler_enable = devcfg_except_handler_enable,
1389 .send_break = devcfg_send_break,
1390 .get_modem_state = devcfg_get_modem_state,
1391 .set_devcontrol = devcfg_set_devcontrol,
1392 .show_devcontrol = devcfg_show_devcontrol,
1393 .show_devcfg = devcfg_show_devcfg,
1394 .baud_rate = devcfg_baud_rate,
1395 .data_size = devcfg_data_size,
1396 .parity = devcfg_parity,
1397 .stop_size = devcfg_stop_size,
1398 .control = devcfg_control,
1399 .flow_control = devcfg_flow_control,
1400 .flush = devcfg_flush,
1401 .free = devcfg_free,
1402 .serparm_to_str = devcfg_serparm_to_str
1403 };
1404
1405 int
devcfg_init(struct devio * io,struct absout * eout,const char * instr,int (* otherconfig)(void * data,struct absout * eout,const char * item),void * data)1406 devcfg_init(struct devio *io, struct absout *eout, const char *instr,
1407 int (*otherconfig)(void *data, struct absout *eout,
1408 const char *item),
1409 void *data)
1410 {
1411 struct devcfg_data *d;
1412
1413 d = malloc(sizeof(*d));
1414 if (!d)
1415 return -1;
1416 memset(d, 0, sizeof(*d));
1417 d->devfd = -1;
1418
1419 if (devconfig(d, eout, instr, otherconfig, data) == -1) {
1420 free(d);
1421 return -1;
1422 }
1423
1424 io->my_data = d;
1425 io->f = &devcfg_io_f;
1426 return 0;
1427 }
1428
1429