Esempio n. 1
0
int dhcp ( struct net_device *netdev ) {
	uint8_t *chaddr;
	uint8_t hlen;
	uint16_t flags;
	int rc;

	/* Check we can open the interface first */
	if ( ( rc = ifopen ( netdev ) ) != 0 )
		return rc;

	/* Wait for link-up */
	if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 )
		return rc;

	/* Perform DHCP */
	chaddr = dhcp_chaddr ( netdev, &hlen, &flags );
	printf ( "DHCP (%s ", netdev->name );
	while ( hlen-- )
		printf ( "%02x%c", *(chaddr++), ( hlen ? ':' : ')' ) );

	if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) {
		rc = monojob_wait ( "" );
	} else if ( rc > 0 ) {
		printf ( " using cached\n" );
		rc = 0;
	}

	return rc;
}
Esempio n. 2
0
int dhcp ( struct net_device *netdev ) {
	int rc;

	/* Check we can open the interface first */
	if ( ( rc = ifopen ( netdev ) ) != 0 )
		return rc;

	/* Wait for link-up */
	if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 )
		return rc;

	/* Perform DHCP */
	printf ( "DHCP (%s %s)", netdev->name,
		 netdev->ll_protocol->ntoa ( netdev->ll_addr ) );
	if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 )
		rc = monojob_wait ( "" );

	return rc;
}
Esempio n. 3
0
/*
 * For wireless interface, we will try to find out available wireless
 * network; for wired, if dhcp should be used, start it now to try to
 * avoid delays there.
 *
 * For the real code, we should pass back the network information
 * gathered.  Note that the state engine will then use the llp to
 * determine which interface should be set up.
 *
 * ifs_lock is not held on entry.  The caller will cancel this thread and wait
 * for it to exit if the interface is to be deleted.
 */
static void *
gather_interface_info(void *arg)
{
	struct interface *i = arg;
	int retv;

	dprintf("Start gathering info for %s", i->if_name);

	switch (i->if_type) {
	case IF_WIRELESS:
		/* This generates EV_NEWAP when successful */
		retv = launch_wireless_scan(i->if_name);
		if (retv != 0)
			dprintf("didn't launch wireless scan: %s",
			    strerror(retv));
		break;
	case IF_WIRED:
		if (llp_get_ipv4src(i->if_name) == IPV4SRC_DHCP) {
			/*
			 * The following is to avoid locking up the state
			 * machine as it is currently the choke point.  We
			 * start dhcp with a wait time of 0; later, if we see
			 * the link go down (IFF_RUNNING is cleared), we will
			 * drop the attempt.
			 */
			if (is_startable(i))
				start_dhcp(i);
		}
		(void) np_queue_add_event(EV_LINKUP, i->if_name);
		break;
	}

	dprintf("Done gathering info for %s", i->if_name);
	i->if_thr = 0;
	return (NULL);
}
Esempio n. 4
0
/*
 * Process a received router advertisement.
 * Called both when packets arrive as well as when we send RAs.
 * In the latter case 'loopback' is set.
 */
void
incoming_ra(struct phyint *pi, struct nd_router_advert *ra, int len,
    struct sockaddr_in6 *from, boolean_t loopback)
{
	struct nd_opt_hdr *opt;
	int optlen;
	struct lifreq lifr;
	boolean_t set_needed = _B_FALSE;
	struct router *dr;
	uint16_t router_lifetime;
	uint_t reachable, retrans;
	boolean_t reachable_time_changed = _B_FALSE;
	boolean_t slla_opt_present	 = _B_FALSE;

	if (no_loopback && loopback)
		return;

	bzero(&lifr, sizeof (lifr));
	(void) strlcpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name));

	if (ra->nd_ra_curhoplimit != CURHOP_UNSPECIFIED &&
	    ra->nd_ra_curhoplimit != pi->pi_CurHopLimit) {
		pi->pi_CurHopLimit = ra->nd_ra_curhoplimit;
		lifr.lifr_ifinfo.lir_maxhops = pi->pi_CurHopLimit;
		set_needed = _B_TRUE;

		if (pi->pi_CurHopLimit < bad_hopcount_threshhold) {
			char abuf[INET6_ADDRSTRLEN];

			bad_hopcount_packets++;
			logmsg(LOG_ALERT,
			    "Low hopcount %d received on %s%s%s\n",
			    pi->pi_CurHopLimit, pi->pi_name,
			    bad_hopcount_record_addr ? " from " : "",
			    bad_hopcount_record_addr ?
			    inet_ntop(AF_INET6, &from->sin6_addr, abuf,
			    INET6_ADDRSTRLEN) : "");
		}
	}

	reachable = ntohl(ra->nd_ra_reachable);
	if (reachable != 0 &&
	    reachable != pi->pi_BaseReachableTime) {
		pi->pi_BaseReachableTime = reachable;
		reachable_time_changed = _B_TRUE;
	}

	if (pi->pi_reach_time_since_random < MIN_REACH_RANDOM_INTERVAL ||
	    reachable_time_changed) {
		phyint_reach_random(pi, _B_FALSE);
		set_needed = _B_TRUE;
	}
	lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime;

	retrans = ntohl(ra->nd_ra_retransmit);
	if (retrans != 0 &&
	    pi->pi_RetransTimer != retrans) {
		pi->pi_RetransTimer = retrans;
		lifr.lifr_ifinfo.lir_reachretrans = pi->pi_RetransTimer;
		set_needed = _B_TRUE;
	}

	if (set_needed) {
		if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) {
			logperror_pi(pi, "incoming_ra: SIOCSLIFLNKINFO");
			return;
		}
	}

	/*
	 * If the "managed" flag is set, then just assume that the "other" flag
	 * is set as well.  It's not legal to get addresses alone without
	 * getting other data.
	 */
	if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
		ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;

	/*
	 * If either the "managed" or "other" bits have turned on, then it's
	 * now time to invoke DHCP.  If only the "other" bit is set, then don't
	 * get addresses via DHCP; only "other" data.  If "managed" is set,
	 * then we must always get both addresses and "other" data.
	 */
	if (pi->pi_autoconf && pi->pi_stateful &&
	    (ra->nd_ra_flags_reserved & ~pi->pi_ra_flags &
	    (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))) {
		if (debug & D_DHCP) {
			logmsg(LOG_DEBUG,
			    "incoming_ra: trigger dhcp %s on %s\n",
			    (ra->nd_ra_flags_reserved & ~pi->pi_ra_flags &
			    ND_RA_FLAG_MANAGED) ? "MANAGED" : "OTHER",
			    pi->pi_name);
		}
		pi->pi_ra_flags |= ra->nd_ra_flags_reserved;
		start_dhcp(pi);
	}

	/* Skip default router code if sent from ourselves */
	if (!loopback) {
		/* Find and update or add default router in list */
		dr = router_lookup(pi, from->sin6_addr);
		router_lifetime = ntohs(ra->nd_ra_router_lifetime);
		if (dr == NULL) {
			if (router_lifetime != 0) {
				dr = router_create(pi, from->sin6_addr,
				    MILLISEC * router_lifetime);
				timer_schedule(dr->dr_lifetime);
			}
		} else {
			dr->dr_lifetime = MILLISEC * router_lifetime;
			if (dr->dr_lifetime != 0)
				timer_schedule(dr->dr_lifetime);
			if ((dr->dr_lifetime != 0 && !dr->dr_inkernel) ||
			    (dr->dr_lifetime == 0 && dr->dr_inkernel))
				router_update_k(dr);
		}
	}
	/* Process any options */
	len -= sizeof (struct nd_router_advert);
	opt = (struct nd_opt_hdr *)&ra[1];
	while (len >= sizeof (struct nd_opt_hdr)) {
		optlen = opt->nd_opt_len * 8;
		switch (opt->nd_opt_type) {
		case ND_OPT_PREFIX_INFORMATION:
			incoming_prefix_opt(pi, (uchar_t *)opt, from,
			    loopback);
			break;
		case ND_OPT_MTU:
			incoming_mtu_opt(pi, (uchar_t *)opt, from);
			break;
		case ND_OPT_SOURCE_LINKADDR:
			/* skip lla option if sent from ourselves! */
			if (!loopback) {
				incoming_lla_opt(pi, (uchar_t *)opt,
				    from, NDF_ISROUTER_ON);
				slla_opt_present = _B_TRUE;
			}
			break;
		default:
			break;
		}
		opt = (struct nd_opt_hdr *)((char *)opt + optlen);
		len -= optlen;
	}
	if (!loopback && !slla_opt_present)
		update_ra_flag(pi, from, NDF_ISROUTER_ON);
	/* Stop sending solicitations */
	check_to_solicit(pi, SOLICIT_DONE);
}
Esempio n. 5
0
/*
 * Returns SUCCESS if the interface is successfully brought up,
 * FAILURE if bringup fails, or WAITING if we'll need to wait on the GUI to run.
 * Called only in the main thread or a thread holding machine_lock.
 */
return_vals_t
bringupinterface(const char *ifname, const char *host, const char *ipv6addr,
    boolean_t ipv6onlink)
{
	struct interface *intf;

	intf = get_interface(ifname);
	if (intf == NULL) {
		syslog(LOG_ERR, "could not bring up interface %s: not in list",
		    ifname);
		return (FAILURE);
	}

	/* check current state; no point going on if flags are 0 */
	if ((intf->if_flags = get_ifflags(ifname, intf->if_family)) == 0) {
		dprintf("bringupinterface(%s): get_ifflags() returned 0",
		    ifname);
		return (FAILURE);
	}

	if (intf->if_type == IF_WIRELESS) {
		switch (handle_wireless_lan(ifname)) {
		case WAITING:
			intf->if_up_attempted = B_TRUE;
			return (WAITING);
		case FAILURE:
			syslog(LOG_INFO, "Could not connect to any WLAN, not "
			    "bringing %s up", ifname);
			return (FAILURE);
		}
	}
	intf->if_up_attempted = B_TRUE;

	/* physical level must now be up; bail out if not */
	intf->if_flags = get_ifflags(ifname, intf->if_family);
	if (!(intf->if_flags & IFF_RUNNING)) {
		dprintf("bringupinterface(%s): physical layer down", ifname);
		return (FAILURE);
	}

	/*
	 * If the link layer profile says that we want v6 then plumb it and
	 * bring it up; if there's a static address, configure it as well.
	 */
	if (ipv6onlink) {
		dprintf("bringupinterface: configuring ipv6");
		(void) start_child(IFCONFIG, ifname, "inet6", "plumb", "up",
		    NULL);
		if (ipv6addr) {
			(void) start_child(IFCONFIG, ifname, "inet6", "addif",
			    ipv6addr, "up", NULL);
		}
	}
	intf->if_v6onlink = ipv6onlink;

	if (strcmp(host, "dhcp") == 0) {
		start_dhcp(intf);
	} else {
		(void) start_child(IFCONFIG, ifname, host, NULL);
		(void) start_child(IFCONFIG, ifname, "up", NULL);
	}

	syslog(LOG_DEBUG, "brought up %s", ifname);

	return (SUCCESS);
}