main.c revision 36709
1139823Simp/*
244165Sjulian *			User Process PPP
344165Sjulian *
444165Sjulian *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
544165Sjulian *
644165Sjulian *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
744165Sjulian *
844165Sjulian * Redistribution and use in source and binary forms are permitted
944165Sjulian * provided that the above copyright notice and this paragraph are
1044165Sjulian * duplicated in all such forms and that any documentation,
1144165Sjulian * advertising materials, and other materials related to such
1244165Sjulian * distribution and use acknowledge that the software was developed
1344165Sjulian * by the Internet Initiative Japan, Inc.  The name of the
1444165Sjulian * IIJ may not be used to endorse or promote products derived
1544165Sjulian * from this software without specific prior written permission.
1644165Sjulian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1744165Sjulian * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1844165Sjulian * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1944165Sjulian *
2044165Sjulian * $Id: main.c,v 1.129 1998/05/29 18:33:09 brian Exp $
2144165Sjulian *
2244165Sjulian *	TODO:
2344165Sjulian */
2444165Sjulian
2544165Sjulian#include <sys/types.h>
2644165Sjulian#include <sys/socket.h>
2744165Sjulian#include <netinet/in.h>
2844165Sjulian#include <netinet/in_systm.h>
2944165Sjulian#include <netinet/ip.h>
3044165Sjulian#include <sys/un.h>
3144165Sjulian#include <net/if_tun.h>
3244165Sjulian
3350477Speter#include <errno.h>
3444165Sjulian#include <fcntl.h>
3544165Sjulian#include <paths.h>
3644165Sjulian#include <signal.h>
3744165Sjulian#include <stdio.h>
3844165Sjulian#include <string.h>
3944165Sjulian#include <sys/time.h>
4044165Sjulian#include <termios.h>
4144165Sjulian#include <unistd.h>
4244165Sjulian
4344165Sjulian#include "mbuf.h"
4474408Smdodd#include "log.h"
4574408Smdodd#include "defs.h"
46112285Smdodd#include "id.h"
4744165Sjulian#include "timer.h"
4844165Sjulian#include "fsm.h"
4944165Sjulian#include "lqr.h"
50112271Smdodd#include "hdlc.h"
51112271Smdodd#include "lcp.h"
5244165Sjulian#include "ccp.h"
53112271Smdodd#include "iplist.h"
5444165Sjulian#include "throughput.h"
5544165Sjulian#include "slcompress.h"
5644165Sjulian#include "ipcp.h"
5744165Sjulian#include "filter.h"
58184710Sbz#include "descriptor.h"
59112271Smdodd#include "link.h"
6044165Sjulian#include "mp.h"
6144165Sjulian#include "bundle.h"
62186119Sqingli#include "loadalias.h"
6344165Sjulian#include "auth.h"
64184710Sbz#include "systems.h"
65112271Smdodd#include "ip.h"
66112271Smdodd#include "sig.h"
67112271Smdodd#include "main.h"
6844165Sjulian#include "tun.h"
6944165Sjulian#include "server.h"
7074408Smdodd#include "prompt.h"
7144165Sjulian#include "chat.h"
7244165Sjulian#include "chap.h"
7344165Sjulian#include "datalink.h"
7444165Sjulian
7574408Smdodd#ifndef O_NONBLOCK
7674408Smdodd#ifdef O_NDELAY
7774408Smdodd#define	O_NONBLOCK O_NDELAY
7844165Sjulian#endif
7974408Smdodd#endif
8074408Smdodd
8174408Smdoddstatic void DoLoop(struct bundle *);
8274408Smdoddstatic void TerminalStop(int);
8374408Smdoddstatic const char *ex_desc(int);
84163606Srwatson
85163606Srwatsonstatic struct bundle *SignalBundle;
86126907Srwatsonstatic struct prompt *SignalPrompt;
87112277Smdodd
88112277Smdoddvoid
89112273SmdoddCleanup(int excode)
90112294Smdodd{
91112273Smdodd  SignalBundle->CleaningUp = 1;
92112276Smdodd  if (bundle_Phase(SignalBundle) != PHASE_DEAD)
9374408Smdodd    bundle_Close(SignalBundle, NULL, 1);
94112297Smdodd}
95112297Smdodd
96112297Smdoddvoid
9744165SjulianAbortProgram(int excode)
98152296Sru{
9944165Sjulian  server_Close(SignalBundle);
100112296Smdodd  log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode));
101111774Smdodd  bundle_Close(SignalBundle, NULL, 1);
10244165Sjulian  bundle_Destroy(SignalBundle);
103112296Smdodd  log_Close();
104112296Smdodd  exit(excode);
10544165Sjulian}
10658313Slile
10758313Slilestatic void
108112297SmdoddCloseConnection(int signo)
109112297Smdodd{
110112297Smdodd  /* NOTE, these are manual, we've done a setsid() */
111112297Smdodd  sig_signal(SIGINT, SIG_IGN);
112112297Smdodd  log_Printf(LogPHASE, "Caught signal %d, abort connection(s)\n", signo);
113112297Smdodd  bundle_Down(SignalBundle);
114112297Smdodd  sig_signal(SIGINT, CloseConnection);
115112297Smdodd}
11644165Sjulian
11758313Slilestatic void
11844165SjulianCloseSession(int signo)
11944165Sjulian{
12044165Sjulian  log_Printf(LogPHASE, "Signal %d, terminate.\n", signo);
121152315Sru  Cleanup(EX_TERM);
122152315Sru}
123112297Smdodd
124112272Smdoddstatic pid_t BGPid = 0;
125112272Smdodd
126112272Smdoddstatic void
127152296SruKillChild(int signo)
128112297Smdodd{
129112297Smdodd  log_Printf(LogPHASE, "Parent: Signal %d\n", signo);
130112297Smdodd  kill(BGPid, SIGINT);
131112297Smdodd}
132112297Smdodd
13344165Sjulianstatic void
13444165SjulianTerminalCont(int signo)
13574408Smdodd{
13674408Smdodd  signal(SIGCONT, SIG_DFL);
13774408Smdodd  prompt_Continue(SignalPrompt);
13874408Smdodd}
13974408Smdodd
14074408Smdoddstatic void
14174408SmdoddTerminalStop(int signo)
14274408Smdodd{
143112274Smdodd  prompt_Suspend(SignalPrompt);
14474408Smdodd  signal(SIGCONT, TerminalCont);
14574408Smdodd  raise(SIGSTOP);
146112274Smdodd}
14774408Smdodd
148112274Smdoddstatic void
149112274SmdoddBringDownServer(int signo)
15074408Smdodd{
15174408Smdodd  /* Drops all child prompts too ! */
15244165Sjulian  server_Close(SignalBundle);
15344165Sjulian}
15444165Sjulian
155112274Smdoddstatic const char *
156112274Smdoddex_desc(int ex)
157112274Smdodd{
15844165Sjulian  static char num[12];
159112274Smdodd  static const char *desc[] = {
160112274Smdodd    "normal", "start", "sock", "modem", "dial", "dead", "done",
161112274Smdodd    "reboot", "errdead", "hangup", "term", "nodial", "nologin"
162112274Smdodd  };
16344165Sjulian
16444165Sjulian  if (ex >= 0 && ex < sizeof desc / sizeof *desc)
16544165Sjulian    return desc[ex];
16644165Sjulian  snprintf(num, sizeof num, "%d", ex);
16744165Sjulian  return num;
16844165Sjulian}
16944165Sjulian
17044165Sjulianstatic void
17184931SfjoeUsage(void)
17244165Sjulian{
17374408Smdodd  fprintf(stderr,
17474408Smdodd	  "Usage: ppp [-auto | -background | -direct | -dedicated | -ddial ]"
17574408Smdodd#ifndef NOALIAS
17674408Smdodd          " [ -alias ]"
17774408Smdodd#endif
178120048Smdodd          " [system]\n");
179120048Smdodd  exit(EX_START);
18074408Smdodd}
181120048Smdodd
18274408Smdoddstatic char *
183120048SmdoddProcessArgs(int argc, char **argv, int *mode)
184120048Smdodd{
185152315Sru  int optc, labelrequired, newmode;
186120048Smdodd  char *cp;
187120048Smdodd
188152315Sru  optc = labelrequired = 0;
189120048Smdodd  *mode = PHYS_INTERACTIVE;
190120048Smdodd  while (argc > 0 && **argv == '-') {
191120048Smdodd    cp = *argv + 1;
192120048Smdodd    newmode = Nam2mode(cp);
193120048Smdodd    switch (newmode) {
194120048Smdodd      case PHYS_NONE:
195120048Smdodd        if (strcmp(cp, "alias") == 0) {
196120048Smdodd#ifndef NOALIAS
19774408Smdodd          if (alias_Load() != 0)
19844165Sjulian#endif
19944165Sjulian	    log_Printf(LogWARN, "Cannot load alias library\n");
20044165Sjulian          optc--;			/* this option isn't exclusive */
20144165Sjulian        } else
20244165Sjulian          Usage();
20344165Sjulian        break;
204120047Smdodd
20544165Sjulian      case PHYS_ALL:
20644165Sjulian        Usage();
20744165Sjulian        break;
208152315Sru
20944165Sjulian      case PHYS_AUTO:
21044165Sjulian      case PHYS_BACKGROUND:
21144165Sjulian      case PHYS_DDIAL:
21244165Sjulian        labelrequired = 1;
21344165Sjulian        /* fall through */
21444165Sjulian
21544165Sjulian      default:
21644165Sjulian        *mode = newmode;
21758313Slile    }
21844165Sjulian    optc++;
21944165Sjulian    argv++;
22044165Sjulian    argc--;
22144165Sjulian  }
22244165Sjulian
223112274Smdodd  if (argc > 1) {
224112274Smdodd    fprintf(stderr, "You may specify only one system label.\n");
225112274Smdodd    exit(EX_START);
22644165Sjulian  }
227112274Smdodd
22844165Sjulian  if (optc > 1) {
22944165Sjulian    fprintf(stderr, "You may specify only one mode.\n");
23044165Sjulian    exit(EX_START);
23144165Sjulian  }
23244165Sjulian
23344165Sjulian  if (labelrequired && argc != 1) {
23444165Sjulian    fprintf(stderr, "Destination system must be specified in"
23574408Smdodd            " auto, background or ddial mode.\n");
23674408Smdodd    exit(EX_START);
23774408Smdodd  }
23874408Smdodd
23974408Smdodd  return argc == 1 ? *argv : NULL;	/* Don't SetLabel yet ! */
24044165Sjulian}
24174408Smdodd
24287914Sjlemonint
24387914Sjlemonmain(int argc, char **argv)
24474408Smdodd{
24544627Sjulian  char *name, *label;
24674408Smdodd  int nfds, mode;
247186119Sqingli  struct bundle *bundle;
24844165Sjulian  struct prompt *prompt;
249112285Smdodd
250172930Srwatson  nfds = getdtablesize();
251112285Smdodd  if (nfds >= FD_SETSIZE)
252112285Smdodd    /*
253112285Smdodd     * If we've got loads of file descriptors, make sure they're all
254112285Smdodd     * closed.  If they aren't, we may end up with a seg fault when our
255112308Smdodd     * `fd_set's get too big when select()ing !
256112308Smdodd     */
257148887Srwatson    while (--nfds > 2)
258148887Srwatson      close(nfds);
25944165Sjulian
26074408Smdodd  name = strrchr(argv[0], '/');
26174408Smdodd  log_Open(name ? name + 1 : argv[0]);
262128636Sluigi
263128636Sluigi  label = ProcessArgs(argc - 1, argv + 1, &mode);
26444627Sjulian
265186119Sqingli#ifdef __FreeBSD__
266102291Sarchie  /*
26796184Skbyanc   * A FreeBSD hack to dodge a bug in the tty driver that drops output
26844627Sjulian   * occasionally.... I must find the real reason some time.  To display
26944627Sjulian   * the dodgy behaviour, comment out this bit, make yourself a large
27058313Slile   * routing table and then run ppp in interactive mode.  The `show route'
27158313Slile   * command will drop chunks of data !!!
272152315Sru   */
273112278Smdodd  if (mode == PHYS_INTERACTIVE) {
27444627Sjulian    close(STDIN_FILENO);
27558313Slile    if (open(_PATH_TTY, O_RDONLY) != STDIN_FILENO) {
27644627Sjulian      fprintf(stderr, "Cannot open %s for input !\n", _PATH_TTY);
27796184Skbyanc      return 2;
27874408Smdodd    }
27996184Skbyanc  }
28096184Skbyanc#endif
28144627Sjulian
28244627Sjulian  /* Allow output for the moment (except in direct mode) */
28344627Sjulian  if (mode == PHYS_DIRECT)
28444165Sjulian    prompt = NULL;
28544165Sjulian  else {
28644165Sjulian    SignalPrompt = prompt = prompt_Create(NULL, NULL, PROMPT_STD);
287186119Sqingli    prompt_Printf(prompt, "Working in %s mode\n", mode2Nam(mode));
288128636Sluigi  }
289128636Sluigi
29074408Smdodd  ID0init();
29174408Smdodd  if (ID0realuid() != 0) {
292126951Smdodd    char conf[200], *ptr;
293126951Smdodd
294126951Smdodd    snprintf(conf, sizeof conf, "%s/%s", _PATH_PPP, CONFFILE);
295126951Smdodd    do {
296126951Smdodd      if (!access(conf, W_OK)) {
297126951Smdodd        log_Printf(LogALERT, "ppp: Access violation: Please protect %s\n", conf);
298126951Smdodd        return -1;
299126951Smdodd      }
300126951Smdodd      ptr = conf + strlen(conf)-2;
301126951Smdodd      while (ptr > conf && *ptr != '/')
302126951Smdodd        *ptr-- = '\0';
303126951Smdodd    } while (ptr >= conf);
304126951Smdodd  }
305126951Smdodd
306126951Smdodd  if (!system_IsValid(label, prompt, mode)) {
307126951Smdodd    fprintf(stderr, "You may not use ppp in this mode with this label\n");
308126951Smdodd    if (mode == PHYS_DIRECT) {
309126951Smdodd      const char *l;
310126951Smdodd      l = label ? label : "default";
311126951Smdodd      log_Printf(LogWARN, "Label %s rejected -direct connection\n", l);
312126951Smdodd    }
313126951Smdodd    log_Close();
314126951Smdodd    return 1;
315126951Smdodd  }
316126951Smdodd
317126951Smdodd  if ((bundle = bundle_Create(TUN_PREFIX, mode, (const char **)argv)) == NULL) {
318126951Smdodd    log_Printf(LogWARN, "bundle_Create: %s\n", strerror(errno));
31974408Smdodd    return EX_START;
32074408Smdodd  }
32174408Smdodd  if (prompt) {
322186217Sqingli    prompt->bundle = bundle;	/* couldn't do it earlier */
323128636Sluigi    prompt_Printf(prompt, "Using interface: %s\n", bundle->ifp.Name);
324128636Sluigi  }
32574408Smdodd  SignalBundle = bundle;
32674408Smdodd
32774408Smdodd  if (system_Select(bundle, "default", CONFFILE, prompt) < 0)
32874408Smdodd    prompt_Printf(prompt, "Warning: No default entry found in config file.\n");
32974408Smdodd
33074408Smdodd  sig_signal(SIGHUP, CloseSession);
33174408Smdodd  sig_signal(SIGTERM, CloseSession);
33274408Smdodd  sig_signal(SIGINT, CloseConnection);
33374408Smdodd  sig_signal(SIGQUIT, CloseSession);
334112278Smdodd  sig_signal(SIGALRM, SIG_IGN);
33574408Smdodd  signal(SIGPIPE, SIG_IGN);
336177599Sru
33774408Smdodd  if (mode == PHYS_INTERACTIVE)
33874408Smdodd    sig_signal(SIGTSTP, TerminalStop);
33974408Smdodd
34074408Smdodd  sig_signal(SIGUSR2, BringDownServer);
34174408Smdodd
34274408Smdodd  if (label) {
34374408Smdodd    /*
34474408Smdodd     * Set label both before and after system_Select !
34574408Smdodd     * This way, "set enddisc label" works during system_Select, and we
34674408Smdodd     * also end up with the correct label if we have embedded load
34744165Sjulian     * commands.
34874408Smdodd     */
34974408Smdodd    bundle_SetLabel(bundle, label);
35044627Sjulian    if (system_Select(bundle, label, CONFFILE, prompt) < 0) {
35144627Sjulian      prompt_Printf(prompt, "Destination system (%s) not found.\n", label);
35244627Sjulian      AbortProgram(EX_START);
35344627Sjulian    }
35444627Sjulian    bundle_SetLabel(bundle, label);
35544627Sjulian    if (mode == PHYS_AUTO &&
356108533Sschweikh	bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) {
35744627Sjulian      prompt_Printf(prompt, "You must \"set ifaddr\" with a peer address "
35844165Sjulian                    "in label %s for auto mode.\n", label);
35944627Sjulian      AbortProgram(EX_START);
36044627Sjulian    }
36144627Sjulian  }
36274408Smdodd
363112278Smdodd  if (mode != PHYS_INTERACTIVE) {
36474408Smdodd    if (mode != PHYS_DIRECT) {
365112280Smdodd      int bgpipe[2];
36644627Sjulian      pid_t bgpid;
36744165Sjulian
36874408Smdodd      if (mode == PHYS_BACKGROUND && pipe(bgpipe)) {
36944165Sjulian        log_Printf(LogERROR, "pipe: %s\n", strerror(errno));
370105598Sbrooks	AbortProgram(EX_SOCK);
37144165Sjulian      }
37274408Smdodd
37344165Sjulian      bgpid = fork();
37444165Sjulian      if (bgpid == -1) {
375112274Smdodd	log_Printf(LogERROR, "fork: %s\n", strerror(errno));
376112274Smdodd	AbortProgram(EX_SOCK);
377112274Smdodd      }
37874408Smdodd
37974408Smdodd      if (bgpid) {
380111790Smdodd	char c = EX_NORMAL;
38174408Smdodd
38274408Smdodd	if (mode == PHYS_BACKGROUND) {
38374408Smdodd	  close(bgpipe[1]);
384112281Smdodd	  BGPid = bgpid;
38574408Smdodd          /* If we get a signal, kill the child */
386112268Smdodd          signal(SIGHUP, KillChild);
387112268Smdodd          signal(SIGTERM, KillChild);
388112268Smdodd          signal(SIGINT, KillChild);
389112274Smdodd          signal(SIGQUIT, KillChild);
39074408Smdodd
39174408Smdodd	  /* Wait for our child to close its pipe before we exit */
39244165Sjulian	  if (read(bgpipe[0], &c, 1) != 1) {
39344165Sjulian	    prompt_Printf(prompt, "Child exit, no status.\n");
39444165Sjulian	    log_Printf(LogPHASE, "Parent: Child exit, no status.\n");
39544165Sjulian	  } else if (c == EX_NORMAL) {
396111119Simp	    prompt_Printf(prompt, "PPP enabled.\n");
39744165Sjulian	    log_Printf(LogPHASE, "Parent: PPP enabled.\n");
39844165Sjulian	  } else {
399112274Smdodd	    prompt_Printf(prompt, "Child failed (%s).\n", ex_desc((int) c));
400112291Smdodd	    log_Printf(LogPHASE, "Parent: Child failed (%s).\n",
40144627Sjulian		      ex_desc((int) c));
40244627Sjulian	  }
40344627Sjulian	  close(bgpipe[0]);
40444627Sjulian	}
40544165Sjulian	return c;
40644165Sjulian      } else if (mode == PHYS_BACKGROUND) {
40744165Sjulian	close(bgpipe[0]);
40844165Sjulian        bundle->notify.fd = bgpipe[1];
40944165Sjulian      }
41044165Sjulian
41144165Sjulian      bundle_LockTun(bundle);	/* we have a new pid */
41244165Sjulian
41344165Sjulian      /* -auto, -dedicated, -ddial & -background */
41474408Smdodd      prompt_Destroy(prompt, 0);
41544165Sjulian      close(STDOUT_FILENO);
41674408Smdodd      close(STDERR_FILENO);
41774408Smdodd      close(STDIN_FILENO);
418112279Smdodd      setsid();
41974408Smdodd    } else {
420112279Smdodd      /* -direct: STDIN_FILENO gets used by modem_Open */
42174408Smdodd      prompt_TtyInit(NULL);
422112279Smdodd      close(STDOUT_FILENO);
423112279Smdodd      close(STDERR_FILENO);
424112279Smdodd    }
425112279Smdodd  } else {
42644165Sjulian    /* Interactive mode */
42744165Sjulian    close(STDERR_FILENO);
428130549Smlaier    prompt_TtyInit(prompt);
429130549Smlaier    prompt_TtyCommandMode(prompt);
43069152Sjlemon    prompt_Required(prompt);
431130549Smlaier  }
43244165Sjulian
43344165Sjulian  log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode));
43444165Sjulian  DoLoop(bundle);
43544165Sjulian  AbortProgram(EX_NORMAL);
436112296Smdodd
43744165Sjulian  return EX_NORMAL;
43844165Sjulian}
43944165Sjulian
44044165Sjulianstatic void
44144165SjulianDoLoop(struct bundle *bundle)
44244165Sjulian{
44344165Sjulian  fd_set rfds, wfds, efds;
44444165Sjulian  int i, nfds;
44544165Sjulian
446112299Smdodd  do {
44774408Smdodd    nfds = 0;
44874408Smdodd    FD_ZERO(&rfds);
44944165Sjulian    FD_ZERO(&wfds);
450112299Smdodd    FD_ZERO(&efds);
451112299Smdodd
452111888Sjlemon    /* All our datalinks, the tun device and the MP socket */
453112299Smdodd    descriptor_UpdateSet(&bundle->desc, &rfds, &wfds, &efds, &nfds);
45444165Sjulian
455112308Smdodd    /* All our prompts and the diagnostic socket */
456112308Smdodd    descriptor_UpdateSet(&server.desc, &rfds, NULL, NULL, &nfds);
457112308Smdodd
458112308Smdodd    if (bundle_IsDead(bundle))
459112308Smdodd      /* Don't select - we'll be here forever */
460112308Smdodd      break;
461112308Smdodd
462112308Smdodd    i = select(nfds, &rfds, &wfds, &efds, NULL);
463112308Smdodd
464112308Smdodd    if (i < 0 && errno != EINTR) {
465112308Smdodd      log_Printf(LogERROR, "DoLoop: select(): %s\n", strerror(errno));
466112308Smdodd      if (log_IsKept(LogTIMER)) {
467112308Smdodd        struct timeval t;
468112308Smdodd
469112308Smdodd        for (i = 0; i <= nfds; i++) {
470112308Smdodd          if (FD_ISSET(i, &rfds)) {
471112308Smdodd            log_Printf(LogTIMER, "Read set contains %d\n", i);
472112299Smdodd            FD_CLR(i, &rfds);
473112299Smdodd            t.tv_sec = t.tv_usec = 0;
474112299Smdodd            if (select(nfds, &rfds, &wfds, &efds, &t) != -1) {
475112299Smdodd              log_Printf(LogTIMER, "The culprit !\n");
476112299Smdodd              break;
477112299Smdodd            }
478112299Smdodd          }
479112299Smdodd          if (FD_ISSET(i, &wfds)) {
480112286Smdodd            log_Printf(LogTIMER, "Write set contains %d\n", i);
481112286Smdodd            FD_CLR(i, &wfds);
482112286Smdodd            t.tv_sec = t.tv_usec = 0;
483148887Srwatson            if (select(nfds, &rfds, &wfds, &efds, &t) != -1) {
484148887Srwatson              log_Printf(LogTIMER, "The culprit !\n");
485112286Smdodd              break;
48644165Sjulian            }
487112308Smdodd          }
488112308Smdodd          if (FD_ISSET(i, &efds)) {
489112308Smdodd            log_Printf(LogTIMER, "Error set contains %d\n", i);
490112308Smdodd            FD_CLR(i, &efds);
491112308Smdodd            t.tv_sec = t.tv_usec = 0;
492112308Smdodd            if (select(nfds, &rfds, &wfds, &efds, &t) != -1) {
493112308Smdodd              log_Printf(LogTIMER, "The culprit !\n");
494112308Smdodd              break;
495112308Smdodd            }
496112308Smdodd          }
497112308Smdodd        }
498112308Smdodd      }
499112308Smdodd      break;
500112285Smdodd    }
501172930Srwatson
502112285Smdodd    sig_Handle();
503112285Smdodd
504112286Smdodd    if (i <= 0)
505112286Smdodd      continue;
506112286Smdodd
507112299Smdodd    for (i = 0; i <= nfds; i++)
50874408Smdodd      if (FD_ISSET(i, &efds)) {
50958313Slile        log_Printf(LogALERT, "Exception detected on descriptor %d\n", i);
510112280Smdodd        break;
511112286Smdodd      }
512112286Smdodd
513112286Smdodd    if (i <= nfds)
514112286Smdodd      break;
515112286Smdodd
516152315Sru    if (descriptor_IsSet(&server.desc, &rfds))
517112286Smdodd      descriptor_Read(&server.desc, bundle, &rfds);
518112286Smdodd
519112286Smdodd    if (descriptor_IsSet(&bundle->desc, &wfds))
520112286Smdodd      descriptor_Write(&bundle->desc, bundle, &wfds);
521112280Smdodd
522112280Smdodd    if (descriptor_IsSet(&bundle->desc, &rfds))
52344165Sjulian      descriptor_Read(&bundle->desc, bundle, &rfds);
524126907Srwatson
525126907Srwatson  } while (bundle_CleanDatalinks(bundle), !bundle_IsDead(bundle));
52644165Sjulian
52744165Sjulian  log_Printf(LogDEBUG, "DoLoop done.\n");
52844165Sjulian}
52974408Smdodd