Пример #1
0
/*
 * 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
}
Пример #2
0
/*
 * 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
}
Пример #3
0
/*
 * 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);
}
Пример #4
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;
}