예제 #1
0
/*
 * Make a new bundle or join us to an existing bundle
 * if we are doing multilink.
 */
int
mp_join_bundle()
{
	lcp_options *go = &lcp_gotoptions[0];
	lcp_options *ho = &lcp_hisoptions[0];
	lcp_options *ao = &lcp_allowoptions[0];
	int unit, pppd_pid;
	int l, mtu;
	char *p;
	TDB_DATA key, pid, rec;

	if (doing_multilink) {
		/* have previously joined a bundle */
		if (!go->neg_mrru || !ho->neg_mrru) {
			notice("oops, didn't get multilink on renegotiation");
			lcp_close(pcb, "multilink required");
			return 0;
		}
		/* XXX should check the peer_authname and ho->endpoint
		   are the same as previously */
		return 0;
	}

	if (!go->neg_mrru || !ho->neg_mrru) {
		/* not doing multilink */
		if (go->neg_mrru)
			notice("oops, multilink negotiated only for receive");
		mtu = ho->neg_mru? ho->mru: PPP_MRU;
		if (mtu > ao->mru)
			mtu = ao->mru;
		if (demand) {
			/* already have a bundle */
			cfg_bundle(0, 0, 0, 0);
			netif_set_mtu(pcb, mtu);
			return 0;
		}
		make_new_bundle(0, 0, 0, 0);
		set_ifunit(1);
		netif_set_mtu(pcb, mtu);
		return 0;
	}

	doing_multilink = 1;

	/*
	 * Find the appropriate bundle or join a new one.
	 * First we make up a name for the bundle.
	 * The length estimate is worst-case assuming every
	 * character has to be quoted.
	 */
	l = 4 * strlen(peer_authname) + 10;
	if (ho->neg_endpoint)
		l += 3 * ho->endpoint.length + 8;
	if (bundle_name)
		l += 3 * strlen(bundle_name) + 2;
	bundle_id = malloc(l);
	if (bundle_id == 0)
		novm("bundle identifier");

	p = bundle_id;
	p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname);
	if (ho->neg_endpoint || bundle_name)
		*p++ = '/';
	if (ho->neg_endpoint)
		p += slprintf(p, bundle_id+l-p, "%s",
			      epdisc_to_str(&ho->endpoint));
	if (bundle_name)
		p += slprintf(p, bundle_id+l-p, "/%v", bundle_name);

	/* Make the key for the list of links belonging to the bundle */
	l = p - bundle_id;
	blinks_id = malloc(l + 7);
	if (blinks_id == NULL)
		novm("bundle links key");
	slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7);

	/*
	 * For demand mode, we only need to configure the bundle
	 * and attach the link.
	 */
	mtu = LWIP_MIN(ho->mrru, ao->mru);
	if (demand) {
		cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf);
		netif_set_mtu(pcb, mtu);
		script_setenv("BUNDLE", bundle_id + 7, 1);
		return 0;
	}

	/*
	 * Check if the bundle ID is already in the database.
	 */
	unit = -1;
	lock_db();
	key.dptr = bundle_id;
	key.dsize = p - bundle_id;
	pid = tdb_fetch(pppdb, key);
	if (pid.dptr != NULL) {
		/* bundle ID exists, see if the pppd record exists */
		rec = tdb_fetch(pppdb, pid);
		if (rec.dptr != NULL && rec.dsize > 0) {
			/* make sure the string is null-terminated */
			rec.dptr[rec.dsize-1] = 0;
			/* parse the interface number */
			parse_num(rec.dptr, "IFNAME=ppp", &unit);
			/* check the pid value */
			if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid)
			    || !process_exists(pppd_pid)
			    || !owns_unit(pid, unit))
				unit = -1;
			free(rec.dptr);
		}
		free(pid.dptr);
	}

	if (unit >= 0) {
		/* attach to existing unit */
		if (bundle_attach(unit)) {
			set_ifunit(0);
			script_setenv("BUNDLE", bundle_id + 7, 0);
			make_bundle_links(1);
			unlock_db();
			info("Link attached to %s", ifname);
			return 1;
		}
		/* attach failed because bundle doesn't exist */
	}

	/* we have to make a new bundle */
	make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf);
	set_ifunit(1);
	netif_set_mtu(pcb, mtu);
	script_setenv("BUNDLE", bundle_id + 7, 1);
	make_bundle_links(pcb);
	unlock_db();
	info("New bundle %s created", ifname);
	multilink_master = 1;
	return 0;
}
예제 #2
0
/*
 * Make a new bundle or join us to an existing bundle
 * if we are doing multilink.
 */
int
mp_join_bundle()
{
    lcp_options *go = &lcp_gotoptions[0];
    lcp_options *ho = &lcp_hisoptions[0];
    int unit, pppd_pid;
    int l;
    char *p;
    TDB_DATA key, pid, rec;

    if (!go->neg_mrru || !ho->neg_mrru) {
        /* not doing multilink */
        if (go->neg_mrru)
            notice("oops, multilink negotiated only for receive");
        multilink = 0;
        if (demand) {
            /* already have a bundle */
            cfg_bundle(0, 0, 0, 0);
            return 0;
        }
        make_new_bundle(0, 0, 0, 0);
        set_ifunit(1);
        return 0;
    }

    /*
     * Find the appropriate bundle or join a new one.
     * First we make up a name for the bundle.
     * The length estimate is worst-case assuming every
     * character has to be quoted.
     *
     * Note - RFC 1990 requires that an unnegotiated endpoint
     * discriminator value be equivalent to negotiating with class
     * zero.  Do not test ho->neg_endpoint here.
     */
    l = 4 * strlen(peer_authname) + 10;
    l += 3 * ho->endpoint.length + 8;
    if (bundle_name)
        l += 3 * strlen(bundle_name) + 2;
    bundle_id = malloc(l);
    if (bundle_id == NULL)
        novm("bundle identifier");

    p = bundle_id;
    p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname);
    *p++ = '/';
    p += slprintf(p, bundle_id+l-p, "%s", epdisc_to_str(&ho->endpoint));
    if (bundle_name)
        p += slprintf(p, bundle_id+l-p, "/%v", bundle_name);
    dbglog("bundle_id = %s", bundle_id+7);

    /*
     * For demand mode, we only need to configure the bundle
     * and attach the link.
     */
    if (demand) {
        cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf);
        script_setenv("BUNDLE", bundle_id + 7, 1);
        return 0;
    }

    /*
     * Check if the bundle ID is already in the database.
     */
    unit = -1;
    tdb_writelock(pppdb);
    key.dptr = bundle_id;
    key.dsize = p - bundle_id;
    pid = tdb_fetch(pppdb, key);
    if (pid.dptr != NULL) {
        /* bundle ID exists, see if the pppd record exists */
        rec = tdb_fetch(pppdb, pid);
        if (rec.dptr != NULL) {
            /* it does, parse the interface number */
            parse_num(rec.dptr, "IFNAME=ppp", &unit);
            /* check the pid value */
            if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid)
                    || !process_exists(pppd_pid)
                    || !owns_unit(pid, unit))
                unit = -1;
            free(rec.dptr);
        }
        free(pid.dptr);
    }

    if (unit >= 0) {
        /* attach to existing unit */
        if (bundle_attach(unit)) {
            set_ifunit(0);
            script_setenv("BUNDLE", bundle_id + 7, 0);
            tdb_writeunlock(pppdb);
            info("Link attached to %s", ifname);
            return 1;
        }
        /* attach failed because bundle doesn't exist */
    }

    /* we have to make a new bundle */
    make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf);
    set_ifunit(1);
    script_setenv("BUNDLE", bundle_id + 7, 1);
    tdb_writeunlock(pppdb);
    info("New bundle %s created", ifname);
    return 0;
}