Ejemplo n.º 1
0
Archivo: if.c Proyecto: ayourtch/slirp
void if_init(void)
{
	/*
	 * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
	 * and 8 bytes for PPP, but need to have it on an 8byte boundary
	 */
#ifdef USE_PPP
	if_maxlinkhdr = 48;
#else
	if_maxlinkhdr = 40;
#endif
	if_mtu = 1500;
	if_mru = 1500;
	if_comp = IF_AUTOCOMP;
	if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
	if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
	sl_compress_init(&comp_s);
	next_m = &if_batchq;
}
Ejemplo n.º 2
0
/*
 * Allocate a ppp interface unit and initialize it.
 */
struct ppp_softc *
pppalloc(pid_t pid)
{
    int i;
    struct ppp_softc *sc;

    LIST_FOREACH(sc, &ppp_softc_list, sc_list)
	if (sc->sc_xfer == pid) {
	    sc->sc_xfer = 0;
	    return sc;
	}
    LIST_FOREACH(sc, &ppp_softc_list, sc_list)
	if (sc->sc_devp == NULL)
	    break;
    if (sc == NULL)
	return NULL;

    sc->sc_flags = 0;
    sc->sc_mru = PPP_MRU;
    sc->sc_relinq = NULL;
    bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
#ifdef VJC
    sc->sc_comp = malloc(sizeof(struct slcompress), M_DEVBUF, M_NOWAIT);
    if (sc->sc_comp)
	sl_compress_init(sc->sc_comp);
#endif
#ifdef PPP_COMPRESS
    sc->sc_xc_state = NULL;
    sc->sc_rc_state = NULL;
#endif /* PPP_COMPRESS */
    for (i = 0; i < NUM_NP; ++i)
	sc->sc_npmode[i] = NPMODE_ERROR;
    sc->sc_npqueue = NULL;
    sc->sc_npqtail = &sc->sc_npqueue;
    sc->sc_last_sent = sc->sc_last_recv = time_second;

    return sc;
}
Ejemplo n.º 3
0
/*
 * Allocate a ppp interface unit and initialize it.
 */
struct ppp_softc *
pppalloc(struct thread *td)
{
    int nppp, i;
    struct ppp_softc *sc;

    for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
        if (sc->sc_xfer == td) {
            sc->sc_xfer = NULL;
            return sc;
        }
    for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
        if (sc->sc_devp == NULL)
            break;
    if (nppp >= NPPP)
        return NULL;

    sc->sc_flags = 0;
    sc->sc_mru = PPP_MRU;
    sc->sc_relinq = NULL;
    bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
#ifdef VJC
    MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress),
           M_DEVBUF, M_WAITOK);
    sl_compress_init(sc->sc_comp, -1);
#endif
#ifdef PPP_COMPRESS
    sc->sc_xc_state = NULL;
    sc->sc_rc_state = NULL;
#endif /* PPP_COMPRESS */
    for (i = 0; i < NUM_NP; ++i)
        sc->sc_npmode[i] = NPMODE_ERROR;
    sc->sc_npqueue = NULL;
    sc->sc_npqtail = &sc->sc_npqueue;
    sc->sc_last_sent = sc->sc_last_recv = time_second;

    return sc;
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
/*
 * Receive a control message
 */
static int
ng_vjc_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
	const priv_p priv = NG_NODE_PRIVATE(node);
	struct ng_mesg *resp = NULL;
	int error = 0;
	struct ng_mesg *msg;

	NGI_GET_MSG(item, msg);
	/* Check type cookie */
	switch (msg->header.typecookie) {
	case NGM_VJC_COOKIE:
		switch (msg->header.cmd) {
		case NGM_VJC_SET_CONFIG:
		    {
			struct ngm_vjc_config *const c =
				(struct ngm_vjc_config *) msg->data;

			if (msg->header.arglen != sizeof(*c))
				ERROUT(EINVAL);
			if ((priv->conf.enableComp || priv->conf.enableDecomp)
			    && (c->enableComp || c->enableDecomp))
				ERROUT(EALREADY);
			if (c->enableComp) {
				if (c->maxChannel > NG_VJC_MAX_CHANNELS - 1
				    || c->maxChannel < NG_VJC_MIN_CHANNELS - 1)
					ERROUT(EINVAL);
			} else
				c->maxChannel = NG_VJC_MAX_CHANNELS - 1;
			if (c->enableComp != 0 || c->enableDecomp != 0) {
				bzero(&priv->slc, sizeof(priv->slc));
				sl_compress_init(&priv->slc, c->maxChannel);
			}
			priv->conf = *c;
			break;
		    }
		case NGM_VJC_GET_CONFIG:
		    {
			struct ngm_vjc_config *conf;

			NG_MKRESPONSE(resp, msg, sizeof(*conf), M_NOWAIT);
			if (resp == NULL)
				ERROUT(ENOMEM);
			conf = (struct ngm_vjc_config *)resp->data;
			*conf = priv->conf;
			break;
		    }
		case NGM_VJC_GET_STATE:
		    {
			const struct slcompress *const sl0 = &priv->slc;
			struct slcompress *sl;
			u_int16_t index;
			int i;

			/* Get response structure */
			NG_MKRESPONSE(resp, msg, sizeof(*sl), M_NOWAIT);
			if (resp == NULL)
				ERROUT(ENOMEM);
			sl = (struct slcompress *)resp->data;
			*sl = *sl0;

			/* Replace pointers with integer indicies */
			if (sl->last_cs != NULL) {
				index = sl0->last_cs - sl0->tstate;
				bzero(&sl->last_cs, sizeof(sl->last_cs));
				*((u_int16_t *)&sl->last_cs) = index;
			}
			for (i = 0; i < MAX_STATES; i++) {
				struct cstate *const cs = &sl->tstate[i];

				index = sl0->tstate[i].cs_next - sl0->tstate;
				bzero(&cs->cs_next, sizeof(cs->cs_next));
				*((u_int16_t *)&cs->cs_next) = index;
			}
			break;
		    }
		case NGM_VJC_CLR_STATS:
			priv->slc.sls_packets = 0;
			priv->slc.sls_compressed = 0;
			priv->slc.sls_searches = 0;
			priv->slc.sls_misses = 0;
			priv->slc.sls_uncompressedin = 0;
			priv->slc.sls_compressedin = 0;
			priv->slc.sls_errorin = 0;
			priv->slc.sls_tossed = 0;
			break;
		case NGM_VJC_RECV_ERROR:
			sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &priv->slc);
			break;
		default:
			error = EINVAL;
			break;
		}
		break;
	default:
		error = EINVAL;
		break;
	}
done:
	NG_RESPOND_MSG(error, node, item, resp);
	NG_FREE_MSG(msg);
	return (error);
}