2 * diald.c - Demand dialing daemon for ppp.
4 * Copyright (c) 1994, 1995, 1996 Eric Schenk.
5 * All rights reserved. Please see the file LICENSE which should be
6 * distributed with this software for terms of use.
8 * Portions of this code were derived from the code for pppd copyright
9 * (c) 1989 Carnegie Mellon University. The copyright notice on this code
10 * is reproduced below.
12 * Copyright (c) 1989 Carnegie Mellon University.
13 * All rights reserved.
15 * Redistribution and use in source and binary forms are permitted
16 * provided that the above copyright notice and this paragraph are
17 * duplicated in all such forms and that any documentation,
18 * advertising materials, and other materials related to such
19 * distribution and use acknowledge that the software was developed
20 * by Carnegie Mellon University. The name of the
21 * University may not be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
49 /* intialized variables. */
50 int modem_fd = -1; /* modem device fp (for proxy reads) */
51 MONITORS *monitors = 0; /* Monitor pipes */
52 int modem_hup = 0; /* have we seen a modem HUP? */
53 int sockfd = -1; /* controling socket */
54 int delayed_quit = 0; /* has the user requested a delayed quit? */
55 int request_down = 0; /* has the user requested link down? */
56 int request_up = 0; /* has the user requested link down? */
57 int forced = 0; /* has the user requested the link forced up? */
58 int link_pid = 0; /* current protocol control command pid */
59 int dial_pid = 0; /* current dial command pid */
60 int running_pid = 0; /* current system command pid */
61 int running_status = 0; /* status of last system command */
62 int dial_status = 0; /* status from last dial command */
63 int state_timeout = -1; /* state machine timeout counter */
64 int proxy_iface = 0; /* Interface for the proxy */
65 int link_iface = -1; /* Interface for the link */
66 int force_dynamic = 0; /* true if connect passed back an addr */
67 int redial_rtimeout = -1; /* initialized value */
68 int dial_failures = 0; /* count of dialing failures */
69 int ppp_half_dead = 0; /* is the ppp link half dead? */
72 static PIPE fifo_pipe;
83 /* Get the default defs and config files first */
84 parse_options_file(DIALD_DEFS_FILE);
85 parse_options_file(DIALD_CONFIG_FILE);
86 /* Get the command line modifications */
87 parse_args(argc_save-1,argv_save+1);
88 /* Do validity checks on the setup */
95 orig_local_ip = strdup(local_ip);
96 orig_remote_ip = strdup(remote_ip);
99 int main(int argc, char *argv[])
102 struct timeval timeout;
108 /* initialize system log interface */
109 openlog("diald", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_LOCAL2);
111 /* initialize a firewall unit so we can store our options */
112 /* If I get things into a device this should be an "open" */
113 fwunit = ctl_firewall(IP_FW_OPEN,0);
120 /* Get an internet socket for doing socket ioctls. */
121 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
124 syslog(LOG_ERR, "Couldn't create IP socket: %m");
130 if (debug&DEBUG_VERBOSE)
131 syslog(LOG_INFO,"Starting diald version %s",VERSION);
136 /* get a pty and open up a proxy link on it */
137 if (openpty(&proxy_mfd,&proxy_sfd, NULL, NULL, NULL) < 0)
140 fcntl(proxy_mfd,F_SETFL,fcntl(proxy_mfd,F_GETFL)|O_NONBLOCK);
142 proxy_mfp = fdopen(proxy_mfd,"r+");
146 if (debug&DEBUG_VERBOSE)
147 syslog(LOG_INFO,"Diald initial setup completed.");
150 timeout.tv_sec = PAUSETIME;
153 /* wait up to a second for an event */
156 FD_SET(fifo_fd,&readfds);
157 FD_SET(proxy_mfd,&readfds);
158 FD_SET(snoopfd,&readfds);
159 sel = select(100,&readfds,0,0,&timeout);
161 /* read user commands off the fifo */
162 if (fifo_fd != -1 && FD_ISSET(fifo_fd,&readfds)) fifo_read();
164 /* update the connection filters */
165 if (FD_ISSET(snoopfd,&readfds)) filter_read();
167 /* deal with packets coming into the pty proxy link */
168 if (FD_ISSET(proxy_mfd,&readfds)) proxy_read();
170 if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
171 /* advance the clock 1 second */
172 timeout.tv_sec = PAUSETIME;
174 if (state_timeout > 0) state_timeout--;
175 if (debug&DEBUG_TICK)
176 syslog(LOG_DEBUG,"--- tick --- state %d block %d state_timeout %d",state,blocked,state_timeout);
184 /* Write the pid and optionally the proxy interface to the pid file */
186 void create_pidfile(int iface)
189 if ((fp = fopen(pidfile,"w")) != NULL) {
190 fprintf(fp,"%d\n",getpid());
192 fprintf(fp,"sl%d\n",proxy_iface);
195 syslog(LOG_ERR,"Unable to create run file %s: %m",pidfile);
200 * Change into a daemon.
201 * Get rid of the stdio streams, and disassociate from the original
202 * controling terminal, and become a group leader.
213 /* go into the background */
214 if ((pid = fork()) < 0) {
215 syslog(LOG_ERR,"Could not fork into background: %m");
218 /* parent process is finished */
219 if (pid != 0) exit(0);
221 #endif /* __uClinux__ */
222 if (pidlog[0] == '/') {
226 pidfile = malloc(strlen(RUN_PREFIX) + strlen(pidlog) + 2);
227 sprintf(pidfile,"%s/%s",RUN_PREFIX,pidlog);
232 /* Open the command fifo, if any */
239 if (stat(fifoname,&sbuf) < 0 || !(sbuf.st_mode&S_IFIFO)) {
240 syslog(LOG_INFO,"Creating FIFO");
241 /* Create the fifo. */
242 mknod(fifoname, S_IFIFO|0277, 0);
243 chmod(fifoname, 0600);
245 /* We need to open this RDWR to make select() work the
246 * way we want in kernels after 1.3.81. In particular
247 * we don't want select() to return 1 whenever there
248 * are no writers on the remote side of the command fifo.
249 * This guarantees that there is always at least one writer...
251 if ((fifo_fd = open(fifoname, O_RDWR | O_NDELAY)) >= 0) {
252 if (debug&DEBUG_VERBOSE)
253 syslog(LOG_INFO,"Using fifo %s",fifoname);
254 pipe_init(fifo_fd,&fifo_pipe);
256 syslog(LOG_ERR,"Could not open fifo file %s",fifoname);
260 /* make sure to invalidate the fifo_fd if we don't open one. */
267 * Set up the signal handlers.
269 static sigset_t sig_mask;
274 /* set up signal handlers */
276 sigemptyset(&sig_mask);
277 sigaddset(&sig_mask, SIGHUP);
278 sigaddset(&sig_mask, SIGINT);
279 sigaddset(&sig_mask, SIGTERM);
280 sigaddset(&sig_mask, SIGUSR1);
281 sigaddset(&sig_mask, SIGUSR2);
282 sigaddset(&sig_mask, SIGCHLD);
283 sigaddset(&sig_mask, SIGALRM);
284 sigaddset(&sig_mask, SIGPIPE);
286 #define SIGNAL(s, handler) { \
287 sa.sa_handler = handler; \
288 if (sigaction(s, &sa, NULL) < 0) { \
289 syslog(LOG_ERR, "sigaction(%d): %m", s); \
294 sa.sa_mask = sig_mask;
297 SIGNAL(SIGHUP, sig_hup); /* Hangup: modem went down. */
298 SIGNAL(SIGINT, sig_intr); /* Interrupt: take demand dialer down */
299 SIGNAL(SIGTERM, sig_term); /* Terminate: user take link down */
300 SIGNAL(SIGUSR1, linkup); /* User requests the link to go up */
301 SIGNAL(SIGUSR2, print_filter_queue); /* dump the packet queue to the log */
302 SIGNAL(SIGCHLD, sig_chld); /* reap dead kids */
303 SIGNAL(SIGPIPE, SIG_IGN);
308 sigprocmask(SIG_BLOCK, &sig_mask, NULL);
311 void default_sigacts()
314 sa.sa_mask = sig_mask;
317 SIGNAL(SIGHUP, SIG_DFL);
318 SIGNAL(SIGINT, SIG_DFL);
319 SIGNAL(SIGTERM, SIG_DFL);
320 SIGNAL(SIGUSR1, SIG_DFL);
321 SIGNAL(SIGUSR2, SIG_DFL);
322 SIGNAL(SIGCHLD, SIG_DFL);
323 SIGNAL(SIGALRM, SIG_DFL);
324 SIGNAL(SIGPIPE, SIG_DFL);
327 void unblock_signals()
329 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
334 * Get a pty and open both the slave and master sides.
337 int openpty(int *mfd, int *sfd, void *name, void *termios, void *win)
339 char *ptys = "0123456789abcdef";
341 static char buf[128];
343 for (c = 'p'; c <= 's'; c++)
344 for (i = 0; i < 16; i++) {
345 sprintf(buf,"/dev/pty%c%c",c,ptys[i]);
346 if ((*mfd = open(buf,O_RDWR)) >= 0) {
347 sprintf(buf,"/dev/tty%c%c",c,ptys[i]);
348 if ((*sfd = open(buf,O_RDWR|O_NOCTTY|O_NDELAY)) < 0) {
349 syslog(LOG_ERR,"Can't open slave side of pty: %m");
355 syslog(LOG_ERR,"No pty found in range pty[p-s][0-9a-f]\n");
360 /* Read a request off the fifo.
361 * Valid requests are:
362 * block - block diald from calling out.
363 * unblock - unblock diald from calling out.
364 * down - bring the link down.
365 * up - bring the link up.
366 * delayed-quit - quit next time diald is idle.
367 * quit - stop diald in its tracks.
368 * queue - dump the filter queue.
369 * debug level - set the debug level.
370 * force - force diald to put the connection up and keep it up.
371 * unforce - remove the forced up requirement.
372 * connect pid dev - go up on a connection to the named port.
373 * We assume the connection negotiations are
374 * already finished and any lock files are in place.
375 * When the connection should be killed we send a
376 * SIGTERM to the given pid.
377 * dynamic <lip> <rip> - pass back dynamic IP config info to diald.
378 * message <txt> - set the message text from the connect script.
379 * monitor file - start a monitoring program.
380 * reset - reread the configuration information.
389 i = pipe_read(&fifo_pipe);
390 buf = tail = fifo_pipe.buf;
400 /* Ok, we've got a line, now we need to "parse" it. */
401 if (strcmp(buf,"block") == 0) {
402 char sbuf[sizeof(PATH_IFCONFIG SL_DOWN) + 10];
403 syslog(LOG_INFO, "FIFO: Block request received.");
404 snprintf(sbuf, sizeof(sbuf), PATH_IFCONFIG SL_DOWN, proxy_iface);
406 snprintf(sbuf, sizeof(sbuf), PATH_IFCONFIG SL_UP, proxy_iface);
409 } else if (strcmp(buf, "state") == 0) {
411 } else if (strcmp(buf,"unblock") == 0) {
412 syslog(LOG_INFO, "FIFO: Unblock request received.");
414 } else if (strcmp(buf,"force") == 0) {
415 syslog(LOG_INFO, "FIFO: Force request received.");
417 } else if (strcmp(buf,"unforce") == 0) {
418 syslog(LOG_INFO, "FIFO: Unforce request received.");
420 } else if (strcmp(buf,"down") == 0) {
421 syslog(LOG_INFO, "FIFO: Link down request received.");
424 } else if (strcmp(buf,"up") == 0) {
425 syslog(LOG_INFO, "FIFO: Link up request received.");
428 } else if (strcmp(buf,"delayed-quit") == 0) {
429 syslog(LOG_INFO, "FIFO. Delayed termination request received.");
431 } else if (strcmp(buf,"quit") == 0) {
432 syslog(LOG_INFO, "FIFO. Termination request received.");
434 } else if (strcmp(buf,"reset") == 0) {
435 syslog(LOG_INFO, "FIFO. Reset request received. Re-reading configuration.");
437 } else if (strcmp(buf,"queue") == 0) {
438 struct firewall_req req;
439 syslog(LOG_INFO,"FIFO. User requested dump of firewall queue.");
440 syslog(LOG_INFO,"--------------------------------------");
442 ctl_firewall(IP_FW_PCONN,&req);
443 syslog(LOG_INFO,"--------------------------------------");
444 } else if (sscanf(buf,"debug %d", &pid) == 1) {
445 syslog(LOG_INFO,"FIFO. Changing debug flags to %d.",pid);
447 } else if (sscanf(buf,"dynamic %n%*s%n %n",&j,&k,&l) == 1) {
449 if (inet_addr(buf+j) == (unsigned long)0xffffffff
450 || inet_addr(buf+l) == (unsigned long)0xffffffff) {
451 syslog(LOG_INFO,"FIFO: bad parameters '%s' and '%s' to dynamic command ignored", buf+j,buf+l);
457 local_ip = strdup(buf+j);
458 remote_ip = strdup(buf+l);
461 } else if (strncmp(buf,"monitor", 7) == 0) {
467 if (sscanf(buf,"monitor %d %n",&j,&k) == 1) {
468 syslog(LOG_INFO,"FIFO: monitor connection at info level %d to %s requested",
470 } else if (buf[7] != 0 && buf[7] == ' ') {
471 syslog(LOG_INFO,"FIFO: full monitor connection to %s requested",
473 j = 255; /* Heavy weight connection requested */
477 /* Check list to see if this is just a status change */
480 if (strcmp(new->name,buf+k) == 0) {
488 if (stat(fifoname,&sbuf) < 0 || !sbuf.st_mode&S_IFIFO) {
489 syslog(LOG_INFO,"FIFO: %s not a pipe.",
491 } else if ((fd = open(buf+k,O_WRONLY))<0) {
492 syslog(LOG_INFO,"FIFO: could not open pipe %s: %m",
495 new = (MONITORS *)malloc(sizeof(MONITORS));
496 new->name = strdup(buf+k);
497 new->next = monitors;
505 syslog(LOG_INFO,"FIFO: empty monitor request ignored");
507 } else if (strncmp(buf,"message ",8) == 0) {
508 /* pass a message from the connector on to the monitor */
510 mon_write(MONITOR_MESSAGE,"MESSAGE\n",8);
511 mon_write(MONITOR_MESSAGE,buf+8,strlen(buf+8));
512 mon_write(MONITOR_MESSAGE,"\n",1);
514 } else if (sscanf(buf,"connect %d %n", &pid, &dev) == 1) {
516 if ((state != STATE_DOWN && state != STATE_CLOSE
518 || state==STATE_UP || req_pid) {
519 /* somebody else already has this diald, tell 'em */
521 syslog(LOG_INFO,"FIFO: link up requested but denied");
524 req_dev = (char *)malloc(tail-(buf+dev)+1);
527 syslog(LOG_ERR,"FIFO: no memory to store requested devce!");
529 strcpy(req_dev, buf+dev);
532 syslog(LOG_INFO,"FIFO: link up requested on device %s", req_dev);
536 } else if (strncmp(buf, "interface ", 10) == 0) {
537 syslog(LOG_INFO, "FIFO: interface set to %s.", buf+10);
538 dev = strcspn(buf + 10, "0123456789");
540 link_iface = atoi(buf + (10 + dev));
542 syslog(LOG_ERR,"Unknown request '%s' made.", buf);
549 pipe_flush(&fifo_pipe,buf-fifo_pipe.buf);
553 * Deal with master side packet on the SLIP link.
561 /* read the SLIP packet */
562 len = recv_packet(buffer,4096);
565 /* if we are doing unsafe routing, all counting is in the filter.
566 * otherwise we can see transmitted bytes directly at this spot.
570 rxtotal -= len; /* since it will double count on the snoop */
574 /* If we get here with the link up and fwdfd not -1,
575 * and we are rerouting, then it must be
576 * that the external interface has gone down without
577 * taking the link with it, and as a result our route
578 * to the external interface got lost. (This CAN legally
579 * happen with PPP). In this case we buffer the packet so
580 * we can retransmit it when the link comes back up.
582 * the kernel is retransmitting something through sl0, despite
583 * the existance of a route through another device...
586 /* if the external iface is up then probably we can send it on */
587 if (link_iface != -1 && fwdfd != -1) {
588 /* Make sure we try to restore the link to working condition now... */
589 if (do_reroute && mode == MODE_PPP) {
590 /* Check if a route exists at this point through the ppp device. */
591 /* If not then we must be half dead. */
592 if (!ppp_route_exists()) {
593 /* The external iface is down, buffer the packet so we can
594 * forward it when the iface comes up.
598 buffer_packet(len,buffer);
603 /* Ok, the interface is there, and the route is up,
604 * so just send it on. This can happen when routing is switched
605 * in the middle of a retransmission sequence. (There is a race
606 * between the route switching and the forwarding I think.)
609 #ifdef HAS_SOCKADDR_PKT
610 to.spkt_family = AF_INET;
611 strcpy(to.spkt_device,snoop_dev);
612 to.spkt_protocol = htons(ETH_P_IP);
614 to.sa_family = AF_INET;
615 strcpy(to.sa_data,snoop_dev);
617 if (debug&DEBUG_VERBOSE)
618 syslog(LOG_DEBUG,"Forwarding packet of length %d",len);
619 if (sendto(fwdfd,buffer,len,0,(struct sockaddr *)&to,sizeof(struct SOCKADDR)) < 0) {
621 "Error forwarding data packet to physical device: %m");
624 /* If the link isn't up, then we better buffer the packets */
626 buffer_packet(len,buffer);
631 * Terminate diald gracefully.
634 static int in_die = 0;
642 /* We're killing without a care here. Uhggg. */
643 if (link_pid) kill(link_pid,SIGINT);
644 if (dial_pid) kill(dial_pid,SIGINT);
645 if (running_pid) kill(running_pid,SIGINT);
646 /* Wait up to 30 seconds for them to die */
647 for (count = 0; (link_pid || dial_pid) && count < 30; count++)
649 /* If they aren't dead yet, kill them for sure */
650 if (link_pid) kill(link_pid,SIGKILL);
651 if (dial_pid) kill(dial_pid,SIGKILL);
652 if (running_pid) kill(running_pid,SIGKILL);
653 /* Give the system a second to send the signals */
654 if (link_pid || dial_pid || running_pid) sleep(1);
668 * Modem link went down.
670 void sig_hup(int sig)
672 syslog(LOG_INFO, "SIGHUP: modem got hung up on.");
677 * User wants the link to go down.
678 * (Perhaps there should be a 10 second delay? Configurable????)
680 void sig_intr(int sig)
682 syslog(LOG_INFO, "SIGINT: Link down request received.");
688 * The user has requested that the link be put up.
692 syslog(LOG_INFO, "SIGUSR1. External link up request received.");
698 * A child process died. Find out which one.
700 void sig_chld(int sig)
705 while ((pid = waitpid(-1,&status,WNOHANG)) > 0) {
706 if (debug&DEBUG_VERBOSE)
707 syslog( LOG_DEBUG, "SIGCHLD[%d]: pid %d %s, status %d", seq, pid,
708 pid == link_pid ? "link"
709 : pid == dial_pid ? "dial"
710 : pid == running_pid ? "system"
713 if (pid == link_pid) link_pid = 0;
714 else if (pid == dial_pid) { dial_status = status; dial_pid = 0; }
715 else if (pid == running_pid) { running_status = status; running_pid = 0; }
716 else if (!WIFEXITED(status))
717 syslog(LOG_ERR,"Abnormal exit (status %d) on pid %d",status,pid);
718 else if (WEXITSTATUS(status) != 0)
719 syslog(LOG_ERR,"Nonzero exit status (%d) on pid %d",
720 WEXITSTATUS(status),pid);
722 if (WIFSIGNALED(status)) {
723 syslog(LOG_WARNING, "child process %d terminated with signal %d",
724 pid, WTERMSIG(status));
728 if (pid && errno != ECHILD)
729 syslog(LOG_ERR, "waitpid: %m");
734 * User wants diald to be terminated.
736 void sig_term(int sig)
738 syslog(LOG_INFO, "SIGTERM. Termination request received.");
742 int report_system_result(int res,char *buf)
745 syslog(LOG_ERR,"System call failure on command '%s'",buf);
746 else if (!WIFEXITED(res))
747 syslog(LOG_ERR,"Abnormal exit (status %d) on command '%s'",res,buf);
748 else if (WEXITSTATUS(res) != 0)
749 syslog(LOG_ERR,"Nonzero exit status (%d) on command '%s'",WEXITSTATUS(res),buf);
756 int system(const char *buf)
763 pid = running_pid = vfork();
765 if (debug&DEBUG_VERBOSE)
766 syslog(LOG_DEBUG, "running system pid=%d \"%s\"", pid, buf);
769 if (debug&DEBUG_VERBOSE)
770 syslog(LOG_DEBUG,"running '%s'",buf);
771 pid = running_pid = fork();
774 if (pid != 0) unblock_signals();
777 syslog(LOG_ERR, "failed to fork and run '%s': %m",buf);
782 /* change the signal actions back to the defaults, then unblock them. */
786 /* Leave the current location */
787 (void) setsid(); /* No controlling tty. */
788 (void) umask (S_IRWXG|S_IRWXO);
789 (void) chdir ("/"); /* no current directory. */
791 /* close all fd's the child should not see */
795 if (modem_fd >= 0) close(modem_fd);
796 close(proxy_mfd); /* close the master pty endpoint */
797 close(proxy_sfd); /* close the slave pty endpoint */
798 if (fifo_fd != -1) close(fifo_fd);
800 MONITORS *c = monitors;
807 /* make sure the stdin, stdout and stderr get directed to /dev/null */
808 fd = open("/dev/null", O_RDWR);
820 syslog(LOG_ERR, "could not exec program: errno=%d, buf=%s", errno, buf);
822 execl("/bin/sh", "sh", "-c", buf, (char *)0);
823 syslog(LOG_ERR, "could not exec /bin/sh: %m");
828 while (running_pid) {
831 return running_status;
834 void background_system(const char *buf)
843 if (debug&DEBUG_VERBOSE)
844 syslog(LOG_NOTICE, "running background pid=%d \"%s\"", pid, buf);
846 if (debug&DEBUG_VERBOSE)
847 syslog(LOG_DEBUG,"running '%s'",buf);
851 if (pid != 0) unblock_signals();
854 syslog(LOG_ERR, "failed to fork and run '%s': %m",buf);
859 /* change the signal actions back to the defaults, then unblock them. */
863 /* Leave the current location */
864 (void) setsid(); /* No controlling tty. */
865 (void) umask (S_IRWXG|S_IRWXO);
866 (void) chdir ("/"); /* no current directory. */
868 /* close all fd's the child should not see */
872 if (modem_fd >= 0) close(modem_fd);
873 close(proxy_mfd); /* close the master pty endpoint */
874 close(proxy_sfd); /* close the slave pty endpoint */
875 if (fifo_fd != -1) close(fifo_fd);
877 MONITORS *c = monitors;
884 /* make sure the stdin, stdout and stderr get directed to /dev/null */
885 fd = open("/dev/null", O_RDWR);
897 syslog(LOG_ERR, "could not exec background: errno=%d buf=%s", errno, buf);
899 execl("/bin/sh", "sh", "-c", buf, (char *)0);
900 syslog(LOG_ERR, "could not exec /bin/sh: %m");
907 void mon_write(int level, char *message,int len)
909 MONITORS *c = monitors, *p = 0, *cn;
912 if (c->level&level) {
913 if (write(c->fd,message,len) < 0) {
914 if (errno == EPIPE) {
915 syslog(LOG_INFO,"Monitor pipe %s closed.",c->name);
917 /* Write error. The reader probably got swapped out
918 * or something and the pipe flooded. We'll just "loose"
925 if (p) p->next = c->next;
926 else monitors = c->next;