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; }
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; }
/* * 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); }
/* * 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); }
/* * 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); }