/* * i4b_Timeout() watches the DCD signal and mentions it if it's status * changes. */ static void i4b_Timeout(void *data) { struct physical *p = data; struct i4bdevice *dev = device2i4b(p->handler); int ombits, change; timer_Stop(&dev->Timer); dev->Timer.load = SECTICKS; /* Once a second please */ timer_Start(&dev->Timer); ombits = dev->mbits; if (p->fd >= 0) { if (ioctl(p->fd, TIOCMGET, &dev->mbits) < 0) { log_Printf(LogPHASE, "%s: ioctl error (%s)!\n", p->link.name, strerror(errno)); datalink_Down(p->dl, CLOSE_NORMAL); timer_Stop(&dev->Timer); return; } } else dev->mbits = 0; if (ombits == -1) { /* First time looking for carrier */ if (Online(dev)) log_Printf(LogPHASE, "%s: %s: CD detected\n", p->link.name, p->name.full); else if (++dev->carrier_seconds >= dev->dev.cd.delay) { log_Printf(LogPHASE, "%s: %s: No carrier" " (increase ``set cd'' from %d ?)\n", p->link.name, p->name.full, dev->dev.cd.delay); timer_Stop(&dev->Timer); /* i4b_AwaitCarrier() will notice */ } else { /* Keep waiting */ log_Printf(LogDEBUG, "%s: %s: Still no carrier (%d/%d)\n", p->link.name, p->name.full, dev->carrier_seconds, dev->dev.cd.delay); dev->mbits = -1; } } else { change = ombits ^ dev->mbits; if (change & TIOCM_CD) { if (dev->mbits & TIOCM_CD) log_Printf(LogDEBUG, "%s: offline -> online\n", p->link.name); else { log_Printf(LogDEBUG, "%s: online -> offline\n", p->link.name); log_Printf(LogPHASE, "%s: Carrier lost\n", p->link.name); datalink_Down(p->dl, CLOSE_NORMAL); timer_Stop(&dev->Timer); } } else log_Printf(LogDEBUG, "%s: Still %sline\n", p->link.name, Online(dev) ? "on" : "off"); } }
static int physical_DescriptorWrite(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) { struct physical *p = descriptor2physical(d); int nw, result = 0; if (p->out == NULL) p->out = link_Dequeue(&p->link); if (p->out) { nw = physical_Write(p, MBUF_CTOP(p->out), p->out->m_len); log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%lu) to %d\n", p->link.name, nw, (unsigned long)p->out->m_len, p->fd); if (nw > 0) { p->out->m_len -= nw; p->out->m_offset += nw; if (p->out->m_len == 0) p->out = m_free(p->out); result = 1; } else if (nw < 0) { if (errno == EAGAIN) result = 1; else if (errno != ENOBUFS) { log_Printf(LogPHASE, "%s: write (%d): %s\n", p->link.name, p->fd, strerror(errno)); datalink_Down(p->dl, CLOSE_NORMAL); } } /* else we shouldn't really have been called ! select() is broken ! */ } return result; }
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 SendLqrReport(void *v) { struct lcp *lcp = (struct lcp *)v; struct physical *p = link2physical(lcp->fsm.link); timer_Stop(&p->hdlc.lqm.timer); if (p->hdlc.lqm.method & LQM_LQR) { if (p->hdlc.lqm.lqr.resent > 5) { /* XXX: Should implement LQM strategy */ log_Printf(LogPHASE, "%s: ** Too many LQR packets lost **\n", lcp->fsm.link->name); log_Printf(LogLQM, "%s: Too many LQR packets lost\n", lcp->fsm.link->name); p->hdlc.lqm.method = 0; datalink_Down(p->dl, CLOSE_NORMAL); } else { SendLqrData(lcp); p->hdlc.lqm.lqr.resent++; } } else if (p->hdlc.lqm.method & LQM_ECHO) { if ((p->hdlc.lqm.echo.seq_sent > 5 && p->hdlc.lqm.echo.seq_sent - 5 > p->hdlc.lqm.echo.seq_recv) || (p->hdlc.lqm.echo.seq_sent <= 5 && p->hdlc.lqm.echo.seq_sent > p->hdlc.lqm.echo.seq_recv + 5)) { log_Printf(LogPHASE, "%s: ** Too many LCP ECHO packets lost **\n", lcp->fsm.link->name); log_Printf(LogLQM, "%s: Too many LCP ECHO packets lost\n", lcp->fsm.link->name); p->hdlc.lqm.method = 0; datalink_Down(p->dl, CLOSE_NORMAL); } else SendEchoReq(lcp); } if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load) timer_Start(&p->hdlc.lqm.timer); }
static void ether_DescriptorRead(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) { struct physical *p = descriptor2physical(d); struct etherdevice *dev = device2ether(p->handler); if (dev->cs >= 0 && FD_ISSET(dev->cs, fdset)) { ether_MessageIn(dev); if (dev->connected == CARRIER_LOST) { log_Printf(LogPHASE, "%s: Device disconnected\n", p->link.name); datalink_Down(p->dl, CLOSE_NORMAL); return; } } if (physical_IsSet(d, fdset)) physical_DescriptorRead(d, bundle, fdset); }