Ejemplo n.º 1
0
void dropdead(void)
{
    char switchifname[IFNAMSIZ] = {0};
    /* We're dying, so tidy up*/
    if (tRoot != NULL)
    {
        tdestroy(tRoot, free);
        tEntries = 0;
    }
    /* Restore interface flags*/
    while (0 > npd6getwan(switchifname))
    {
        sleep(1);
    }
    if_allmulti(switchifname, 0);
    if_allmulti(interfacestr, 0);

    close(sockicmp);
    close(sockpkt);

    flog(LOG_ERR, "Tidied up. Goodbye cruel world.");
    exit(0);
}
Ejemplo n.º 2
0
Archivo: util.c Proyecto: ju5t/npd6
void dropdead(void)
{
    int loop;
    
    /* We're dying, so tidy up*/
    /* Restore interface flags and close sockets */
    for (loop=0; loop<interfaceCount; loop++)
    {
        if_allmulti(interfaces[loop].nameStr, interfaces[loop].multiStatus);
        close( interfaces[loop].pktSock );
        close( interfaces[loop].icmpSock );
    }

    flog(LOG_ERR, "Tidied up and now exiting. Goodbye.");
    exit(0);
}
Ejemplo n.º 3
0
/*
 * Delete a mif from the mif table
 */
static int
del_m6if(mifi_t *mifip)
{
	struct mif6 *mifp = mif6table + *mifip;
	mifi_t mifi;
	struct ifnet *ifp;

	if (*mifip >= nummifs)
		return EINVAL;
	if (mifp->m6_ifp == NULL)
		return EINVAL;

	crit_enter();

	if (!(mifp->m6_flags & MIFF_REGISTER)) {
		/*
		 * XXX: what if there is yet IPv4 multicast daemon
		 *      using the interface?
		 */
		ifp = mifp->m6_ifp;

		if_allmulti(ifp, 0);
	}

#ifdef notyet
	bzero((caddr_t)qtable[*mifip], sizeof(qtable[*mifip]));
	bzero((caddr_t)mifp->m6_tbf, sizeof(*(mifp->m6_tbf)));
#endif
	bzero((caddr_t)mifp, sizeof (*mifp));

	/* Adjust nummifs down */
	for (mifi = nummifs; mifi > 0; mifi--)
		if (mif6table[mifi - 1].m6_ifp)
			break;
	nummifs = mifi;

	crit_exit();

#ifdef MRT6DEBUG
	if (mrt6debug)
		log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
#endif

	return 0;
}
Ejemplo n.º 4
0
/*
 * Delete a mif from the mif table
 */
static int
del_m6if_locked(mifi_t *mifip)
{
	struct mif6 *mifp = mif6table + *mifip;
	mifi_t mifi;
	struct ifnet *ifp;

	MIF6_LOCK_ASSERT();

	if (*mifip >= nummifs)
		return (EINVAL);
	if (mifp->m6_ifp == NULL)
		return (EINVAL);

	if (!(mifp->m6_flags & MIFF_REGISTER)) {
		/* XXX: TODO: Maintain an ALLMULTI refcount in struct ifnet. */
		ifp = mifp->m6_ifp;
		if_allmulti(ifp, 0);
	} else {
		if (reg_mif_num != (mifi_t)-1 &&
		    multicast_register_if6 != NULL) {
			if_detach(multicast_register_if6);
			if_free(multicast_register_if6);
			reg_mif_num = (mifi_t)-1;
			multicast_register_if6 = NULL;
		}
	}

	bzero((caddr_t)mifp, sizeof(*mifp));

	/* Adjust nummifs down */
	for (mifi = nummifs; mifi > 0; mifi--)
		if (mif6table[mifi - 1].m6_ifp)
			break;
	nummifs = mifi;
	MRT6_DLOG(DEBUG_ANY, "mif %d, nummifs %d", *mifip, nummifs);

	return (0);
}
Ejemplo n.º 5
0
/*
 * Add a mif to the mif table
 */
static int
add_m6if(struct mif6ctl *mifcp)
{
	struct mif6 *mifp;
	struct ifnet *ifp;
	int error;
#ifdef notyet
	struct tbf *m_tbf = tbftable + mifcp->mif6c_mifi;
#endif

	if (mifcp->mif6c_mifi >= MAXMIFS)
		return EINVAL;
	mifp = mif6table + mifcp->mif6c_mifi;
	if (mifp->m6_ifp)
		return EADDRINUSE; /* XXX: is it appropriate? */
	if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > if_index)
		return ENXIO;
	ifp = ifindex2ifnet[mifcp->mif6c_pifi];

	if (mifcp->mif6c_flags & MIFF_REGISTER) {
		if (reg_mif_num == (mifi_t)-1) {
			strlcpy(multicast_register_if.if_xname, "register_mif",
			    IFNAMSIZ);
			multicast_register_if.if_flags |= IFF_LOOPBACK;
			multicast_register_if.if_index = mifcp->mif6c_mifi;
			reg_mif_num = mifcp->mif6c_mifi;
		}

		ifp = &multicast_register_if;

	} /* if REGISTER */
	else {
		/* Make sure the interface supports multicast */
		if ((ifp->if_flags & IFF_MULTICAST) == 0)
			return EOPNOTSUPP;

		crit_enter();
		error = if_allmulti(ifp, 1);
		crit_exit();
		if (error)
			return error;
	}

	crit_enter();
	mifp->m6_flags     = mifcp->mif6c_flags;
	mifp->m6_ifp       = ifp;
#ifdef notyet
	/* scaling up here allows division by 1024 in critical code */
	mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000;
#endif
	/* initialize per mif pkt counters */
	mifp->m6_pkt_in    = 0;
	mifp->m6_pkt_out   = 0;
	mifp->m6_bytes_in  = 0;
	mifp->m6_bytes_out = 0;
	crit_exit();

	/* Adjust nummifs up if the mifi is higher than nummifs */
	if (nummifs <= mifcp->mif6c_mifi)
		nummifs = mifcp->mif6c_mifi + 1;

#ifdef MRT6DEBUG
	if (mrt6debug)
		log(LOG_DEBUG,
		    "add_mif #%d, phyint %s\n",
		    mifcp->mif6c_mifi,
		    ifp->if_xname);
#endif

	return 0;
}
Ejemplo n.º 6
0
/*
 * Add a mif to the mif table
 */
static int
add_m6if(struct mif6ctl *mifcp)
{
	struct mif6 *mifp;
	struct ifnet *ifp;
	int error;

	MIF6_LOCK();

	if (mifcp->mif6c_mifi >= MAXMIFS) {
		MIF6_UNLOCK();
		return (EINVAL);
	}
	mifp = mif6table + mifcp->mif6c_mifi;
	if (mifp->m6_ifp != NULL) {
		MIF6_UNLOCK();
		return (EADDRINUSE); /* XXX: is it appropriate? */
	}
	if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index) {
		MIF6_UNLOCK();
		return (ENXIO);
	}

	ifp = ifnet_byindex(mifcp->mif6c_pifi);

	if (mifcp->mif6c_flags & MIFF_REGISTER) {
		if (reg_mif_num == (mifi_t)-1) {
			ifp = if_alloc(IFT_OTHER);

			if_initname(ifp, "register_mif", 0);
			ifp->if_flags |= IFF_LOOPBACK;
			if_attach(ifp);
			multicast_register_if6 = ifp;
			reg_mif_num = mifcp->mif6c_mifi;
			/*
			 * it is impossible to guess the ifindex of the
			 * register interface.  So mif6c_pifi is automatically
			 * calculated.
			 */
			mifcp->mif6c_pifi = ifp->if_index;
		} else {
			ifp = multicast_register_if6;
		}
	} else {
		/* Make sure the interface supports multicast */
		if ((ifp->if_flags & IFF_MULTICAST) == 0) {
			MIF6_UNLOCK();
			return (EOPNOTSUPP);
		}

		error = if_allmulti(ifp, 1);
		if (error) {
			MIF6_UNLOCK();
			return (error);
		}
	}

	mifp->m6_flags     = mifcp->mif6c_flags;
	mifp->m6_ifp       = ifp;

	/* initialize per mif pkt counters */
	mifp->m6_pkt_in    = 0;
	mifp->m6_pkt_out   = 0;
	mifp->m6_bytes_in  = 0;
	mifp->m6_bytes_out = 0;

	/* Adjust nummifs up if the mifi is higher than nummifs */
	if (nummifs <= mifcp->mif6c_mifi)
		nummifs = mifcp->mif6c_mifi + 1;

	MIF6_UNLOCK();
	MRT6_DLOG(DEBUG_ANY, "mif #%d, phyint %s", mifcp->mif6c_mifi,
	    if_name(ifp));

	return (0);
}
Ejemplo n.º 7
0
/*
 * Disable IPv6 multicast forwarding.
 */
int
X_ip6_mrouter_done(void)
{
	mifi_t mifi;
	u_long i;
	struct mf6c *rt;
	struct rtdetq *rte;

	MROUTER6_LOCK();

	if (V_ip6_mrouter == NULL) {
		MROUTER6_UNLOCK();
		return (EINVAL);
	}

	/*
	 * For each phyint in use, disable promiscuous reception of all IPv6
	 * multicasts.
	 */
	for (mifi = 0; mifi < nummifs; mifi++) {
		if (mif6table[mifi].m6_ifp &&
		    !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
			if_allmulti(mif6table[mifi].m6_ifp, 0);
		}
	}
	bzero((caddr_t)mif6table, sizeof(mif6table));
	nummifs = 0;

	V_pim6 = 0; /* used to stub out/in pim specific code */

	callout_stop(&expire_upcalls_ch);

	/*
	 * Free all multicast forwarding cache entries.
	 */
	MFC6_LOCK();
	for (i = 0; i < MF6CTBLSIZ; i++) {
		rt = mf6ctable[i];
		while (rt) {
			struct mf6c *frt;

			for (rte = rt->mf6c_stall; rte != NULL; ) {
				struct rtdetq *n = rte->next;

				m_free(rte->m);
				free(rte, M_MRTABLE6);
				rte = n;
			}
			frt = rt;
			rt = rt->mf6c_next;
			free(frt, M_MRTABLE6);
		}
	}
	bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
	MFC6_UNLOCK();

	/*
	 * Reset register interface
	 */
	if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) {
		if_detach(multicast_register_if6);
		if_free(multicast_register_if6);
		reg_mif_num = (mifi_t)-1;
		multicast_register_if6 = NULL;
	}

	V_ip6_mrouter = NULL;
	V_ip6_mrouter_ver = 0;

	MROUTER6_UNLOCK();
	MRT6_DLOG(DEBUG_ANY, "finished");

	return (0);
}
Ejemplo n.º 8
0
/*
 * Apply routing function on the affected upstream and downstream prefixes,
 * i.e. either set or clear RTF_PROXY on the cloning prefix route; all route
 * entries that were cloned off these prefixes will be blown away.  Caller
 * must have acquried proxy6_lock and must not be holding nd6_mutex.
 */
static void
nd6_prproxy_prelist_setroute(boolean_t enable,
    struct nd6_prproxy_prelist_head *up_head,
    struct nd6_prproxy_prelist_head *down_head)
{
	struct nd6_prproxy_prelist *up, *down, *ndprl_tmp;
	struct nd_prefix *pr;

	lck_mtx_assert(&proxy6_lock, LCK_MTX_ASSERT_OWNED);
	lck_mtx_assert(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);

	SLIST_FOREACH_SAFE(up, up_head, ndprl_le, ndprl_tmp) {
		struct rtentry *rt;
		boolean_t prproxy, set_allmulti = FALSE;
		int allmulti_sw;
		struct ifnet *ifp = NULL;

		SLIST_REMOVE(up_head, up, nd6_prproxy_prelist, ndprl_le);
		pr = up->ndprl_pr;
		VERIFY(up->ndprl_up == NULL);

		NDPR_LOCK(pr);
		ifp = pr->ndpr_ifp;
		prproxy = (pr->ndpr_stateflags & NDPRF_PRPROXY);
		VERIFY(!prproxy || ((pr->ndpr_stateflags & NDPRF_ONLINK) &&
		    !(pr->ndpr_stateflags & NDPRF_IFSCOPE)));

		nd6_prproxy_sols_reap(pr);
		VERIFY(pr->ndpr_prproxy_sols_cnt == 0);
		VERIFY(RB_EMPTY(&pr->ndpr_prproxy_sols));

		if (enable && pr->ndpr_allmulti_cnt == 0) {
			nd6_prproxy++;
			pr->ndpr_allmulti_cnt++;
			set_allmulti = TRUE;
			allmulti_sw = TRUE;
		} else if (!enable && pr->ndpr_allmulti_cnt > 0) {
			nd6_prproxy--;
			pr->ndpr_allmulti_cnt--;
			set_allmulti = TRUE;
			allmulti_sw = FALSE;
		}

		if ((rt = pr->ndpr_rt) != NULL) {
			if ((enable && prproxy) || (!enable && !prproxy))
				RT_ADDREF(rt);
			else
				rt = NULL;
			NDPR_UNLOCK(pr);
		} else {
			NDPR_UNLOCK(pr);
		}

		/* Call the following ioctl after releasing NDPR lock */ 
		if (set_allmulti && ifp != NULL)
			if_allmulti(ifp, allmulti_sw);

		
		NDPR_REMREF(pr);
		if (rt != NULL) {
			rt_set_proxy(rt, enable);
			rtfree(rt);
		}
		nd6_ndprl_free(up);
	}

	SLIST_FOREACH_SAFE(down, down_head, ndprl_le, ndprl_tmp) {
		struct nd_prefix *pr_up;
		struct rtentry *rt;
		boolean_t prproxy, set_allmulti = FALSE;
		int allmulti_sw;
		struct ifnet *ifp = NULL;

		SLIST_REMOVE(down_head, down, nd6_prproxy_prelist, ndprl_le);
		pr = down->ndprl_pr;
		pr_up = down->ndprl_up;
		VERIFY(pr_up != NULL);

		NDPR_LOCK(pr_up);
		ifp = pr->ndpr_ifp;
		prproxy = (pr_up->ndpr_stateflags & NDPRF_PRPROXY);
		VERIFY(!prproxy || ((pr_up->ndpr_stateflags & NDPRF_ONLINK) &&
		    !(pr_up->ndpr_stateflags & NDPRF_IFSCOPE)));
		NDPR_UNLOCK(pr_up);

		NDPR_LOCK(pr);
		if (enable && pr->ndpr_allmulti_cnt == 0) {
			pr->ndpr_allmulti_cnt++;
			set_allmulti = TRUE;
			allmulti_sw = TRUE;
		} else if (!enable && pr->ndpr_allmulti_cnt > 0) {
			pr->ndpr_allmulti_cnt--;
			set_allmulti = TRUE;
			allmulti_sw = FALSE;
		}

		if ((rt = pr->ndpr_rt) != NULL) {
			if ((enable && prproxy) || (!enable && !prproxy))
				RT_ADDREF(rt);
			else
				rt = NULL;
			NDPR_UNLOCK(pr);
		} else {
			NDPR_UNLOCK(pr);
		}
		if (set_allmulti && ifp != NULL)
			if_allmulti(ifp, allmulti_sw);

		NDPR_REMREF(pr);
		NDPR_REMREF(pr_up);
		if (rt != NULL) {
			rt_set_proxy(rt, enable);
			rtfree(rt);
		}
		nd6_ndprl_free(down);
	}
}
Ejemplo n.º 9
0
int main(int argc, char *argv[])
{
    char logfile[FILENAME_MAX] = "";
    char switchifname[IFNAMSIZ] = {0};
    int c, err;
    int pid = 0;
    FILE *pidfp = NULL;

    // Default some globals
    strncpy(configfile, NPD6_CONF, FILENAME_MAX);
    strncpy( interfacestr, NULLSTR, sizeof(NULLSTR));
    memset( prefixaddrstr, 0, sizeof(prefixaddrstr));
    interfaceIdx = -1;
    daemonize = 0;
    // Default black/whitelisting to OFF
    listType = NOLIST;
    // Default config file values as required
    naLinkOptFlag = 0;
    nsIgnoreLocal = 1;
    naRouter = 1;
    debug = 0;
    maxHops = MAXMAXHOPS;

    /* Parse the args */
    while ((c = getopt_long(argc, argv, OPTIONS_STR, prog_opt, NULL)) > 0)
    {
        if (c==-1)
            break;

        switch (c) {
        case 'c':
            strcpy(configfile, optarg);
            break;
        case 'l':
            strcpy(logfile, optarg);
            break;
        case 'd':
            debug=1;
            break;
        case 'D':
            debug=2;
            break;
        case 'b':
            daemonize=1;
            break;
        case 'v':
            showVersion();
            return 0;
            break;
        case 'h':
            showUsage();
            return 0;
            break;
        }
    }
    
	/* Seems like about the right time to daemonize (or not) */
    if (daemonize)
    {
        if (daemon(0, 0) < 0 )
        {
            flog(LOG_ERR, "Failed to daemonize. Error: %s", strerror(errno) );
            exit(1);
        }
    }
	
	pid = getpid();
	if ((pidfp = fopen(NDP6PROXY_PIDFILE, "w")) != NULL) {
		fprintf(pidfp, "%d\n", pid);
		fclose(pidfp);
	}
    else
    {
        printf("**************** Open Pid file faild *********************** \r\n");
    }
	
    while (0 >= strlen(prefixaddrstr))
    {
        addr6match(NULL, NULL, 0);
        sleep(1);
    }
    /* Sort out where to log */
    if ( strlen(logfile) )
    {
        if (strlen(logfile) == 1 && (logfile[0]='-')  )
            logging = USE_STD;
        else
            logging = USE_FILE;
    }
    else
    {
        logging = USE_SYSLOG;
    }

    /* Open the log and config*/
    if ( (logging == USE_FILE) && (openLog(logfile) < 0)  )
    {
        printf("Exiting. Error in setting up logging correctly.\n");
        exit (1);
    }
    flog(LOG_INFO, "*********************** npd6 *****************************");

    if ( readConfig(configfile) )
    {
        flog(LOG_ERR, "Error in config file: %s", configfile);
        return 1;
    }

    flog(LOG_INFO, "Using normalised prefix %s/%d", prefixaddrstr, prefixaddrlen);
    flog(LOG_DEBUG2, "ifIndex for %s is: %d", interfacestr, interfaceIdx);

    err = init_sockets();
    if (err) {
        flog(LOG_ERR, "init_sockets: failed to initialise one or both sockets.");
        exit(1);
    }

    /* Set allmulti on the interface */
    while (0 > npd6getwan(switchifname))
    {
        sleep(1);
    }
    if_allmulti(switchifname, TRUE);
    if_allmulti(interfacestr, TRUE);
    /* Set up signal handlers */
    signal(SIGUSR1, usersignal);
    signal(SIGUSR2, usersignal);
    signal(SIGHUP, usersignal);
    signal(SIGINT, usersignal);
    signal(SIGTERM, usersignal);    // Typically used by init.d scripts

    /* And off we go... */
    dispatcher();

    flog(LOG_ERR, "Fell back out of dispatcher... This is impossible.");
    return 0;
}