in google_guest_agent/network/manager/dhclient_linux.go [180:235]
func (n *dhclient) SetupEthernetInterface(ctx context.Context, config *cfg.Sections, nics *Interfaces) error {
dhcpCommand := config.NetworkInterfaces.DHCPCommand
if dhcpCommand != "" {
tokens := strings.Split(dhcpCommand, " ")
return run.Quiet(ctx, tokens[0], tokens[1:]...)
}
// Get all interfaces separated by ipv4 and ipv6.
googleInterfaces, googleIpv6Interfaces := interfaceListsIpv4Ipv6(nics.EthernetInterfaces)
obtainIpv4Interfaces, obtainIpv6Interfaces, releaseIpv6Interfaces, err := partitionInterfaces(ctx, googleInterfaces, googleIpv6Interfaces)
if err != nil {
return fmt.Errorf("error partitioning interfaces: %v", err)
}
// Release IPv6 leases.
for _, iface := range releaseIpv6Interfaces {
if err := runDhclient(ctx, ipv6, iface, true); err != nil {
logger.Errorf("failed to run dhclient: %+x", err)
}
}
// Setup IPV4.
for _, iface := range obtainIpv4Interfaces {
if err := runDhclient(ctx, ipv4, iface, false); err != nil {
logger.Errorf("failed to run dhclient: %+x", err)
}
}
if len(obtainIpv6Interfaces) == 0 {
return nil
}
// Wait for tentative IPs to resolve as part of SLAAC for primary network interface.
tentative := []string{"-6", "-o", "a", "s", "dev", googleInterfaces[0], "scope", "link", "tentative"}
for i := 0; i < 5; i++ {
res := run.WithOutput(ctx, "ip", tentative...)
if res.ExitCode == 0 && res.StdOut == "" {
break
}
time.Sleep(1 * time.Second)
}
// Setup IPv6.
for _, iface := range obtainIpv6Interfaces {
// Set appropriate system values.
val := fmt.Sprintf("net.ipv6.conf.%s.accept_ra_rt_info_max_plen=128", iface)
if err := run.Quiet(ctx, "sysctl", val); err != nil {
return err
}
if err := runDhclient(ctx, ipv6, iface, false); err != nil {
logger.Errorf("failed to run dhclient: %+x", err)
}
}
return nil
}