void physical_SetupStack(struct physical *p, const char *who, int how) { link_EmptyStack(&p->link); if (how == PHYSICAL_FORCE_SYNC || how == PHYSICAL_FORCE_SYNCNOACF || (how == PHYSICAL_NOFORCE && physical_IsSync(p))) link_Stack(&p->link, &synclayer); else { link_Stack(&p->link, &asynclayer); link_Stack(&p->link, &hdlclayer); } if (how != PHYSICAL_FORCE_SYNCNOACF) link_Stack(&p->link, &acflayer); link_Stack(&p->link, &protolayer); link_Stack(&p->link, &lqrlayer); link_Stack(&p->link, &ccplayer); link_Stack(&p->link, &vjlayer); link_Stack(&p->link, &tcpmsslayer); #ifndef NONAT link_Stack(&p->link, &natlayer); #endif if (how == PHYSICAL_FORCE_ASYNC && physical_IsSync(p)) { log_Printf(LogWARN, "Sync device setting ignored for ``%s'' device\n", who); p->cfg.speed = MODEM_SPEED; } else if (how == PHYSICAL_FORCE_SYNC && !physical_IsSync(p)) { log_Printf(LogWARN, "Async device setting ignored for ``%s'' device\n", who); physical_SetSync(p); } }
void physical_DescriptorRead(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) { struct physical *p = descriptor2physical(d); u_char *rbuff; int n, found; rbuff = p->input.buf + p->input.sz; /* something to read */ n = physical_Read(p, rbuff, sizeof p->input.buf - p->input.sz); log_Printf(LogDEBUG, "%s: DescriptorRead: read %d/%d from %d\n", p->link.name, n, (int)(sizeof p->input.buf - p->input.sz), p->fd); if (n <= 0) { if (n < 0) log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd, strerror(errno)); else log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n", p->link.name, p->fd); datalink_Down(p->dl, CLOSE_NORMAL); return; } rbuff -= p->input.sz; n += p->input.sz; if (p->link.lcp.fsm.state <= ST_CLOSED) { if (p->type != PHYS_DEDICATED) { found = hdlc_Detect((u_char const **)&rbuff, n, physical_IsSync(p)); if (rbuff != p->input.buf) log_WritePrompts(p->dl, "%.*s", (int)(rbuff - p->input.buf), p->input.buf); p->input.sz = n - (rbuff - p->input.buf); if (found) { /* LCP packet is detected. Turn ourselves into packet mode */ log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n", p->link.name); log_SetTtyCommandMode(p->dl); datalink_Up(p->dl, 0, 1); link_PullPacket(&p->link, rbuff, p->input.sz, bundle); p->input.sz = 0; } else bcopy(rbuff, p->input.buf, p->input.sz); } else /* In -dedicated mode, we just discard input until LCP is started */ p->input.sz = 0; } else if (n > 0) link_PullPacket(&p->link, rbuff, n, bundle); }
static void ipv6cp_SendConfigReq(struct fsm *fp) { /* Send config REQ please */ struct physical *p = link2physical(fp->link); struct ipv6cp *ipv6cp = fsm2ipv6cp(fp); u_char buff[IPV6CP_IFIDLEN+2]; struct fsm_opt *o; o = (struct fsm_opt *)buff; if ((p && !physical_IsSync(p)) || !REJECTED(ipv6cp, TY_TOKEN)) { memcpy(o->data, ipv6cp->my_ifid, IPV6CP_IFIDLEN); INC_FSM_OPT(TY_TOKEN, IPV6CP_IFIDLEN + 2, o); } fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, MB_IPV6CPOUT); }
int physical_ShowStatus(struct cmdargs const *arg) { struct physical *p = arg->cx->physical; struct cd *cd; const char *dev; int n, slot; prompt_Printf(arg->prompt, "Name: %s\n", p->link.name); prompt_Printf(arg->prompt, " State: "); if (p->fd < 0) prompt_Printf(arg->prompt, "closed\n"); else { slot = physical_Slot(p); if (p->handler && p->handler->openinfo) { if (slot == -1) prompt_Printf(arg->prompt, "open (%s)\n", (*p->handler->openinfo)(p)); else prompt_Printf(arg->prompt, "open (%s, port %d)\n", (*p->handler->openinfo)(p), slot); } else if (slot == -1) prompt_Printf(arg->prompt, "open\n"); else prompt_Printf(arg->prompt, "open (port %d)\n", slot); } prompt_Printf(arg->prompt, " Device: %s", *p->name.full ? p->name.full : p->type == PHYS_DIRECT ? "unknown" : "N/A"); if (p->session_owner != (pid_t)-1) prompt_Printf(arg->prompt, " (session owner: %ld)", (long)p->session_owner); prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(p->type)); prompt_Printf(arg->prompt, " Connect Count: %d\n", p->connect_count); #ifdef TIOCOUTQ if (p->fd >= 0 && ioctl(p->fd, TIOCOUTQ, &n) >= 0) prompt_Printf(arg->prompt, " Physical outq: %d\n", n); #endif prompt_Printf(arg->prompt, " Queued Packets: %lu\n", (u_long)link_QueueLen(&p->link)); prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen); prompt_Printf(arg->prompt, "\nDefaults:\n"); prompt_Printf(arg->prompt, " Device List: "); dev = p->cfg.devlist; for (n = 0; n < p->cfg.ndev; n++) { if (n) prompt_Printf(arg->prompt, ", "); prompt_Printf(arg->prompt, "\"%s\"", dev); dev += strlen(dev) + 1; } prompt_Printf(arg->prompt, "\n Characteristics: "); if (physical_IsSync(arg->cx->physical)) prompt_Printf(arg->prompt, "sync"); else prompt_Printf(arg->prompt, "%dbps", p->cfg.speed); switch (p->cfg.parity & CSIZE) { case CS7: prompt_Printf(arg->prompt, ", cs7"); break; case CS8: prompt_Printf(arg->prompt, ", cs8"); break; } if (p->cfg.parity & PARENB) { if (p->cfg.parity & PARODD) prompt_Printf(arg->prompt, ", odd parity"); else prompt_Printf(arg->prompt, ", even parity"); } else prompt_Printf(arg->prompt, ", no parity"); prompt_Printf(arg->prompt, ", CTS/RTS %s\n", (p->cfg.rts_cts ? "on" : "off")); prompt_Printf(arg->prompt, " CD check delay: "); cd = p->handler ? &p->handler->cd : &p->cfg.cd; if (cd->necessity == CD_NOTREQUIRED) prompt_Printf(arg->prompt, "no cd"); else if (p->cfg.cd.necessity == CD_DEFAULT) { prompt_Printf(arg->prompt, "device specific"); } else { prompt_Printf(arg->prompt, "%d second%s", p->cfg.cd.delay, p->cfg.cd.delay == 1 ? "" : "s"); if (p->cfg.cd.necessity == CD_REQUIRED) prompt_Printf(arg->prompt, " (required!)"); } prompt_Printf(arg->prompt, "\n\n"); throughput_disp(&p->link.stats.total, arg->prompt); return 0; }
struct device * exec_Create(struct physical *p) { struct execdevice *dev; dev = NULL; if (p->fd < 0) { if (*p->name.full == '!') { int fids[2], type; if ((dev = malloc(sizeof *dev)) == NULL) { log_Printf(LogWARN, "%s: Cannot allocate an exec device: %s\n", p->link.name, strerror(errno)); return NULL; } dev->fd_out = -1; p->fd--; /* We own the device but maybe can't use it - change fd */ type = physical_IsSync(p) ? SOCK_DGRAM : SOCK_STREAM; if (socketpair(AF_UNIX, type, PF_UNSPEC, fids) < 0) { log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n", strerror(errno)); free(dev); dev = NULL; } else { static int child_status; /* This variable is abused ! */ int stat, argc, i, ret, wret, pidpipe[2]; pid_t pid, realpid; char *argv[MAXARGS]; stat = fcntl(fids[0], F_GETFL, 0); if (stat > 0) { stat |= O_NONBLOCK; fcntl(fids[0], F_SETFL, stat); } realpid = getpid(); if (pipe(pidpipe) == -1) { log_Printf(LogPHASE, "Unable to pipe for line exec: %s\n", strerror(errno)); close(fids[1]); close(fids[0]); free(dev); dev = NULL; } else switch ((pid = fork())) { case -1: log_Printf(LogPHASE, "Unable to fork for line exec: %s\n", strerror(errno)); close(pidpipe[0]); close(pidpipe[1]); close(fids[1]); close(fids[0]); break; case 0: close(pidpipe[0]); close(fids[0]); timer_TermService(); #ifndef NOSUID setuid(ID0realuid()); #endif child_status = 0; switch ((pid = vfork())) { case 0: close(pidpipe[1]); break; case -1: ret = errno; log_Printf(LogPHASE, "Unable to vfork to drop parent: %s\n", strerror(errno)); close(pidpipe[1]); _exit(ret); default: write(pidpipe[1], &pid, sizeof pid); close(pidpipe[1]); _exit(child_status); /* The error from exec() ! */ } log_Printf(LogDEBUG, "Exec'ing ``%s''\n", p->name.base); if ((argc = MakeArgs(p->name.base, argv, VECSIZE(argv), PARSE_REDUCE|PARSE_NOHASH)) < 0) { log_Printf(LogWARN, "Syntax error in exec command\n"); _exit(ESRCH); } command_Expand(argv, argc, (char const *const *)argv, p->dl->bundle, 0, realpid); dup2(fids[1], STDIN_FILENO); dup2(fids[1], STDOUT_FILENO); dup2(fids[1], STDERR_FILENO); for (i = getdtablesize(); i > STDERR_FILENO; i--) fcntl(i, F_SETFD, 1); execvp(*argv, argv); child_status = errno; /* Only works for vfork() */ printf("execvp failed: %s: %s\r\n", *argv, strerror(child_status)); _exit(child_status); break; default: close(pidpipe[1]); close(fids[1]); if (read(pidpipe[0], &p->session_owner, sizeof p->session_owner) != sizeof p->session_owner) p->session_owner = (pid_t)-1; close(pidpipe[0]); while ((wret = waitpid(pid, &stat, 0)) == -1 && errno == EINTR) ; if (wret == -1) { log_Printf(LogWARN, "Waiting for child process: %s\n", strerror(errno)); close(fids[0]); p->session_owner = (pid_t)-1; break; } else if (WIFSIGNALED(stat)) { log_Printf(LogWARN, "Child process received sig %d !\n", WTERMSIG(stat)); close(fids[0]); p->session_owner = (pid_t)-1; break; } else if (WIFSTOPPED(stat)) { log_Printf(LogWARN, "Child process received stop sig %d !\n", WSTOPSIG(stat)); /* I guess that's ok.... */ } else if ((ret = WEXITSTATUS(stat))) { log_Printf(LogWARN, "Cannot exec \"%s\": %s\n", p->name.base, strerror(ret)); close(fids[0]); p->session_owner = (pid_t)-1; break; } p->fd = fids[0]; log_Printf(LogDEBUG, "Using descriptor %d for child\n", p->fd); } } } } else { struct stat st; if (fstat(p->fd, &st) != -1 && (st.st_mode & S_IFIFO)) { if ((dev = malloc(sizeof *dev)) == NULL) log_Printf(LogWARN, "%s: Cannot allocate an exec device: %s\n", p->link.name, strerror(errno)); else if (p->fd == STDIN_FILENO) { log_Printf(LogPHASE, "%s: Using stdin/stdout to communicate with " "parent (pipe mode)\n", p->link.name); dev->fd_out = dup(STDOUT_FILENO); /* Hook things up so that we monitor dev->fd_out */ p->desc.UpdateSet = exec_UpdateSet; p->desc.IsSet = exec_IsSet; } else dev->fd_out = -1; } } if (dev) { memcpy(&dev->dev, &baseexecdevice, sizeof dev->dev); physical_SetupStack(p, dev->dev.name, PHYSICAL_NOFORCE); if (p->cfg.cd.necessity != CD_DEFAULT) log_Printf(LogWARN, "Carrier settings ignored\n"); return &dev->dev; } return NULL; }