]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-osf.c
took out bpf filtering stuff
[ppp.git] / pppd / sys-osf.c
1 /*
2  * sys-osf.c - System-dependent procedures for setting up
3  * PPP interfaces on OSF/1 systems which use the STREAMS ppp interface.
4  *
5  * Copyright (c) 1989 Carnegie Mellon University.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by Carnegie Mellon University.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20
21 #ifndef lint
22 static char rcsid[] = "$Id: sys-osf.c,v 1.9 1996/05/26 23:58:46 paulus Exp $";
23 #endif
24
25 /*
26  * TODO:
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <syslog.h>
33 #include <termios.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <time.h>
37 #include <utmp.h>
38 #include <poll.h>
39 #include <signal.h>
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/time.h>
43 #include <sys/stream.h>
44 #include <sys/stropts.h>
45
46 #include <net/if.h>
47 #include <net/ppp_defs.h>
48 #include <net/ppp_str.h>
49 #include <net/route.h>
50 #include <net/if_arp.h>
51 #include <netinet/in.h>
52
53 #include "pppd.h"
54
55 #ifndef ifr_mtu
56 #define ifr_mtu         ifr_metric
57 #endif
58
59 #define MAXMODULES      10      /* max number of module names to save */
60 static struct   modlist {
61     char        modname[FMNAMESZ+1];
62 } str_modules[MAXMODULES];
63 static int      str_module_count = 0;
64 static int      pushed_ppp;
65 static int      closed_stdio;
66
67 static int      restore_term;   /* 1 => we've munged the terminal */
68 static struct termios inittermios; /* Initial TTY termios */
69 static struct winsize wsinfo;      /* Initial window size info */
70 static int      initfdflags = -1; /* Initial file descriptor flags for fd */
71
72 static int sockfd;              /* socket for doing interface ioctls */
73
74 int orig_ttyfd = -1;   /*  Original ttyfd if we did a streamify()  */
75
76 static int      if_is_up;       /* Interface has been marked up */
77 static u_int32_t ifaddrs[2];    /* Local and remote addrs we've set */
78 static u_int32_t default_route_gateway; /* Gateway for default route added */
79 static u_int32_t proxy_arp_addr;        /* Addr for proxy arp entry added */
80
81 /* Prototypes for procedures local to this file. */
82 static int translate_speed __P((int));
83 static int baud_rate_of __P((int));
84 static int get_ether_addr __P((u_int32_t, struct sockaddr *));
85
86
87 /*
88  * sys_init - System-dependent initialization.
89  */
90 void
91 sys_init()
92 {
93     /* Get an internet socket for doing socket ioctl's on. */
94     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
95         syslog(LOG_ERR, "Couldn't create IP socket: %m");
96         die(1);
97     }
98 }
99
100 /*
101  * sys_cleanup - restore any system state we modified before exiting:
102  * mark the interface down, delete default route and/or proxy arp entry.
103  * This should call die() because it's called from die().
104  */
105 void
106 sys_cleanup()
107 {
108     struct ifreq ifr;
109
110     if (if_is_up) {
111         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
112         if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
113             && ((ifr.ifr_flags & IFF_UP) != 0)) {
114             ifr.ifr_flags &= ~IFF_UP;
115             ioctl(sockfd, SIOCSIFFLAGS, &ifr);
116         }
117     }
118     if (ifaddrs[0])
119         cifaddr(0, ifaddrs[0], ifaddrs[1]);
120     if (default_route_gateway)
121         cifdefaultroute(0, default_route_gateway);
122     if (proxy_arp_addr)
123         cifproxyarp(0, proxy_arp_addr);
124 }
125
126 /*
127  * daemon - Detach us from the terminal session.
128  */
129 int
130 daemon(nochdir, noclose)
131     int nochdir, noclose;
132 {
133     int pid;
134
135     if ((pid = fork()) < 0)
136         return -1;
137     if (pid != 0)
138         exit(0);                /* parent dies */
139     setsid();
140     if (!nochdir)
141         chdir("/");
142     if (!noclose) {
143         fclose(stdin);          /* don't need stdin, stdout, stderr */
144         fclose(stdout);
145         fclose(stderr);
146     }
147     return 0;
148 }
149
150
151 char pipename[] = "/dev/streams/pipe";
152
153 /*
154  * ppp_available - check if this kernel supports PPP.
155  */
156 int
157 ppp_available()
158 {
159     int fd, ret;
160
161     fd = open(pipename, O_RDONLY, 0);
162     if (fd < 0)
163         return 0;               /* can't find out - assume we don't have ppp */
164     ret = ioctl(fd, I_FIND, "pppasync") >= 0;
165     close(fd);
166     return ret;
167 }
168
169
170 /*
171  *  streampipe -- Opens a STREAMS based pipe.  Used by streamify().
172  */
173
174 int 
175 streampipe(int fd[2])
176 {
177     if ((fd[0]=open(pipename, O_RDWR)) == -1)
178         return(-1);
179     else if ((fd[1]=open(pipename, O_RDWR)) == -1) {
180         close(fd[0]);
181         return(-1);
182     } else if (ioctl(fd[0], I_PIPE, fd[1]) != 0) {
183         close(fd[0]);
184         close(fd[1]);
185         return(-1);
186     } else {
187         return(ioctl(fd[0], I_PUSH, "pipemod"));
188     }
189 }
190
191 /*
192  *  streamify -- Needed for DEC OSF/1, since tty devices are not STREAMS
193  *               modules (but ptys are, and pipes can be).
194  */
195
196 #define BUFFSIZE 1000     /*  Size of buffer for streamify()  */
197
198 int 
199 streamify(int fd)
200 {
201     int fdes[2];
202     fd_set readfds;
203     int ret, fret, rret, maxfd;
204     static char buffer[BUFFSIZE];
205     struct sigaction sa;
206
207     if (streampipe(fdes) != 0)
208         syslog(LOG_ERR, "streampipe(): %m\n");
209     else if (isastream(fdes[0]) == 1) {
210         if ((fret=fork()) < 0) {
211             syslog(LOG_ERR, "fork(): %m\n");
212         } else if (fret == 0) {
213             /*  Process to forward things from pipe to tty  */
214             sigemptyset(&(sa.sa_mask));
215             sa.sa_handler = SIG_DFL;
216             sa.sa_flags = 0;
217             sigaction(SIGHUP, &sa, NULL);   /*  Go back to default actions */
218             sigaction(SIGINT, &sa, NULL);   /*  for changed signals.  */
219             sigaction(SIGTERM, &sa, NULL);
220             sigaction(SIGCHLD, &sa, NULL);
221             sigaction(SIGUSR1, &sa, NULL);
222             sigaction(SIGUSR2, &sa, NULL);
223             close(fdes[0]);
224
225             maxfd = (fdes[1]>fd)?fdes[1]:fd;
226             while (1) {
227                 FD_ZERO(&readfds);
228                 FD_SET(fdes[1], &readfds);
229                 FD_SET(fd, &readfds);
230                 ret = select(maxfd+1, &readfds, NULL, NULL, NULL);
231                 if (FD_ISSET(fd, &readfds)) {
232                     rret = read(fd, buffer, BUFFSIZE);
233                     if (rret == 0) {
234                         MAINDEBUG((LOG_DEBUG, "slave died:  EOF on tty."));
235                         exit(0);
236                     } else {
237                         write(fdes[1], buffer, rret);
238                     }
239                 }
240                 if (FD_ISSET(fdes[1], &readfds)) {
241                     rret = read(fdes[1], buffer, BUFFSIZE);
242                     if (rret == 0) {
243                         MAINDEBUG((LOG_DEBUG, "slave died:  EOF on pipe."));
244                         exit(0);
245                     } else {
246                         write(fd, buffer, rret);
247                     }
248                 }
249             }
250         } else {
251             close(fdes[1]);
252             orig_ttyfd = fd;
253             return(fdes[0]);
254         }
255     }
256
257     return(-1);
258 }
259
260
261 /*
262  * establish_ppp - Turn the serial port into a ppp interface.
263  */
264 void
265 establish_ppp(fd)
266     int fd;
267 {
268     int ret;
269
270     if (isastream(fd) != 1) {
271         if ((ttyfd = fd = streamify(fd)) < 0) {
272             syslog(LOG_ERR, "Couldn't get a STREAMS module!\n");
273             die(1);
274         }
275     }
276
277     /* go through and save the name of all the modules, then pop em */
278     for (;;) { 
279         if (ioctl(fd, I_LOOK, str_modules[str_module_count].modname) < 0 ||
280             ioctl(fd, I_POP, 0) < 0)
281             break;
282         MAINDEBUG((LOG_DEBUG, "popped stream module : %s",
283                    str_modules[str_module_count].modname));
284         str_module_count++;
285     }
286
287     /* now push the async/fcs module */
288     if (ioctl(fd, I_PUSH, "pppasync") < 0) {
289         syslog(LOG_ERR, "ioctl(I_PUSH, ppp_async): %m");
290         die(1);
291     }
292     /* push the compress module */
293     if (ioctl(fd, I_PUSH, "pppcomp") < 0) {
294         syslog(LOG_WARNING, "ioctl(I_PUSH, ppp_comp): %m");
295     }
296     /* finally, push the ppp_if module that actually handles the */
297     /* network interface */ 
298     if (ioctl(fd, I_PUSH, "pppif") < 0) {
299         syslog(LOG_ERR, "ioctl(I_PUSH, ppp_if): %m");
300         die(1);
301     }
302     pushed_ppp = 1;
303     /* read mode, message non-discard mode */
304     if (ioctl(fd, I_SRDOPT, RMSGN|RPROTNORM) < 0) {
305         syslog(LOG_ERR, "ioctl(I_SRDOPT, RMSGN): %m");
306         die(1);
307     }
308     /*
309      * Find out which interface we were given.
310      * (ppp_if handles this ioctl)
311      */
312     if (ioctl(fd, (int)SIOCGETU, &ifunit) < 0) {
313         syslog(LOG_ERR, "ioctl(SIOCGETU): %m");
314         die(1);
315     }
316
317     /* Set debug flags in driver */
318     if (ioctl(fd, (int)SIOCSIFDEBUG, &kdebugflag) < 0) {
319         syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m");
320     }
321
322     /* close stdin, stdout, stderr if they might refer to the device */
323     if (default_device && !closed_stdio) {
324         int i;
325
326         for (i = 0; i <= 2; ++i)
327             if (i != fd && i != sockfd) 
328                 close(i);
329         closed_stdio = 1;
330     }
331
332     /*
333      * Set device for non-blocking reads.
334      */
335     if ((initfdflags = fcntl(fd, F_GETFL)) == -1
336         || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
337         syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
338     }
339 }
340
341 /*  Debugging routine....  */
342
343 void prstrstack(int fd)
344 {
345     struct str_list sl;
346     struct str_mlist names[20];
347     int ret, i;
348
349     sl.sl_modlist = names;
350
351     ret = ioctl(fd, I_LIST, &sl);
352
353     if (ret >= 0) {
354         MAINDEBUG((LOG_DEBUG, "Current streams modules:\n"));
355         for (i=0; i<sl.sl_nmods; i++)
356             MAINDEBUG((LOG_DEBUG,"    %s\n", names[i].l_name));
357     } else {
358         MAINDEBUG((LOG_DEBUG,"I_LIST ioctl() failed.\n"));
359     }
360 }
361
362
363 /*
364  * disestablish_ppp - Restore the serial port to normal operation.
365  * It attempts to reconstruct the stream with the previously popped
366  * modules.  This shouldn't call die() because it's called from die().
367  */
368 void
369 disestablish_ppp(fd)
370     int fd;
371 {
372     int flags;
373     char *s;
374
375     /* Reset non-blocking mode on the file descriptor. */
376     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
377         syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
378     initfdflags = -1;
379
380     if (hungup) {
381         /* we can't push or pop modules after the stream has hung up */
382         str_module_count = 0;
383         restore_term = 0;       /* nor can we fix up terminal settings */
384         return;
385     }
386
387     if (pushed_ppp) {
388         while (ioctl(fd, I_POP, 0) == 0) /* pop any we pushed */
389             ;
390         pushed_ppp = 0;
391
392         for (; str_module_count > 0; str_module_count--) {
393             if (ioctl(fd, I_PUSH, str_modules[str_module_count-1].modname)) {
394                 if (errno != ENXIO)
395                     syslog(LOG_WARNING, "str_restore: couldn't push module %s: %m",
396                            str_modules[str_module_count-1].modname);
397             } else {
398                 MAINDEBUG((LOG_INFO, "str_restore: pushed module %s",
399                            str_modules[str_module_count-1].modname));
400             }
401         }
402
403         if (orig_ttyfd >= 0) {
404             close(fd);
405             ttyfd = orig_ttyfd;
406             fd = -1;
407         }
408     }
409
410 }
411
412 /*
413  * clean_check - check whether the link seems to be 8-bit clean.
414  */
415 void
416 clean_check()
417 {
418     if (pushed_ppp) {
419         /*
420          * Check whether the link seems not to be 8-bit clean.
421          */
422         if (ioctl(ttyfd, (int)SIOCGIFDEBUG, (caddr_t) &flags) == 0) {
423             s = NULL;
424             switch (~flags & PAI_FLAGS_HIBITS) {
425               case PAI_FLAGS_B7_0:
426                 s = "bit 7 set to 1";
427                 break;
428               case PAI_FLAGS_B7_1:
429                 s = "bit 7 set to 0";
430                 break;
431               case PAI_FLAGS_PAR_EVEN:
432                 s = "odd parity";
433                 break;
434               case PAI_FLAGS_PAR_ODD:
435                 s = "even parity";
436                 break;
437             }
438             if (s != NULL) {
439                 syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
440                 syslog(LOG_WARNING, "All received characters had %s", s);
441             }
442         }
443     }
444 }
445
446 /*
447  * List of valid speeds.
448  */
449 struct speed {
450     int speed_int, speed_val;
451 } speeds[] = {
452 #ifdef B50
453     { 50, B50 },
454 #endif
455 #ifdef B75
456     { 75, B75 },
457 #endif
458 #ifdef B110
459     { 110, B110 },
460 #endif
461 #ifdef B134
462     { 134, B134 },
463 #endif
464 #ifdef B150
465     { 150, B150 },
466 #endif
467 #ifdef B200
468     { 200, B200 },
469 #endif
470 #ifdef B300
471     { 300, B300 },
472 #endif
473 #ifdef B600
474     { 600, B600 },
475 #endif
476 #ifdef B1200
477     { 1200, B1200 },
478 #endif
479 #ifdef B1800
480     { 1800, B1800 },
481 #endif
482 #ifdef B2000
483     { 2000, B2000 },
484 #endif
485 #ifdef B2400
486     { 2400, B2400 },
487 #endif
488 #ifdef B3600
489     { 3600, B3600 },
490 #endif
491 #ifdef B4800
492     { 4800, B4800 },
493 #endif
494 #ifdef B7200
495     { 7200, B7200 },
496 #endif
497 #ifdef B9600
498     { 9600, B9600 },
499 #endif
500 #ifdef B19200
501     { 19200, B19200 },
502 #endif
503 #ifdef B38400
504     { 38400, B38400 },
505 #endif
506 #ifdef EXTA
507     { 19200, EXTA },
508 #endif
509 #ifdef EXTB
510     { 38400, EXTB },
511 #endif
512 #ifdef B57600
513     { 57600, B57600 },
514 #endif
515 #ifdef B115200
516     { 115200, B115200 },
517 #endif
518     { 0, 0 }
519 };
520
521 /*
522  * Translate from bits/second to a speed_t.
523  */
524 static int
525 translate_speed(bps)
526     int bps;
527 {
528     struct speed *speedp;
529
530     if (bps == 0)
531         return 0;
532     for (speedp = speeds; speedp->speed_int; speedp++)
533         if (bps == speedp->speed_int)
534             return speedp->speed_val;
535     syslog(LOG_WARNING, "speed %d not supported", bps);
536     return 0;
537 }
538
539 /*
540  * Translate from a speed_t to bits/second.
541  */
542 static int
543 baud_rate_of(speed)
544     int speed;
545 {
546     struct speed *speedp;
547
548     if (speed == 0)
549         return 0;
550     for (speedp = speeds; speedp->speed_int; speedp++)
551         if (speed == speedp->speed_val)
552             return speedp->speed_int;
553     return 0;
554 }
555
556 /*
557  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
558  * at the requested speed, etc.  If `local' is true, set CLOCAL
559  * regardless of whether the modem option was specified.
560  */
561 void
562 set_up_tty(fd, local)
563     int fd, local;
564 {
565     int speed;
566     struct termios tios;
567
568     if (tcgetattr(fd, &tios) < 0) {
569         syslog(LOG_ERR, "tcgetattr: %m");
570         die(1);
571     }
572
573     if (!restore_term) {
574         inittermios = tios;
575         ioctl(fd, TIOCGWINSZ, &wsinfo);
576     }
577
578     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
579     if (crtscts > 0)
580         tios.c_cflag |= CRTSCTS;
581     else if (crtscts < 0)
582         tios.c_cflag &= ~CRTSCTS;
583
584     tios.c_cflag |= CS8 | CREAD | HUPCL;
585     if (local || !modem)
586         tios.c_cflag |= CLOCAL;
587     tios.c_iflag = IGNBRK | IGNPAR;
588     tios.c_oflag = 0;
589     tios.c_lflag = 0;
590     tios.c_cc[VMIN] = 1;
591     tios.c_cc[VTIME] = 0;
592
593     if (crtscts == -2) {
594         tios.c_iflag |= IXON | IXOFF;
595         tios.c_cc[VSTOP] = 0x13;        /* DC3 = XOFF = ^S */
596         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
597     }
598
599     speed = translate_speed(inspeed);
600     if (speed) {
601         cfsetospeed(&tios, speed);
602         cfsetispeed(&tios, speed);
603     } else {
604         speed = cfgetospeed(&tios);
605         /*
606          * We can't proceed if the serial port speed is B0,
607          * since that implies that the serial port is disabled.
608          */
609         if (speed == B0) {
610             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
611                    devnam);
612             die(1);
613         }
614     }
615
616     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
617         syslog(LOG_ERR, "tcsetattr: %m");
618         die(1);
619     }
620
621     baud_rate = inspeed = baud_rate_of(speed);
622     restore_term = 1;
623 }
624
625 /*
626  * restore_tty - restore the terminal to the saved settings.
627  */
628 void
629 restore_tty(fd)
630     int fd;
631 {
632     if (restore_term) {
633         if (!default_device) {
634             /*
635              * Turn off echoing, because otherwise we can get into
636              * a loop with the tty and the modem echoing to each other.
637              * We presume we are the sole user of this tty device, so
638              * when we close it, it will revert to its defaults anyway.
639              */
640             inittermios.c_lflag &= ~(ECHO | ECHONL);
641         }
642         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
643             if (errno != ENXIO)
644                 syslog(LOG_WARNING, "tcsetattr: %m");
645         ioctl(fd, TIOCSWINSZ, &wsinfo);
646         restore_term = 0;
647     }
648 }
649
650 /*
651  * setdtr - control the DTR line on the serial port.
652  * This is called from die(), so it shouldn't call die().
653  */
654 void
655 setdtr(fd, on)
656 int fd, on;
657 {
658     int modembits = TIOCM_DTR;
659
660     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
661 }
662
663
664 /*
665  * output - Output PPP packet.
666  */
667 void
668 output(unit, p, len)
669     int unit;
670     u_char *p;
671     int len;
672 {
673     struct strbuf str;
674     int retries;
675     struct pollfd pfd;
676
677     if (debug)
678         log_packet(p, len, "sent ");
679
680     str.len = len;
681     str.buf = (caddr_t) p;
682     retries = 4;
683     while (putmsg(ttyfd, NULL, &str, 0) < 0) {
684         if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
685             if (errno != ENXIO)
686                 syslog(LOG_ERR, "Couldn't send packet: %m");
687             break;
688         }
689         pfd.fd = ttyfd;
690         pfd.events = POLLOUT;
691         poll(&pfd, 1, 250);     /* wait for up to 0.25 seconds */
692     }
693 }
694
695 /*
696  * wait_input - wait for input, for a length of time specified in *timo.
697  */
698 void
699 wait_input(timo)
700     struct timeval *timo;
701 {
702     int t;
703     struct pollfd pfd;
704
705     t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000;
706     pfd.fd = ttyfd;
707     pfd.events = POLLIN | POLLPRI | POLLHUP;
708     if (poll(&pfd, 1, t) < 0 && errno != EINTR) {
709         syslog(LOG_ERR, "poll: %m");
710         die(1);
711     }
712 }
713
714 /*
715  * read_packet - get a PPP packet from the serial device.
716  */
717 int
718 read_packet(buf)
719     u_char *buf;
720 {
721     struct strbuf str, ctl;
722     int len, i;
723     unsigned char ctlbuf[16];
724
725     str.maxlen = PPP_MTU + PPP_HDRLEN;
726     str.buf = (caddr_t) buf;
727     ctl.maxlen = sizeof(ctlbuf);
728     ctl.buf = (caddr_t) ctlbuf;
729     i = 0;
730     len = getmsg(ttyfd, &ctl, &str, &i);
731     if (len < 0) {
732         if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
733             return -1;
734         }
735         syslog(LOG_ERR, "getmsg %m");
736         die(1);
737     }
738     if (len) 
739         MAINDEBUG((LOG_DEBUG, "getmsg returned 0x%x",len));
740     if (ctl.len > 0)
741         syslog(LOG_NOTICE, "got ctrl msg len %d %x %x\n", ctl.len,
742                ctlbuf[0], ctlbuf[1]);
743
744     if (str.len < 0) {
745         MAINDEBUG((LOG_DEBUG, "getmsg short return length %d", str.len));
746         return -1;
747     }
748
749     return str.len;
750 }
751
752
753 /*
754  * ppp_send_config - configure the transmit characteristics of
755  * the ppp interface.
756  */
757 void
758 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
759     int unit, mtu;
760     u_int32_t asyncmap;
761     int pcomp, accomp;
762 {
763     char c;
764     struct ifreq ifr;
765
766     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
767     ifr.ifr_mtu = mtu;
768     if (ioctl(sockfd, (int)SIOCSIPMTU, (caddr_t) &ifr) < 0) {
769         syslog(LOG_ERR, "ioctl(SIOCSIPMTU): %m");
770         quit();
771     }
772
773     if(ioctl(ttyfd, (int)SIOCSIFASYNCMAP, (caddr_t) &asyncmap) < 0) {
774         syslog(LOG_ERR, "ioctl(SIOCSIFASYNCMAP): %m");
775         quit();
776     }
777
778     c = (pcomp? 1: 0);
779     if(ioctl(ttyfd, (int)SIOCSIFCOMPPROT, &c) < 0) {
780         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m");
781         quit();
782     }
783
784     c = (accomp? 1: 0);
785     if(ioctl(ttyfd, (int)SIOCSIFCOMPAC, &c) < 0) {
786         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m");
787         quit();
788     }
789 }
790
791
792 /*
793  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
794  */
795 void
796 ppp_set_xaccm(unit, accm)
797     int unit;
798     ext_accm accm;
799 {
800     if (ioctl(ttyfd, (int)SIOCSIFXASYNCMAP, accm) < 0 && errno != ENOTTY)
801         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
802 }
803
804
805 /*
806  * ppp_recv_config - configure the receive-side characteristics of
807  * the ppp interface.
808  */
809 void
810 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
811     int unit, mru;
812     u_int32_t asyncmap;
813     int pcomp, accomp;
814 {
815     char c;
816
817     if (ioctl(ttyfd, (int)SIOCSIFMRU, &mru) < 0) {
818         syslog(LOG_ERR, "ioctl(SIOCSIFMRU): %m");
819     }
820
821     if (ioctl(ttyfd, (int)SIOCSIFRASYNCMAP, (caddr_t) &asyncmap) < 0) {
822         syslog(LOG_ERR, "ioctl(SIOCSIFRASYNCMAP): %m");
823     }
824
825     c = 2 + (pcomp? 1: 0);
826     if(ioctl(ttyfd, (int)SIOCSIFCOMPPROT, &c) < 0) {
827         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m");
828     }
829
830     c = 2 + (accomp? 1: 0);
831     if (ioctl(ttyfd, (int)SIOCSIFCOMPAC, &c) < 0) {
832         syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m");
833     }
834 }
835
836 /*
837  * ccp_test - ask kernel whether a given compression method
838  * is acceptable for use.
839  */
840 int
841 ccp_test(unit, opt_ptr, opt_len, for_transmit)
842     int unit, opt_len, for_transmit;
843     u_char *opt_ptr;
844 {
845     struct ppp_option_data data;
846
847     if ((unsigned) opt_len > MAX_PPP_OPTION)
848         opt_len = MAX_PPP_OPTION;
849     data.length = opt_len;
850     data.transmit = for_transmit;
851     BCOPY(opt_ptr, data.opt_data, opt_len);
852     if (ioctl(ttyfd, (int)SIOCSCOMPRESS, (caddr_t) &data) >= 0)
853         return 1;
854     return (errno == ENOSR)? 0: -1;
855 }
856
857 /*
858  * ccp_flags_set - inform kernel about the current state of CCP.
859  */
860 void
861 ccp_flags_set(unit, isopen, isup)
862     int unit, isopen, isup;
863 {
864     int x;
865
866     x = (isopen? 1: 0) + (isup? 2: 0);
867     if (ioctl(ttyfd, (int)SIOCSIFCOMP, (caddr_t) &x) < 0 && errno != ENOTTY)
868         syslog(LOG_ERR, "ioctl (SIOCSIFCOMP): %m");
869 }
870
871 /*
872  * ccp_fatal_error - returns 1 if decompression was disabled as a
873  * result of an error detected after decompression of a packet,
874  * 0 otherwise.  This is necessary because of patent nonsense.
875  */
876 int
877 ccp_fatal_error(unit)
878     int unit;
879 {
880     int x;
881
882     if (ioctl(ttyfd, (int)SIOCGIFCOMP, (caddr_t) &x) < 0) {
883         syslog(LOG_ERR, "ioctl(SIOCGIFCOMP): %m");
884         return 0;
885     }
886     return x & CCP_FATALERROR;
887 }
888
889 /*
890  * sifvjcomp - config tcp header compression
891  */
892 int
893 sifvjcomp(u, vjcomp, cidcomp, maxcid)
894     int u, vjcomp, cidcomp, maxcid;
895 {
896     char x;
897
898     x = (vjcomp? 1: 0) + (cidcomp? 0: 2) + (maxcid << 4);
899     if (ioctl(ttyfd, (int)SIOCSIFVJCOMP, (caddr_t) &x) < 0) {
900         syslog(LOG_ERR, "ioctl(SIOCSIFVJCOMP): %m");
901         return 0;
902     }
903     return 1;
904 }
905
906 /*
907  * sifup - Config the interface up and enable IP packets to pass.
908  */
909 int
910 sifup(u)
911     int u;
912 {
913     struct ifreq ifr;
914
915     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
916     if (ioctl(sockfd, (int)SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
917         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
918         return 0;
919     }
920     ifr.ifr_flags |= IFF_UP;
921     if (ioctl(sockfd, (int)SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
922         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
923         return 0;
924     }
925     if_is_up = 1;
926     return 1;
927 }
928
929 /*
930  * sifdown - Config the interface down.
931  */
932 int
933 sifdown(u)
934     int u;
935 {
936     struct ifreq ifr;
937     int rv;
938     struct npioctl npi;
939
940     rv = 1;
941     npi.protocol = PPP_IP;
942     npi.mode = NPMODE_ERROR;
943     ioctl(ttyfd, (int)SIOCSETNPMODE, (caddr_t) &npi);   /* ignore errors */
944
945     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
946     if (ioctl(sockfd, (int)SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
947         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
948         rv = 0;
949     } else {
950         ifr.ifr_flags &= ~IFF_UP;
951         if (ioctl(sockfd, (int)SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
952             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
953             rv = 0;
954         } else
955             if_is_up = 0;
956     }
957     return rv;
958 }
959
960 /*
961  * SET_SA_FAMILY - initialize a struct sockaddr, setting the sa_family field.
962  */
963 #define SET_SA_FAMILY(addr, family)             \
964     BZERO((char *) &(addr), sizeof(addr));      \
965     addr.sa_family = (family);                  \
966     addr.sa_len = sizeof ((addr))
967
968 /*
969  * sifaddr - Config the interface IP addresses and netmask.
970  */
971 int
972 sifaddr(u, o, h, m)
973     int u;
974     u_int32_t o, h, m;
975 {
976     struct ifreq ifr;
977     struct ifaliasreq addreq;
978     int ret;
979
980     ret = 1;
981
982     /* flush old address, if any
983      */
984     bzero(&ifr, sizeof (ifr));
985     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
986     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
987     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
988     if ((ioctl(sockfd, (int)SIOCDIFADDR, (caddr_t) &ifr) < 0)
989         && errno != EADDRNOTAVAIL) {
990         syslog(LOG_ERR, "ioctl(SIOCDIFADDR): %m");
991         ret = 0;
992     }
993
994     bzero(&addreq, sizeof (addreq));
995     strncpy(addreq.ifra_name, ifname, sizeof (addreq.ifra_name));
996     SET_SA_FAMILY(addreq.ifra_addr, AF_INET);
997     SET_SA_FAMILY(addreq.ifra_broadaddr, AF_INET);
998     ((struct sockaddr_in *)&addreq.ifra_addr)->sin_addr.s_addr = o;
999     ((struct sockaddr_in *)&addreq.ifra_broadaddr)->sin_addr.s_addr = h;
1000
1001     if (m != 0) {
1002         ((struct sockaddr_in *)&addreq.ifra_mask)->sin_addr.s_addr = m;
1003         addreq.ifra_mask.sa_len = sizeof (struct sockaddr);
1004         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
1005     }
1006   
1007     /* install new src/dst and (possibly) netmask
1008      */
1009     if (ioctl(sockfd, SIOCPIFADDR, &addreq) < 0) {
1010         syslog(LOG_ERR, "ioctl(SIOCPIFADDR): %m");
1011         ret = 0;
1012     }
1013   
1014     ifaddrs[0] = o;
1015     ifaddrs[1] = h;
1016     return (ret);
1017 }
1018
1019 /*
1020  * cifaddr - Clear the interface IP addresses, and delete routes
1021  * through the interface if possible.
1022  */
1023 int
1024 cifaddr(u, o, h)
1025     int u;
1026     u_int32_t o, h;
1027 {
1028     struct ifreq ifr;
1029
1030     ifaddrs[0] = 0;
1031     bzero(&ifr, sizeof (ifr));
1032     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1033     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
1034     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
1035     if (ioctl(sockfd, (int)SIOCDIFADDR, (caddr_t) &ifr) < 0) {
1036         syslog(LOG_ERR, "ioctl(SIOCDIFADDR): %m");
1037         return 0;
1038     }
1039     return 1;
1040 }
1041
1042 /*
1043  * sifdefaultroute - assign a default route through the address given.
1044  */
1045 int
1046 sifdefaultroute(u, g)
1047     int u;
1048     u_int32_t g;
1049 {
1050     struct ortentry rt;
1051
1052     BZERO(&rt, sizeof(rt));
1053     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1054     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1055     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1056     rt.rt_flags = RTF_GATEWAY;
1057     if (ioctl(sockfd, (int)SIOCADDRT, &rt) < 0) {
1058         syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
1059         return 0;
1060     }
1061     default_route_gateway = g;
1062     return 1;
1063 }
1064
1065 /*
1066  * cifdefaultroute - delete a default route through the address given.
1067  */
1068 int
1069 cifdefaultroute(u, g)
1070     int u;
1071     u_int32_t g;
1072 {
1073     struct ortentry rt;
1074
1075     BZERO(&rt, sizeof(rt));
1076     SET_SA_FAMILY(rt.rt_dst, AF_INET);
1077     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
1078     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
1079     rt.rt_flags = RTF_GATEWAY;
1080     if (ioctl(sockfd, (int)SIOCDELRT, &rt) < 0) {
1081         syslog(LOG_ERR, "default route ioctl(SIOCDELRT): %m");
1082         return 0;
1083     }
1084     default_route_gateway = 0;
1085     return 1;
1086 }
1087
1088 /*
1089  * sifproxyarp - Make a proxy ARP entry for the peer.
1090  */
1091 int
1092 sifproxyarp(unit, hisaddr)
1093     int unit;
1094     u_int32_t hisaddr;
1095 {
1096     struct arpreq arpreq;
1097
1098     BZERO(&arpreq, sizeof(arpreq));
1099
1100     /*
1101      * Get the hardware address of an interface on the same subnet
1102      * as our local address.
1103      */
1104     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
1105         syslog(LOG_WARNING, "Cannot determine ethernet address for proxy ARP");
1106         return 0;
1107     }
1108
1109     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1110     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1111     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1112     if (ioctl(sockfd, (int)SIOCSARP, (caddr_t)&arpreq) < 0) {
1113         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1114         return 0;
1115     }
1116
1117     proxy_arp_addr = hisaddr;
1118     return 1;
1119 }
1120
1121 /*
1122  * cifproxyarp - Delete the proxy ARP entry for the peer.
1123  */
1124 int
1125 cifproxyarp(unit, hisaddr)
1126     int unit;
1127     u_int32_t hisaddr;
1128 {
1129     struct arpreq arpreq;
1130
1131     BZERO(&arpreq, sizeof(arpreq));
1132     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1133     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1134     if (ioctl(sockfd, (int)SIOCDARP, (caddr_t)&arpreq) < 0) {
1135         syslog(LOG_ERR, "ioctl(SIOCDARP): %m");
1136         return 0;
1137     }
1138     proxy_arp_addr = 0;
1139     return 1;
1140 }
1141
1142 /*
1143  * get_ether_addr - get the hardware address of an interface on the
1144  * the same subnet as ipaddr.
1145  */
1146 #define MAX_IFS         32
1147
1148 int s;
1149
1150 static int
1151 get_ether_addr(ipaddr, hwaddr)
1152     u_int ipaddr;
1153     struct sockaddr *hwaddr;
1154 {
1155     struct ifreq *ifr, *ifend, *ifp;
1156     u_int ina, mask;
1157     struct sockaddr_dl *dla;
1158     struct ifreq ifreq;
1159     struct ifconf ifc;
1160     struct ifreq ifs[MAX_IFS];
1161     struct ifdevea ifdevreq;
1162
1163     ifc.ifc_len = sizeof(ifs);
1164     ifc.ifc_req = ifs;
1165     if (ioctl(sockfd, (int)SIOCGIFCONF, &ifc) < 0) {
1166         perror("ioctl(SIOCGIFCONF)");
1167         return 0;
1168     }
1169
1170     /*
1171      * Scan through looking for an interface with an Internet
1172      * address on the same subnet as `ipaddr'.
1173      */
1174     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1175     for (ifr = ifc.ifc_req; ifr < ifend; +ifr = (struct ifreq *)
1176                 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len) {
1177         if (ifr->ifr_addr.sa_family == AF_INET) {
1178             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1179             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1180             /*
1181              * Check that the interface is up, and not point-to-point
1182              * or loopback.
1183              */
1184             if (ioctl(sockfd, (int)SIOCGIFFLAGS, &ifreq) < 0)
1185                 continue;
1186             if ((ifreq.ifr_flags &
1187                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1188                  != (IFF_UP|IFF_BROADCAST))
1189                 continue;
1190             /*
1191              * Get its netmask and check that it's on the right subnet.
1192              */
1193             if (ioctl(sockfd, (int)SIOCGIFNETMASK, &ifreq) < 0)
1194                 continue;
1195             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1196             if ((ipaddr & mask) != (ina & mask))
1197                 continue;
1198
1199             break;
1200         }
1201     }
1202
1203     if (ifr >= ifend)
1204         return 0;
1205     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1206
1207     strncpy(ifdevreq.ifr_name, ifr->ifr_name, sizeof(ifdevreq.ifr_name));
1208
1209     if (ioctl(sockfd, (int)SIOCRPHYSADDR, &ifdevreq) < 0) {
1210         perror("ioctl(SIOCRPHYSADDR)");
1211         return(0);
1212     }
1213
1214     hwaddr->sa_family = AF_UNSPEC;
1215     memcpy(hwaddr->sa_data, ifdevreq.current_pa, sizeof(ifdevreq.current_pa));
1216     return(1);
1217 }
1218
1219
1220 /*
1221  * Return user specified netmask, modified by any mask we might determine
1222  * for address `addr' (in network byte order).
1223  * Here we scan through the system's list of interfaces, looking for
1224  * any non-point-to-point interfaces which might appear to be on the same
1225  * network as `addr'.  If we find any, we OR in their netmask to the
1226  * user-specified netmask.
1227  */
1228 u_int32_t
1229 GetMask(addr)
1230     u_int32_t addr;
1231 {
1232     u_int32_t mask, nmask, ina;
1233     struct ifreq *ifr, *ifend, ifreq;
1234     struct ifconf ifc;
1235     struct ifreq ifs[MAX_IFS];
1236
1237     addr = ntohl(addr);
1238     if (IN_CLASSA(addr))        /* determine network mask for address class */
1239         nmask = IN_CLASSA_NET;
1240     else if (IN_CLASSB(addr))
1241         nmask = IN_CLASSB_NET;
1242     else
1243         nmask = IN_CLASSC_NET;
1244     /* class D nets are disallowed by bad_ip_adrs */
1245     mask = netmask | htonl(nmask);
1246
1247     /*
1248      * Scan through the system's network interfaces.
1249      */
1250     ifc.ifc_len = sizeof(ifs);
1251     ifc.ifc_req = ifs;
1252     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1253         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1254         return mask;
1255     }
1256     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1257     for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
1258         /*
1259          * Check the interface's internet address.
1260          */
1261         if (ifr->ifr_addr.sa_family != AF_INET)
1262             continue;
1263         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1264         if ((ntohl(ina) & nmask) != (addr & nmask))
1265             continue;
1266         /*
1267          * Check that the interface is up, and not point-to-point or loopback.
1268          */
1269         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1270         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1271             continue;
1272         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1273             != IFF_UP)
1274             continue;
1275         /*
1276          * Get its netmask and OR it into our mask.
1277          */
1278         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1279             continue;
1280         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1281     }
1282
1283     return mask;
1284 }
1285
1286
1287 #define WTMPFILE        "/usr/adm/wtmp"
1288 #include <sys/stat.h>
1289
1290 void
1291 logwtmp(line, name, host)
1292     char *line, *name, *host;
1293 {
1294     int fd;
1295     struct stat buf;
1296     struct utmp ut;
1297
1298     if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
1299         return;
1300     if (!fstat(fd, &buf)) {
1301         (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1302         (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1303         (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1304         (void)time(&ut.ut_time);
1305         if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp))
1306             (void)ftruncate(fd, buf.st_size);
1307     }
1308     close(fd);
1309 }
1310
1311 /*
1312  * Code for locking/unlocking the serial device.
1313  * This code is derived from chat.c.
1314  */
1315
1316 #ifndef LOCK_DIR
1317 #  ifdef HDB
1318 #   define      PIDSTRING
1319 #   define      LOCK_PREFIX     "/usr/spool/locks/LCK.."
1320 #  else /* HDB */
1321 #   define      LOCK_PREFIX     "/usr/spool/uucp/LCK.."
1322 #  endif /* HDB */
1323 #endif /* LOCK_DIR */
1324
1325 static char *lock_file;
1326
1327 /*
1328  * lock - create a lock file for the named device
1329  */
1330 int
1331 lock(dev)
1332     char *dev;
1333 {
1334     char hdb_lock_buffer[12];
1335     int fd, pid, n;
1336     char *p;
1337
1338     if ((p = strrchr(dev, '/')) != NULL)
1339         dev = p + 1;
1340     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1341     if (lock_file == NULL)
1342         novm("lock file name");
1343     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1344
1345     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1346         if (errno == EEXIST
1347             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1348             /* Read the lock file to find out who has the device locked */
1349 #ifdef PIDSTRING
1350             n = read(fd, hdb_lock_buffer, 11);
1351             if (n > 0) {
1352                 hdb_lock_buffer[n] = 0;
1353                 pid = atoi(hdb_lock_buffer);
1354             }
1355 #else
1356             n = read(fd, &pid, sizeof(pid));
1357 #endif
1358             if (n <= 0) {
1359                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1360                 close(fd);
1361             } else {
1362                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1363                     /* pid no longer exists - remove the lock file */
1364                     if (unlink(lock_file) == 0) {
1365                         close(fd);
1366                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1367                                dev, pid);
1368                         continue;
1369                     } else
1370                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1371                                dev);
1372                 } else
1373                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1374                            dev, pid);
1375             }
1376             close(fd);
1377         } else
1378             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1379         free(lock_file);
1380         lock_file = NULL;
1381         return -1;
1382     }
1383
1384 # ifdef PIDSTRING
1385     sprintf(hdb_lock_buffer, "%10d\n", getpid());
1386     write(fd, hdb_lock_buffer, 11);
1387 # else
1388     pid = getpid();
1389     write(fd, &pid, sizeof pid);
1390 # endif
1391
1392     close(fd);
1393     return 0;
1394 }
1395
1396 /*
1397  * unlock - remove our lockfile
1398  */
1399 void
1400 unlock()
1401 {
1402     if (lock_file) {
1403         unlink(lock_file);
1404         free(lock_file);
1405         lock_file = NULL;
1406     }
1407 }
1408