/* * Deallocate a ppp unit. Must be called at splsoftnet or higher. */ void pppdealloc(struct ppp_softc *sc) { struct mbuf *m; if_down(&sc->sc_if); sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); getmicrotime(&sc->sc_if.if_lastchange); sc->sc_devp = NULL; sc->sc_xfer = NULL; for (;;) { IF_DEQUEUE(&sc->sc_rawq, m); if (m == NULL) break; m_freem(m); } for (;;) { IF_DEQUEUE(&sc->sc_inq, m); if (m == NULL) break; m_freem(m); } for (;;) { IF_DEQUEUE(&sc->sc_fastq, m); if (m == NULL) break; m_freem(m); } while ((m = sc->sc_npqueue) != NULL) { sc->sc_npqueue = m->m_nextpkt; m_freem(m); } #ifdef PPP_COMPRESS ppp_ccp_closed(sc); sc->sc_xc_state = NULL; sc->sc_rc_state = NULL; #endif /* PPP_COMPRESS */ #ifdef PPP_FILTER if (sc->sc_pass_filt.bf_insns != NULL) { kfree(sc->sc_pass_filt.bf_insns, M_DEVBUF); sc->sc_pass_filt.bf_insns = NULL; sc->sc_pass_filt.bf_len = 0; } if (sc->sc_active_filt.bf_insns != NULL) { kfree(sc->sc_active_filt.bf_insns, M_DEVBUF); sc->sc_active_filt.bf_insns = NULL; sc->sc_active_filt.bf_len = 0; } #endif /* PPP_FILTER */ #ifdef VJC if (sc->sc_comp != NULL) { kfree(sc->sc_comp, M_DEVBUF); sc->sc_comp = NULL; } #endif }
/* * Deallocate a ppp unit. Must be called at splsoftnet or higher. */ void pppdealloc(struct ppp_softc *sc) { struct ppp_pkt *pkt; struct mbuf *m; splsoftassert(IPL_SOFTNET); if_down(&sc->sc_if); sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING); sc->sc_devp = NULL; sc->sc_xfer = 0; while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL) ppp_pkt_free(pkt); while ((m = mq_dequeue(&sc->sc_inq)) != NULL) m_freem(m); for (;;) { IF_DEQUEUE(&sc->sc_fastq, m); if (m == NULL) break; m_freem(m); } while ((m = sc->sc_npqueue) != NULL) { sc->sc_npqueue = m->m_nextpkt; m_freem(m); } m_freem(sc->sc_togo); sc->sc_togo = NULL; #ifdef PPP_COMPRESS ppp_ccp_closed(sc); sc->sc_xc_state = NULL; sc->sc_rc_state = NULL; #endif /* PPP_COMPRESS */ #if NBPFILTER > 0 if (sc->sc_pass_filt.bf_insns != 0) { free(sc->sc_pass_filt.bf_insns, M_DEVBUF, 0); sc->sc_pass_filt.bf_insns = 0; sc->sc_pass_filt.bf_len = 0; } if (sc->sc_active_filt.bf_insns != 0) { free(sc->sc_active_filt.bf_insns, M_DEVBUF, 0); sc->sc_active_filt.bf_insns = 0; sc->sc_active_filt.bf_len = 0; } #endif #ifdef VJC if (sc->sc_comp != 0) { free(sc->sc_comp, M_DEVBUF, 0); sc->sc_comp = 0; } #endif }
/* * Ioctl routine for generic ppp devices. */ int pppioctl(struct ppp_softc *sc, u_long cmd, caddr_t data, int flag, struct ucred *cred) { int error, flags, mru, npx; u_int nb; struct ppp_option_data *odp; struct compressor **cp; struct npioctl *npi; time_t t; #ifdef PPP_FILTER struct bpf_program *bp, *nbp; struct bpf_insn *newcode, *oldcode; int newcodelen; #endif /* PPP_FILTER */ #ifdef PPP_COMPRESS u_char ccp_option[CCP_MAX_OPTION_LENGTH]; #endif switch (cmd) { case FIONREAD: *(int *)data = sc->sc_inq.ifq_len; break; case PPPIOCGUNIT: *(int *)data = sc->sc_if.if_dunit; break; case PPPIOCGFLAGS: *(u_int *)data = sc->sc_flags; break; case PPPIOCSFLAGS: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); flags = *(int *)data & SC_MASK; crit_enter(); #ifdef PPP_COMPRESS if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN)) ppp_ccp_closed(sc); #endif sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags; crit_exit(); break; case PPPIOCSMRU: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); mru = *(int *)data; if (mru >= PPP_MRU && mru <= PPP_MAXMRU) sc->sc_mru = mru; break; case PPPIOCGMRU: *(int *)data = sc->sc_mru; break; #ifdef VJC case PPPIOCSMAXCID: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); if (sc->sc_comp) { crit_enter(); sl_compress_init(sc->sc_comp, *(int *)data); crit_exit(); } break; #endif case PPPIOCXFERUNIT: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); sc->sc_xfer = curthread; break; #ifdef PPP_COMPRESS case PPPIOCSCOMPRESS: if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); odp = (struct ppp_option_data *) data; nb = odp->length; if (nb > sizeof(ccp_option)) nb = sizeof(ccp_option); if ((error = copyin(odp->ptr, ccp_option, nb)) != 0) return (error); if (ccp_option[1] < 2) /* preliminary check on the length byte */ return (EINVAL); for (cp = ppp_compressors; *cp != NULL; ++cp) if ((*cp)->compress_proto == ccp_option[0]) { /* * Found a handler for the protocol - try to allocate * a compressor or decompressor. */ error = 0; if (odp->transmit) { crit_enter(); if (sc->sc_xc_state != NULL) (*sc->sc_xcomp->comp_free)(sc->sc_xc_state); sc->sc_xcomp = *cp; sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb); if (sc->sc_xc_state == NULL) { if (sc->sc_flags & SC_DEBUG) kprintf("%s: comp_alloc failed\n", sc->sc_if.if_xname); error = ENOBUFS; } sc->sc_flags &= ~SC_COMP_RUN; crit_exit(); } else { crit_enter(); if (sc->sc_rc_state != NULL) (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state); sc->sc_rcomp = *cp; sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb); if (sc->sc_rc_state == NULL) { if (sc->sc_flags & SC_DEBUG) kprintf("%s: decomp_alloc failed\n", sc->sc_if.if_xname); error = ENOBUFS; } sc->sc_flags &= ~SC_DECOMP_RUN; crit_exit(); } return (error); } if (sc->sc_flags & SC_DEBUG) kprintf("%s: no compressor for [%x %x %x], %x\n", sc->sc_if.if_xname, ccp_option[0], ccp_option[1], ccp_option[2], nb); return (EINVAL); /* no handler found */ #endif /* PPP_COMPRESS */ case PPPIOCGNPMODE: case PPPIOCSNPMODE: npi = (struct npioctl *) data; switch (npi->protocol) { case PPP_IP: npx = NP_IP; break; default: return EINVAL; } if (cmd == PPPIOCGNPMODE) { npi->mode = sc->sc_npmode[npx]; } else { if ((error = priv_check_cred(cred, PRIV_ROOT, 0)) != 0) return (error); if (npi->mode != sc->sc_npmode[npx]) { crit_enter(); sc->sc_npmode[npx] = npi->mode; if (npi->mode != NPMODE_QUEUE) { ppp_requeue(sc); (*sc->sc_start)(sc); } crit_exit(); } } break; case PPPIOCGIDLE: crit_enter(); t = time_uptime; ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent; ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv; crit_exit(); break; #ifdef PPP_FILTER case PPPIOCSPASS: case PPPIOCSACTIVE: nbp = (struct bpf_program *) data; if ((unsigned) nbp->bf_len > BPF_MAXINSNS) return EINVAL; newcodelen = nbp->bf_len * sizeof(struct bpf_insn); if (newcodelen != 0) { newcode = kmalloc(newcodelen, M_DEVBUF, M_WAITOK); if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode, newcodelen)) != 0) { kfree(newcode, M_DEVBUF); return error; } if (!bpf_validate(newcode, nbp->bf_len)) { kfree(newcode, M_DEVBUF); return EINVAL; } } else newcode = NULL; bp = (cmd == PPPIOCSPASS)? &sc->sc_pass_filt: &sc->sc_active_filt; oldcode = bp->bf_insns; crit_enter(); bp->bf_len = nbp->bf_len; bp->bf_insns = newcode; crit_exit(); if (oldcode != NULL) kfree(oldcode, M_DEVBUF); break; #endif default: return (ENOIOCTL); } return (0); }
void tty_detached(struct ttys *ttyp, int exiting) { struct ttys *ttyp_tmp, *ttyp_last = 0; DEBUG_CALL("tty_detached"); DEBUG_ARG("ttyp = %lx", (long)ttyp); DEBUG_ARG("exiting = %d", exiting); /* First, remove ttyp from the queue */ if (ttyp == ttys) { ttys = ttys->next; } else { for (ttyp_tmp = ttys; ttyp_tmp; ttyp_tmp = ttyp_tmp->next) { if (ttyp_tmp == ttyp) break; ttyp_last = ttyp_tmp; } if (!ttyp_last) { /* XXX */ /* Can't find it *shrug* */ return; } ttyp_last->next = ttyp->next; } term_restore(ttyp); #ifdef FULL_BOLT fd_block(ttyp->fd); #endif /* Restore device mode */ if (ttyp->mode) fchmod(ttyp->fd, ttyp->mode); /* Bring the link down */ #ifdef USE_PPP /* * Call lcp_lowerdown if it's ppp */ if (ttyp->proto == PROTO_PPP) { lcp_lowerdown(ttyp->unit); phase = PHASE_DEAD; /* XXXXX */ } #endif /* * Kill the guardian, if it exists */ if (ttyp->pid) kill(ttyp->pid, SIGQUIT); /* * If this was the last tty and we're not restarting, exit */ if (!ttys && slirp_socket < 0 && !exiting) slirp_exit(0); close(ttyp->fd); if (ttyp->m) m_free(ttyp->m); /* * If this was the controlling tty, call ctty_detached */ if ((ttyp->flags & TTY_CTTY) && !exiting) ctty_detached(); #ifdef USE_PPP /* Deallocate compress data */ ppp_ccp_closed(ttyp); #endif ttys_unit[ttyp->unit] = 0; /* * If you love it, set it free() ... * If it comes back, we have a memory leak */ free(ttyp); detach_time = curtime; }